Помощник тега asp-action не работает с атрибутом Route на контроллере

Я попытался сделать простую вещь. Я хотел иметь другое имя действия и другое имя метода:

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();
});

Итак, почему asp-action не работает, когда есть атрибут Route на всем контроллере


person Adam Jachocki    schedule 27.05.2020    source источник


Ответы (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)
{
}

Дополнительные сведения о маршрутизации см. В официальная документация.

person Prolog    schedule 11.11.2020