假设我有一个 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"
und )解决了这个问题。"Action2"
他还上传了一些重现此行为的示例代码。
但是,我真的更愿意保留nameof
, 以避免以后的重命名/重构问题。
是否有一种干净的方式来使用nameof
或其他类型安全的构造来为函数提供带有Async
后缀的方法Url.Action
?