4

我对 MVC 还是很陌生,很难弄清楚如何最好地解决这个问题。

我有一个自动脚手架"Create" (GET)操作的修改版本,它采用可选参数(下拉列表的默认值)。然后它将其表单提交给"Create" (HTTPPost)操作。

public ActionResult Create(string id = null)
{ 
    //use id to pick a default item in a drop down list.
}

[HttpPost]
public ActionResult Create(Registration registration)
{ 
    //this method doesn't care one iota what was passed to the GET method
    // but registration.id is invalid because it's trying to set it to the value that was passed to the get method.  If id in the get method is not passed, then everything is fine
}

问题是,如果将值传递给 GET 创建操作,则ModelState.isValid该操作为 false,POST create因为它试图将传递给 GET 操作的值填充到 POST 操作中模型的主键 (Id) 字段中(应该省略,因为它是自动生成的。

我知道我可以将主键列名更改为 Id 以外的名称,但我无法控制数据库,并且正在尝试找出解决此问题的另一种方法。

如果我尝试将 GET 操作上的参数从 'id' 重命名为其他名称,那么我必须将链接从 CREATE/paramValue to更改为CREATE/?paramName=paramValue我宁愿不这样做。(尽管如果这是唯一简单的方法,我会这样做)。

有没有办法让 POST 操作忽略传递给 GET 操作的值?

4

2 回答 2

3

我认为您要做的是使用它应该创建的对象类型的 ID 参数化控制器的 Create 方法。

虽然 ASP.NET MVC 中的参数名称没有硬性规定,但我认为大多数人希望调用的参数id引用正在处理的对象,而不是它的属性。

考虑到这一点,我对您的建议是执行以下操作:

  1. 将 Create 方法的 GET 版本中的参数重命名为合适的类型,例如 typeId 或其他名称,因此签名看起来像public ActionResult Create(string typeId = null)

  2. 向 中添加自定义路由MvcApplication,这将让您拥有良好的格式/Create/typeId,而不是强制拥有/Create?typeId=value

您可以通过在默认路由之前添加以下代码行来做到这一点:

routes.MapRoute
(
    name: "CreateGet",
    url: "Controller/Create/{typeId}",
    defaults: new
    {
        controller = "Controller",
        action = "Create",
        typeId = UrlParameter.Optional
    }
);

默认路由如下所示:

routes.MapRoute
(
    name: "Default",
    url: "{controller}/{action}/{id}",
    defaults: new
    {
        controller = "Site",
        action = "Index",
        id = UrlParameter.Optional
    }
);

我认为这将解决您的问题,但请确保我建议的自定义路线位于默认路线之前。

更新:

您有一个 Get 方法和一个 Post 方法。

Get 方法(可能)创建一个视图模型对象并将其发送到视图,视图呈现它。或者,您的视图可以在 HTML 中硬编码或通过 AJAX 调用注入各种输入。不管他们是如何到达那里的,你呈现给 Web 浏览器的视图看起来像这样:

<html>
<head />
<body>
<form>
<input id="Input1" ... />
<select id="Select1" ... />
</form>
</body>
</html>

上面是一个大大简化的 HTML 结构。

输入的 ID 与回发此页面时将创建的视图模型对象内的属性名称相匹配,即Registration类的实例。

在返回的途中(返回 Post 方法),模型绑定器从请求中获取值(查询字符串参数、表单值等)并将它们绑定回提供给 Post 方法的模型对象。

在您的情况下,最有可能发生的事情是idGet 方法(和呈现的视图)id中的含义与Registration提供给 Post 方法的对象中的含义不匹配。

不匹配的原因是Registration.Id属性名称是由数据库决定的,并且Create(string id)是由默认路由决定的,但它们实际上是不同的东西,所以应该命名不同。

这使得您需要有一个干净的 /Create/id 表单的 URL,这可以通过自定义路由轻松完成。

现在,如果您真的想从模型绑定逻辑中排除一个参数,那么您将使用另一个答案,它使用RegistrationPost 方法的参数上的属性来明确告诉DefaultModelBinder从绑定逻辑中排除该参数。

完成此操作后,在实例化和运行构造函数之后,它所绑定的属性将保留 CLR 赋予它的默认值。

ASP.NET MVC 还支持自定义模型绑定器,如果需要,它可以显着改变模型绑定逻辑,尽管这不适用于您的情况。

于 2013-01-22T21:44:07.160 回答
2

尝试使用BindAttribute

[HttpPost]
public ActionResult Create([Bind(Exclude = "RegistrationId")]Registration registration)
{ 

}

绑定到模型时,它将省略RegistrationIdPOSTed with 表单...

于 2013-01-22T21:21:26.543 回答