【问题标题】:asp-action tag helper doesn't work with Route attribute on controllerasp-action 标记助手不适用于控制器上的 Route 属性
【发布时间】:2020-09-14 12:43:10
【问题描述】:

我试着做一些简单的事情。我想要不同的动作名称和不同的方法名称:

public class SuperController: Controller
{
    [HttpGet("dosth")]
    public IActionResult DoSomethingWithThoseParameters(int id, string token)
    {
    }
}

看看控制器上没有Route属性。

在这种情况下,标签助手asp-action 可以完美运行。但是我以为我的动作dosth会放在:localhost/Super/dosth

但事实并非如此。所以我想我可能应该为整个控制器设置路由,如下所示:

[Route("[controller]")]
public class SuperController: Controller
{
    [HttpGet("dosth")]
    public IActionResult DoSomethingWithThoseParameters(int id, string token)
    {
    }

    public IActionResult Register()
    {
        return View();
    }
}

但是现在asp-action 停止工作了。例如:

<a asp-controller="Super" asp-action="Register">

创建锚点到:localhost/Super 而不是:localhost/Super/Register

当我从控制器中删除 Route 标记时,它再次起作用。

我的映射是按照标准配置的:

app.UseEndpoints(endpoints =>
{
    endpoints.MapControllerRoute(
        name: "default",
        pattern: "{controller=Home}/{action=Index}/{id?}");
    endpoints.MapRazorPages();
});

那么,当整个控制器上有Route 属性时,asp-action 怎么会不起作用

【问题讨论】:

    标签: .net-core-3.1 tag-helpers


    【解决方案1】:

    在控制器上应用[Route] 属性可为所有控制器方法启用属性路由。因此,通过这样做,你强迫自己为每种方法提供路径(以一种或另一种方式)。

    使用[Route("[controller]")],您的控制器操作的基本路由模板就是控制器名称,因此如果您有多个操作没有应用[Route][HttpGet](和其他HTTP 动词)属性:

    [Route("[controller]")]
    public class SuperController: Controller
    {
        public IActionResult DoSomethingWithThoseParameters(int id, string token)
        {
        }
    
        public IActionResult Register()
        {
            return View();
        }
    }
    

    ...你会得到一个AmbiguousMatchException,因为多个控制器操作将匹配相同的路由:

    /超级

    您可以为每个操作显式指定路由:

    [Route("[controller]")]
    public class SuperController: Controller
    {
        [HttpGet("dosth")]
        public IActionResult DoSomethingWithThoseParameters(int id, string token)
        {
        }
    
        [HttpGet("Register")]
        public IActionResult Register()
        {
            return View();
        }
    }
    

    或将动作名称指定为控制器级别的预期路由的一部分:

    [Route("[controller]/[action]")]
    public class SuperController : Controller
    {
        public IActionResult DoSomethingWithThoseParameters(int id, string token)
        {
        }
    
        public IActionResult Register()
        {
            return View();
        }
    }
    

    然后,您不必为操作指定路由,因为您在控制器级别应用了路由模板。您的操作将继承该路由模板。

    但是,请注意,要覆盖它,您必须将其全部覆盖,否则您将附加到路由模板。

    [HttpGet("/[controller]/dosth")]
    public IActionResult DoSomethingWithThoseParameters(int id, string token)
    {
    }
    

    official documentation 中阅读有关路由的更多信息。

    【讨论】:

      猜你喜欢
      • 2016-10-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-01-03
      • 2019-06-16
      • 1970-01-01
      • 2023-03-09
      • 1970-01-01
      相关资源
      最近更新 更多