如何将模型包含在 RedirectToAction 中?

在下面的 RedirectToAction中,我想传递一个 viewmodel。我如何将模型传递给重定向?

我设置了一个断点来检查模型的值,以验证模型是否正确创建。它是正确的,但是结果视图不包含在模型属性中找到的值。

//
// model created up here...
//
return RedirectToAction("actionName", "controllerName", model);

NET MVC 4 RC

99227 次浏览

RedirectToAction向客户端浏览器返回一个302响应,因此浏览器将向浏览器响应的位置标头值中的 URL 发出一个新的 GET 请求。

如果您试图将一个简单的瘦平视图模型传递给第二个操作方法,那么可以使用 RedirectToAction方法的 这个过载

protected internal RedirectToRouteResult RedirectToAction(
string actionName,
string controllerName,
object routeValues
)

RedirectToAction将把传递的对象(routeValue)转换为一个查询字符串,并将其附加到 url (由我们传递的前2个参数生成) ,并将生成的 url 嵌入到响应的 位置头中。

让我们假设您的视图模型是这样的

public class StoreVm
{
public int StoreId { get; set; }
public string Name { get; set; }
public string Code { set; get; }
}

在第一个 action 方法中,可以像这样将这个对象传递给 RedirectToAction方法

var m = new Store { StoreId =101, Name = "Kroger", Code = "KRO"};
return RedirectToAction("Details","Store", m);

此代码将向浏览器发送一个302响应,其位置标头值为

Store/Details?StoreId=101&Name=Kroger&Code=KRO

假设您的 Details操作方法的参数类型为 StoreVm,那么 querystring 参数值将被正确地映射到参数的属性。

public ActionResult Details(StoreVm model)
{
// model.Name & model.Id will have values mapped from the request querystring
// to do  : Return something.
}

以上内容适用于传递小型平面倾斜视图模型。但是如果您想传递一个复杂的对象,您应该尝试遵循 PRG 模式。

PRG 模式

PRG 代表 职位-重定向-走开。使用这种方法,您将在 querystring 中发出具有唯一 id 的重定向响应,第二个 GET 操作方法可以使用该方法再次查询资源并向视图返回一些内容。

int newStoreId=101;
return RedirectToAction("Details", "Store", new { storeId=newStoreId} );

这将创建 URL Store/Details?storeId=101 在 Details GET操作中,使用传入的 storeId,您将从某处(从服务或查询数据库等)获取/构建 StoreVm对象

public ActionResult Details(string storeId)
{
// from the storeId value, get the entity/object/resource
var store = yourRepo.GetStore(storeId);
if(store!=null)
{
// Map the the view model
var storeVm = new StoreVm { Id=storeId, Name=store.Name,Code=store.Code};
return View(storeVm);
}
return View("StoreNotFound"); // view to render when we get invalid store id
}

TempData

遵循 PRG 模式是处理这个用例的更好的解决方案。但是,如果您不想这样做,并且确实希望跨 无状态 HTTP请求传递一些复杂的数据,那么可以使用一些临时存储机制,如 TempData

TempData["NewCustomer"] = model;
return RedirectToAction("Index", "Users");

然后在 GET Action 方法中再次读取它。

public ActionResult Index()
{
var model=TempData["NewCustomer"] as Customer
return View(model);
}

TempData使用场景后面的 Session对象来存储数据。但是一旦数据被读取,数据就会被终止。

Rachel 写了一篇不错的博客 邮寄,解释了什么时候使用 TempData/ViewData。值得一读。

使用 TempData 将模型数据传递给 Asp.Net Core 中的重定向请求

在 Asp.Net 核心中,不能在 TempData 中传递复杂类型。您可以传递简单的类型,如 stringintGuid等。

如果您绝对希望通过 TempData 传递复杂类型对象,那么有两个选项。

1)将对象序列化为字符串并将其传递给。

下面是一个使用 Json.NET 将对象序列化为字符串的示例

var s = Newtonsoft.Json.JsonConvert.SerializeObject(createUserVm);
TempData["newuser"] = s;
return RedirectToAction("Index", "Users");

现在在 Index操作方法中,从 TempData 读取该值并将其反序列化为 CreateUserViewModel类对象。

public IActionResult Index()
{
if (TempData["newuser"] is string s)
{
var newUser = JsonConvert.DeserializeObject<CreateUserViewModel>(s);
// use newUser object now as needed
}
// to do : return something
}

2)将简单类型的字典设置为 TempData

var d = new Dictionary<string, string>
{
["FullName"] = rvm.FullName,
["Email"] = rvm.Email;
};
TempData["MyModelDict"] = d;
return RedirectToAction("Index", "Users");

然后再看

public IActionResult Index()
{
if (TempData["MyModelDict"] is Dictionary<string,string> dict)
{
var name = dict["Name"];
var email =  dict["Email"];
}
// to do : return something
}

另一种方法是将它存储在会话中。

var s = JsonConvert.SerializeObject(myView);
HttpContext.Session.SetString("myView", s);

然后拿回来

string s = HttpContext.Session.GetString("myView");
myView = JsonConvert.DeserializeObject<MyView>(s);