Использование nameof () с методами Url.Action () и asyn c в ASP. NET Core 3.x MVC - PullRequest
2 голосов
/ 29 января 2020

Допустим, у меня есть приложение ASP. NET Core 3.0 MVC, которое имеет простой контроллер, содержащий два действия и использующий маршрутизацию на основе атрибутов:

[Route("home")]
public class HomeController : Controller
{
    public static string ControllerName { get; } = "Home";

    public HomeController()
    {
    }

    string GenerateUrls()
    {
        string url1 = Url.Action(nameof(Action1), ControllerName);
        string url2 = Url.Action(nameof(Action2Async), ControllerName);
        return $"Action1: '{url1}'\nAction2: '{url2}'";
    }

    [HttpGet("a1")]
    public IActionResult Action1()
    {
        return Ok(GenerateUrls());
    }

    [HttpGet("a2")]
    public async Task<IActionResult> Action2Async()
    {
        await Task.CompletedTask;

        return Ok(GenerateUrls());
    }
}

Поэтому вызов любого действия должен просто выдайте страницу с URL-адресами для обоих действий.

Открытие /home/a1 и /home/a2 правильно вызывает соответствующие действия, но вывод выглядит неожиданно:

Action1: '/home/a1'
Action2: ''

Это означает, что Url.Action() возвратил пустую строку для второго действия, хотя она отлично работала для первого действия.

После долгой отладки я обнаружил сообщение в блоге , отслеживающее это Самая проблема заключается в критическом изменении в ASP. NET Core 3.0, где суффикс Async каким-то образом игнорируется Url.Action().

Автор исправил эту проблему путем жесткого кодирования строк в качестве имен действий ("Action1" и "Action2" в моем случае). Он также загрузил пример кода , воспроизводящий это поведение.

Однако я бы действительно предпочел сохранить nameof, чтобы избежать последующих проблем с переименованием / рефакторингом.

Есть ли чистый способ использования nameof или других безопасных типов конструкций для предоставления метода с суффиксом Async для функции Url.Action?

Ответы [ 2 ]

2 голосов
/ 30 января 2020

Описанное поведение вызвано критическим изменением, введенным с ASP. NET Core 3.0.

Вы можете go вернуться к старому поведению, отключив SuppressAsyncSuffixInActionNames:

Получает или задает значение, определяющее, удалит ли MVC суффикс «Asyn c», применяемый к именам действий контроллера.

Отключить этот переключатель в вызове AddControllers при настройке служб приложения:

services.AddControllers(options => {
    options.SuppressAsyncSuffixInActionNames = false;
});

Более подробную информацию об этом изменении можно найти в официальном объявлении 1017 * и в документах 1019 *.

0 голосов
/ 29 января 2020

Если вы измените имя метода Action2Asyn c на Action2, проблема будет решена.

Из связанного сообщения блога :

In ASP. NET Core 3, если у вас есть методы Action с суффиксом Asyn c, но путь к маршруту, который не включает Asyn c, обращайтесь к ним без суффикса Asyn c при разрешении URL через URL-адрес, например, URL .action (). Похоже, это серьезное изменение по сравнению с ASP. NET Core 2.2, которое официально не задокументировано.

public static string ControllerName { get; } = "Home";

string GenerateUrls()
{
    string url1 = Url.Action(nameof(Action1), ControllerName);
    string url2 = Url.Action(nameof(Action2), ControllerName);
    return $"Action1: '{url1}'\nAction2: '{url2}'";
}

[HttpGet("action1")]
public IActionResult Action1()
{
    return Ok(GenerateUrls());
}

[HttpGet("action2")]
public async Task<IActionResult> Action2()
{
    await Task.CompletedTask;

    return Ok(GenerateUrls());
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...