HTTP GET请求中的MVC3模型绑定?

时间:2012-08-15 19:27:41

标签: c# asp.net-mvc-3

如果没有自定义,我可以在MVC 3中做这样的事情吗?

    [HttpGet]
    public ViewResult MyAction(ViewModel model)
    {
        // Do stuff
        return View("ViewName", model);
    }

我这样做的原因是在不同页面之间传递数据作为工作流程的一部分。 (即,当用户了解步骤1中所需的内容时,将表单数据传递给第2步...)

7 个答案:

答案 0 :(得分:8)

只要您具有与Model类的属性名称相同的参数名称

,它就会起作用

假设你的班级是这样的

public class ViewModel
{
  public string Name { set;get;}
  public string Loc{ set;get;}
}

你可以像这样做一个Get请求

MyAction?Name=jon&Loc=America

答案 1 :(得分:1)

你可以做到;它会自动将查询字符串中的任何值绑定到具有匹配名称的属性。

那就是说,这不是通常做的事情;它是[HttpPost]方法,您可以看到执行的模型绑定,因为两个操作的接口需要以某种方式不同。您可以通过回发到不同的操作名称来解决这个问题,但是您仍然可能在模型的(部分)加载上触发模型验证错误,这对用户来说确实很混乱。

答案 2 :(得分:1)

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类完全匹配,但Line1Line2子属性将< strong> 绑定。他们的价值观将以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中的一个例子:

<form method="get" action="/ViewResult">
  <input type="text" name="Name" />
  <input type="text" name="Title" />
  <input type="text" name="MyAddress.Line1" />
  <input type="text" name="MyAddress.Line2" />
  <button type="submit">Submit GET request</button>
</form>

解决方法2:

另一种方法是简单地使用POST请求而不是GET。请注意,执行POST请求而不是实际更改服务器端的某些数据是技术上不好的做法,但这是一个选项。

答案 3 :(得分:0)

您可以通过将PostMethod属性设置为get来将表单发布到get。如果表单的输入字段与任何接受ViewModel匹配,那么它们将被填充。这些匹配由输入中的name字段确定(<input name="MatchedField"> - &gt; public string MatchedField { get; set; })。

您应该做的是从帖子中传递表单,然后从帖子操作重定向到get。此模式是最佳实践,称为Post-Redirect-Get模式。

答案 4 :(得分:0)

我会反对这种做法。只使用POST的最佳解决方案,因为如果您使用GET,一旦您从步骤3单击回到步骤2并且浏览器缓存不可用,您将对旧版ViewModel执行操作。您是否有特殊原因要使用GET?

答案 5 :(得分:0)

我无法建议使用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"];

    }

希望上面的一个有帮助..

此致

答案 6 :(得分:0)

对于Web API 2:

[HttpGet]
public ActionResult Get([FromUri]ViewModel model)
{
    // Do stuff
    return View("ViewName", model);
}