HTTP GET请求中的MVC3模型绑定?
没有定制,我可以在MVC 3中做这样的事情吗?
[HttpGet] public ViewResult MyAction(ViewModel model) { // Do stuff return View("ViewName", model); }
我这样做的原因是作为工作流程的一部分在不同页面之间传递数据。 (即当用户在步骤1中查看所需内容时,将表单数据传递给第2步…)
只要您具有与Model类的Property name相同的参数Name,它就会起作用
假设你的class级是这样的
public class ViewModel { public string Name { set;get;} public string Loc{ set;get;} }
你可以这样做一个Get请求
MyAction?Name=jon&Loc=America
你能行的; 它会自动将查询字符串中的任何值绑定到具有匹配名称的属性。
也就是说,这不是通常做的事情; 它是[HttpPost]
方法,您可以看到执行的模型绑定,因为两个操作的接口需要以某种方式不同。 您可以通过回发到不同的操作名称来解决此问题,但您仍可能在模型的(部分)加载上触发模型validation错误,这对用户来说确实很混乱。
只有端点的方法签名中的类成员仅包含标量属性时,Shyju的答案才有效。 但是如果你有嵌套类呢? 我们假设您的ViewModel
类如下所示:
public class ViewModel { public string Name { get; set; } public string Title { get; set; } public Address MyAddress { get; set; } }
Address
类看起来像这样:
public class Address { public string Line1 { get; set; } public string Line2 { get; set; } }
现在让我们说GET请求是通过AJAX完成的,你在JavaScript中做了类似的事情:
var address = { Line1: "123 Nowhere St.", Line2: "Apt. B5" } var getRequestData = { Name: "Joe", Title: "Manager", MyAddress: address } var uriString = $.param(getRequestData); //the parameters for the GET request $.get("/ViewResult?" + uriString, function (data) { /*callback function*/ });
尽管JavaScript中address
对象的形状与端点方法签名中的C# Address
类完全匹配,但Line1
和Line2
子属性不会绑定。 他们的价值观将null
。
有两种解决方法。
解决方法1:
第一种是在命名GET请求中的参数而不是嵌套的JavaScript对象时使用点表示法。 使用此方法,AJAX中的GET请求数据如下所示:
var getRequestData = { Name: "Joe", Title: "Manager", MyAddress.Line1: "123 Nowhere St.", MyAddress.Line2: "Apt. B5" }
MVC模型绑定将知道如何执行此操作,只要所有属性名称都匹配(它们区分大小写,所以要小心)。
如果你没有使用AJAX,只提交一个简单的HTML表单,那就更容易了。 只需使用相同的点表示法命名输入元素。 使用诸如TextBoxFor()
类的辅助方法,Razor语法非常简单,但这是纯HTML中的一个示例:
解决方法2:
另一种方法是简单地使用POST请求而不是GET。 请注意,执行POST请求而不是实际更改服务器端的某些数据是技术上不好的做法,但这是一个选项。
您可以通过将PostMethod
属性设置为get来将表单发布到get。 如果表单的输入字段与任何接受的ViewModel
匹配,那么它们将被填充。 这些匹配由输入中的name
字段确定( – >
public string MatchedField { get; set; }
)。
你应该做的是从post传递表单,然后重定向到post post的get。 此模式是最佳实践,称为Post-Redirect-Get模式。
我会反对这种做法。 使用POST的最佳解决方案,因为如果您使用GET,一旦您从步骤3单击回到步骤2并且浏览器缓存不可用,您将对旧版本的ViewModel
执行操作。 你有没有想要使用GET的特殊原因?
我不能建议使用QueryString传递值。 您可以使用以下方法之一:此代码将呈现给定模型的局部视图。确保将视图添加到视图中。 您的视图应放在Shared
文件夹中
public ActionResult myaction(ViewModel model) { return PartialView("anotherView", model); }
另一种做同样事情的方法:
public ActionResult myaction(ViewModel model) { return View("someAnotherView", model); }
如果您的视图不在同一个控制器中,请使用视图名称的路径,如"../Controller/viewName"
还有一种不同的方法可以通过使用TempData来完成:
public ActionResult myaction(ViewModel model) { TempData["model"] = model; return RedirectToAction("someAnotherView"); }
但您应该使用如下所示的代码在视图中访问您的数据:
@{ ViewModel model=(ViewModel)TempData["model"]; }
希望上面的一个有帮助..
问候
对于Web API 2:
[HttpGet] public ActionResult Get([FromUri]ViewModel model) { // Do stuff return View("ViewName", model); }