首页 > 解决方案 > AttributeRouting 修复两个名为 Id 的参数

问题描述

所以我有一个使用默认值Route的项目

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

我刚刚遇到了 7 年前在MVC Pro 中描述的情况 提示:不要在路由中使用“id”URL 参数

他们拥有的解决方案非常棒,但此刻,我不想改变我的整个网站。我希望用Attribute Routing解决我的问题。

但是,我似乎无法让它工作,我收到了一个404 Error页面。(以防上面的链接不起作用,我将在此处详细描述代码)。

细节

在我的项目中,我使用ViewModels. 是ViewModel(非常简单地)定义为:

public class Foo {
    public int Id { get; set; }
    ...
}

BarController的如下:

public ActionResult Create(string id) {
    if (string.IsNullOrWhiteSpace(id)) {
        return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
    }
    ...
}

[HttpPost]
public ActionResult Create(string id, Foo viewModel) {
    if (string.IsNullOrWhiteSpace(id)) {
        return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
    }
    ...
}

错误

当我导航到 时/Bar/Create/abc123,我看到我的表格很好。但是,当我提交表单时,Model.IsValidfalse. 查看对象的Watch窗口this.ModelState,我发现错误消息说

值“abc123”对 ID 无效。

我认为这是因为模型绑定器试图绑定abc123到具有属性Id的对象。ViewModelintId

我试过的

到目前为止,这是我尝试在我的 上做的事情Controller

[Route("Bar/Create/{aid}", Name = "FooBarRouteName")]
public ActionResult Create(string aid) {
    if (string.IsNullOrWhiteSpace(aid)) {
        return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
    }
    ...
}

[HttpPost]
public ActionResult Create(string aid, Foo viewModel) {
    if (string.IsNullOrWhiteSpace(aid)) {
        return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
    }
    ...
}

现在的问题是当我导航到 时/Bar/Create/abc123,我得到一个404 Error页面,甚至无法尝试提交表单。

有人可以指出我正确的方向或找出我做错了什么吗?谢谢!

标签: c#asp.net-mvcasp.net-mvc-5asp.net-mvc-routingattributerouting

解决方案


首先确保在基于约定的路由之前启用属性路由,以避免路由冲突。

//Attribute routing
routes.MapMvcAttributeRoutes();

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

您缺少 POST 操作的路线。

如果使用属性路由,您必须装饰控制器上的所有操作

[HttpGet]
[Route("Bar/Create/{aid}", Name = "FooBarRouteName")] // GET Bar/Create/abc123
public ActionResult Create(string aid) {
    if (string.IsNullOrWhiteSpace(aid)) {
        return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
    }
    ...
}

[HttpPost]
[Route("Bar/Create/{aid}")] // POST Bar/Create/abc123
public ActionResult Create(string aid, Foo viewModel) {
    if (string.IsNullOrWhiteSpace(aid)) {
        return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
    }
    ...
}

推荐阅读