在我们将应用程序升级到 MVC3 之前,这条路线有效:
routes.MapRoute(
"Versioned API with Controller, ID, subentity",
"api/{version}/{controller}/{id}/{subentity}/",
new { controller = "API", action = "Index" },
new { id = @"\d+", subentity = "serviceitem|accessitem" }
),
我正在尝试通过 POST 到以下网址来访问此路由:
/api/1.0/items/3/serviceitem
我的 Controller 方法具有以下签名:
[ActionName("Index"), AcceptVerbs(HttpVerbs.Post)]
public ActionResult CreateServiceItem(int id)
当我尝试使用此方法时,出现以下错误:
The parameters dictionary contains a null entry for parameter 'id' of non-nullable type 'System.Int32' for method 'System.Web.Mvc.ActionResult CreateServiceItem(Int32)' in 'API.Controllers.ItemsController'. An optional parameter must be a reference type, a nullable type, or be declared as an optional parameter. Parameter name: parameters
mvc2 和 mvc3 之间是否存在某种语法变化?
编辑:更新信息!
我想我找到了罪魁祸首。我将一些 JSON 数据发布到 URL。我的 JSON 对象恰好如下所示:
{ Id: null, OtherProperty: 'foo' }
MVC3 使用 JSON 对象中的 ID,而不是 URL 中指定的 ID。此行为可以配置吗?
编辑2:可重现的示例:
我们在应用程序中使用 Ext,所以我的示例是使用 Ext,但我可以重现它,这是在我的/Views/Home/Index.aspx 中:
Ext.onReady(function() {
var w = new Ext.Window({
title: 'Hi there',
height: 400,
width: 400,
items: [
new Ext.Button({
text: 'Click me',
handler: function() {
var obj = {
Id: null,
Text: 'Hi there'
};
Ext.Ajax.request({
url: '/item/3/serviceitem',
method: 'POST',
jsonData: Ext.util.JSON.encode(obj),
headers: { 'Content-type': 'application/json' },
success: function(result, request) {
console.log(result);
},
failure: function(result, request) {
console.log(result);
}
});
}
})
]
});
w.show();
});
在我的 Global.asax 中,我有以下路线:
routes.MapRoute(
"Test",
"{controller}/{id}/{subentity}",
new { action = "Index" },
new { id = @"\d+", subentity = "serviceitem" }
);
在我的/Controllers/ItemController 中,我有这个方法:
[ActionName("Index")]
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult CreateServiceItem(int id)
{
string data;
using (StreamReader sr = new StreamReader(Request.InputStream))
{
data = sr.ReadToEnd();
}
return Json(new
{
DT = DateTime.Now,
Id = id,
PostedData = data
});
}
当我点击按钮,导致使用指定的 JSON 数据向 Controller 发送 POST 时,我得到与上面相同的错误。如果我不发送 JSON 数据,它就会起作用(因为 MVC 将使用 URL 部分作为我的方法的参数)。
这是我的重现解决方案的链接:http://www.mediafire.com/?77881176saodnxp
最佳答案
不,这方面没有任何改变。我喜欢将此类问题称为“状态无法重现”。
步骤:
- 使用默认模板创建新的 ASP.NET MVC 3 项目
将
ItemsController
添加到项目中:public class ItemsController : Controller { [ActionName("Index")] [AcceptVerbs(HttpVerbs.Post)] public ActionResult CreateServiceItem(int id) { return Content(id.ToString()); } }
修改
Application_Start
中的路由注册,使其如下所示:public static void RegisterRoutes(RouteCollection routes) { routes.IgnoreRoute("{resource}.axd/{*pathInfo}"); routes.MapRoute( "Versioned API with Controller, ID, subentity", "api/{version}/{controller}/{id}/{subentity}", new { controller = "API", action = "Index" }, new { id = @"\d+", subentity = "serviceitem|accessitem" } ); routes.MapRoute( "Default", "{controller}/{action}/{id}", new { controller = "Home", action = "Index", id = UrlParameter.Optional } ); }
修改
~/Views/Home/Index.cshtml
View ,使其如下所示:<script type="text/javascript"> $.ajax({ url: '/api/1.0/items/3/serviceitem', type: 'POST', success: function (result) { alert(result); } }); </script>
点击F5运行项目
正如预期的那样,默认浏览器启动,AJAX 请求被发送到
Items
Controller 的CreateServiceItem
操作,该操作返回 id=3 字符串,它是这个收到警报的字符串。
结论:要么你没有显示你的实际代码,要么问题出在你的电视上。
更新:
现在您已经发布了一个可重现的示例,我知道问题是什么以及它与我的测试用例有何不同。在我的测试用例中,我执行了如下请求:
$.ajax({
url: 'item/3/serviceitem',
type: 'POST',
contentType: 'application/json',
data: JSON.stringify({ model: { id: null, text: 'Hi there' } }),
success: function (result) {
console.log(result);
}
});
在您的请求中,您正在执行以下操作:
$.ajax({
url: 'item/3/serviceitem',
type: 'POST',
contentType: 'application/json',
data: JSON.stringify({ id: null, text: 'Hi there' }),
success: function (result) {
console.log(result);
}
});
不再有模型名称变量。因此,当您尝试调用以下 Controller 操作时会发生冲突:
public ActionResult CreateServiceItem(int id)
如果模型未包装在请求中的正确对象中,则模型绑定(bind)器首先从 POST 请求中选取值,因为它的优先级高于 url 的值。这就是模型绑定(bind)器的工作方式:它首先查找已发布的数据。在 ASP.NET MVC 2 中,这工作正常,因为没有 JsonValueProviderFactory,因此 POST 请求中没有 id 参数。在 ASP.NET MVC 3 中引入了这一点,现在它有了值(value)。
我建议您的解决方法是将 JSON 包装在另一个对象中。
关于asp.net-mvc-3 - MVC3 下的路由损坏,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7854934/