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

ASP.NET Attribute Routes and default routes can work together?

我有一个用 NET Core 2.1 编写的项目,其中有一堆 Controller/Actions,上面有属性路由。 类似于:

[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 工作...如果我只是注释掉控制器中的属性,默认路由就会发生。

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

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

如果你想让属性路由使用/products那么你可以改变它:

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

但您不能将两种类型的路线用于同一 controller/action

我知道的唯一解决方法是您可以创建另一个继承自具有属性路由的控制器的控制器(使操作方法成为虚拟的)。然后您可以使用新的子 classed 控制器离开属性路由,您可以使用常规路由路由到它并只调用基本 class 操作方法。

示例:

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,而基本控制器使用属性路由。

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

详细:

如果您将 RouteAttribute 应用于控制器或操作方法,则该 controller/action 方法将仅响应指定的路由。在您给出的那个特定示例中,它只会在您浏览到 /~test/65.

时执行

如果您希望 controller/action 方法默认使用名称,请尝试使用 [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)
    {
        ...
    }
}

你也可以试试小乔试过的建议,也是一种方法。但最后你可以微调你的路线,如果你愿意,可以在一个控制器或动作上有多个路线。自己尝试和试验,但请查看文档以获取更多信息。

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