ASP.NET属性路由和默认路由可以一起使用吗?

时间:2018-07-04 13:18:23

标签: c# asp.net-core asp.net-core-mvc asp.net-core-routing

我有一个用NET Core 2.1编写的项目,其中有一堆带有属性路由的Controller / Action。 像这样:

[Route("~/test")]
public class ProductsController : Controller
{
    [HttpGet("{id:int}")]
    public IActionResult ById(int id)
    {
        ...
    }
}

在启动时,我只是默认值:

app.UseMvc(routeBuilder =>
{
    routeBuilder.MapRoute(
        name: "default",
        template: "{controller=Home}/{action=Index}/{id?}");
});

因此,应用程序正在按预期方式解析/test/42,但是没有办法使/products/byid?id=42工作...如果我只是从控制器中注释掉属性,则会发生默认路由。

有没有办法让他们一起工作?

2 个答案:

答案 0 :(得分:2)

简而言之:将其更改为[Route("/products")],然后重试。

详细信息:

如果将RouteAttribute应用于控制器或操作方法,则该控制器/操作方法将仅响应该指定的路由。在该示例中,您给出的内容只有在浏览到/~test/65时才会执行。

如果您希望控制器/操作方法默认使用名称,请尝试使用[controller][action]标志,如下所示:

[Route("[controller]")]
public class ProductsController : Controller
{
    [HttpGet("[action]/{id:int}")] // /Products/ById/5
    public IActionResult ById(int id)
    {
        ...
    }
}

您的ASP.NET Core中的默认路由是如果没有控制器点击您指定的路由,MVC将回退的路由。在这种情况下,/Products/ById/5也会起作用。

默认情况下,它映射到Home控制器和Index操作方法,这是您的默认主页。如果路由仅是/,则将执行该操作。

您还可以执行此操作以仅直接指定所需的路线

[Route("/api/products")]
public class ProductsController : Controller
{
    [HttpGet("by-id/{id:int}")] // /api/products/by-id/5
    public IActionResult ById(int id)
    {
        ...
    }
}

您也可以尝试Joe尝试过的建议,因为它也是一种方法。但最后,您可以微调路线,并且可以根据需要在一个控制器或一个动作上具有多个路线。尝试尝试一下,但请查看文档以了解更多信息。

很可能您不想修改默认路由,并根据自己的喜好调整RouteAttribute。在我提供的链接中了解attribute routingrouting to controller actions using app.UseMvc()

答案 1 :(得分:1)

您可以在同一应用程序中同时使用属性路由和常规路由。但是,一旦用属性路由标记了控制器或动作,就根本无法使用常规路由将其路由到该控制器或动作。您仍然可以将常规路由用于其他控制器。

如果您希望属性路由使用/ products,则可以对其进行更改:

[Route("~/products")]
public class ProductsController : Controller
{
    [HttpGet("{id:int}")]
    public IActionResult ById(int id)
    {
        ...
    }
}

但是您不能将两种类型的路由用于同一控制器/操作

我知道的唯一解决方法是,您可以创建另一个从具有属性路由的控制器继承的控制器(将操作方法​​设为虚拟)。然后,您可以使用新的子类控制器来取消属性路由,而可以使用常规路由来路由到它,而只需调用基类操作方法即可。

示例:

namespace MyNamespace
{
    public class ProductsController : Controller
    {
        [HttpGet("{id:int}")]
        public virtual IActionResult ById(int id)
        {
            ...
        }
    }
}

namespace MyOtherNamespace
{

    public class ProductsController : MyNamespace.ProductsController
    {

        public override IActionResult ById(int id)
        {
            base.ById(id);
        }
    }
}

现在,您可以使用常规路由将路由路由到ProductsController,而基本控制器使用属性路由。