【发布时间】:2020-01-31 23:43:31
【问题描述】:
假设我有一个 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() 为第二个操作返回了一个空字符串,而它在第一个操作中运行良好。
在调试了一段时间后,我发现 blog post 将这个问题追溯到 ASP.NET Core 3.0 中的一个重大变化,其中 Async 后缀被 Url.Action() 以某种方式忽略了。
作者通过将字符串硬编码为操作名称(在我的例子中为"Action1" 和"Action2")解决了这个问题。他还上传了一些example code复制这种行为。
但是,我真的更愿意保留 nameof,以避免以后出现重命名/重构问题。
有没有一种干净的方法来使用nameof 或其他类型安全的构造来为Url.Action 函数提供带有Async 后缀的方法?
【问题讨论】:
-
您可以查看T4MVC(或R4MVC for Core)来生成强类型帮助器(参数)代码。
-
这与您的问题无关,但请避免在您的代码中使用
await Task.CompletedTask;这样的星座。请改用return Task.FromResult()。 -
@CodeCaster 感谢您的指点,这看起来很有希望!这也可能解决控制器名称属性的问题...
-
@MarcusWichelmann 好吧,这更多是尽可能简化示例的结果,但仍然感谢您的提示:)
标签: asp.net-core asp.net-core-mvc url-routing asp.net-core-3.0 nameof