ASP.NET MVC 3 Gotcha(Bug?):GET和POST的不同参数绑定优先级

时间:2011-01-12 22:47:55

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

鉴于这条路线:

routes.MapRoute("home", "{action}/{id}",
  new { controller = "home", action = "index", id = UrlParameter.Optional });

......而且这个动作:

public ActionResult Hi(string id) {
   return Content("hello, id: " + id);
}

问题#1 回复是什么:

GET http://localhost:2247/hi/7?id=55 HTTP/1.1

问题#2 回复是什么:

POST http://localhost:2247/hi/7?id=55 HTTP/1.1
Content-Length: 4
Content-Type: application/x-www-form-urlencoded

id=3

<小时/> 我相信这是一个错误,路由值应该始终具有优先权,因为URL是标识资源的。如果您编写POST,PUT或DELETE操作,您希望ID来自URL,而不是来自请求正文。这可能会导致对不同资源的更改,并可被恶意用户利用。
在做了一些研究后发现问题是默认的ValueProviderFactory注册顺序,其中FormValueProviderFactory位于RouteDataValueProviderFactory之前。我没有搞乱订单,而是创建了一个CustomModelBinderAttribute:

[AttributeUsage(AttributeTargets.Parameter)]
public sealed class FromRouteAttribute : CustomModelBinderAttribute, IModelBinder {

   public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext) {

      bindingContext.ValueProvider = new RouteDataValueProvider(controllerContext);

      return ModelBinders.Binders.DefaultBinder.BindModel(controllerContext, bindingContext);
   }

   public override IModelBinder GetBinder() {
      return this;
   }
}

......你可以这样使用:

public ActionResult Hi([FromRoute]string id) {
   return Content("hello, id: " + id);
}

2 个答案:

答案 0 :(得分:6)

在ASP.NET MVC 3 RC2中:

  • GET :回复:你好,id:7
  • POST :回复:你好,id:3

以下是测试视图:

<a href="/hi/7?id=55">GET</a>
<form action="/hi/7?id=55" method="POST">
    <input type="hidden" name="id" value="3" />
    <input type="submit" value="POST" />
</form>

所以这是评估优先顺序:

  1. POST正文参数
  2. 路线
  3. 查询字符串参数
  4. 顺便说一下,使用ASP.NET MVC 2.0可以获得完全相同的结果。

答案 1 :(得分:1)

我猜想,对于GET,响应将是“Hello 7”,而POST将是“Hello 3”。