如何使用RedirectToAction包含模型?

use*_*655 54 asp.net-mvc

RedirectToAction下面,我想通过一个viewmodel.如何将模型传递给重定向?

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

//
// model created up here...
//
return RedirectToAction("actionName", "controllerName", model);
Run Code Online (Sandbox Code Playgroud)

ASP.NET MVC 4 RC

Shy*_*yju 97

RedirectToAction 向客户端浏览器返回302响应,因此浏览器将对响应的位置标头值中的url发出新的GET请求来到浏览器.

如果你想通过一个简单的贫平面视图模式到第二操作方法,您可以使用此重载的的RedirectToAction方法.

protected internal RedirectToRouteResult RedirectToAction(
    string actionName,
    string controllerName,
    object routeValues
)
Run Code Online (Sandbox Code Playgroud)

RedirectToAction将对象传递(routeValues)转换成一个查询字符串和它添加到URL,并且将嵌入结果URL中(从我们通过第一2个参数生成)位置的响应的报头中.

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

public class StoreVm
{
    public int StoreId { get; set; }
    public string Name { get; set; }
    public string Code { set; get; } 
}
Run Code Online (Sandbox Code Playgroud)

而你在第一个动作方法中,你可以将这个对象传递给这样的RedirectToAction方法

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

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

Store/Details?StoreId=101&Name=Kroger&Code=KRO
Run Code Online (Sandbox Code Playgroud)

假设您的Detailsaction方法的参数是类型StoreVm,则查询字符串参数值将正确映射到参数的属性.

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

以上将适用于传递小平视图模型.但是如果你想传递一个复杂的对象,你应该尝试遵循PRG模式.

PRG模式

PRG代表POST - REDIRECT - GET.使用此方法,您将在查询字符串中发出具有唯一ID的重定向响应,使用该响应,第二个GET操作方法可以再次查询资源并将某些内容返回到视图.

int newStoreId=101;
return RedirectToAction("Details", "Store", new { storeId=newStoreId} );
Run Code Online (Sandbox Code Playgroud)

这将创建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
}
Run Code Online (Sandbox Code Playgroud)

TempData的

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

TempData["NewCustomer"] = model;
return RedirectToAction("Index", "Users");
Run Code Online (Sandbox Code Playgroud)

GET再次在Action方法中阅读它.

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

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

Rachel写了一篇很好的博客文章,解释何时使用TempData/ViewData.值得一读.

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

在Asp.Net核心中,您无法在TempData中传递复杂类型.你可以通过简单的类型,如string,int,Guid等.

如果您绝对想通过TempData传递复杂类型对象,则有2个选项.

1)将对象序列化为字符串并传递它.

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

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

现在在您的Indexaction方法中,从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
}
Run Code Online (Sandbox Code Playgroud)

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

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

并稍后阅读

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