C# 中方法命名的特殊问题
Peculiar problem with method naming in C#
我在 ASP.NET Core 中遇到了一个特殊问题。我有一个方法 returns 创建后的实体。
[HttpGet("{id}")]
public async Task<IActionResult> GetItemAsync(int id)
{
var entity = await _unitOfWork.UserRepository.FindByIdAsync(id);
if (entity == null)
return NotFound();
return Ok(entity);
}
[HttpPost]
public async Task<IActionResult> CreateUser(UserNewDto userNewDto)
{
if (ModelState.IsValid)
{
var entity = new User()
{
UserName = userNewDto.UserName,
FirstName = userNewDto.FirstName,
LastName = userNewDto.LastName,
Email = userNewDto.Email,
PhoneMobile = userNewDto.PhoneMobile,
Password = userNewDto.Password,
};
await _unitOfWork.UserRepository.AddAsync(entity);
await _unitOfWork.Complete();
return CreatedAtAction("GetItemAsync", new { entity.Id }, entity);
}
return new JsonResult("Something went wrong") { StatusCode = 500 };
}
CreateUser
方法应该在创建用户后重定向到 GetItemAsync
。相反,我收到一条错误消息
System.InvalidOperationException: No route matches the supplied values.
at Microsoft.AspNetCore.Mvc.CreatedAtActionResult.OnFormatting(ActionContext context)
at Microsoft.AspNetCore.Mvc.Infrastructure.ObjectResultExecutor.ExecuteAsyncCore(ActionContext context, ObjectResult result, Type objectType, Object value)
at Microsoft.AspNetCore.Mvc.Infrastructure.ObjectResultExecutor.ExecuteAsync(ActionContext context, ObjectResult result)
at Microsoft.AspNetCore.Mvc.ObjectResult.ExecuteResultAsync(ActionContext context)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.InvokeResultAsync(IActionResult result)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.ResultNext[TFilter,TFilterAsync](State& next, Scope& scope, Object& state, Boolean& isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.InvokeNextResultFilterAsync[TFilter,TFilterAsync]()
--- End of stack trace from previous location ---
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Rethrow(ResultExecutedContextSealed context)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.ResultNext[TFilter,TFilterAsync](State& next, Scope& scope, Object& state, Boolean& isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.InvokeResultFilters()
--- End of stack trace from previous location ---
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeFilterPipelineAsync>g__Awaited|20_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Awaited|17_0(ResourceInvoker invoker, Task task, IDisposable scope)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Awaited|17_0(ResourceInvoker invoker, Task task, IDisposable scope)
at Microsoft.AspNetCore.Routing.EndpointMiddleware.<Invoke>g__AwaitRequestTask|6_0(Endpoint endpoint, Task requestTask, ILogger logger)
at Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext context)
at Swashbuckle.AspNetCore.SwaggerUI.SwaggerUIMiddleware.Invoke(HttpContext httpContext)
at Swashbuckle.AspNetCore.Swagger.SwaggerMiddleware.Invoke(HttpContext httpContext, ISwaggerProvider swaggerProvider)
at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context)
如果我将方法名称从 GetItemAsync
更改为 GetItem
,重定向将按预期工作。我做错了什么?
这是 .net-core 3.0 中的一个问题。请参阅 Async suffix removal from controller action names:
In ASP.NET Core 3.0, ASP.NET Core MVC removes the Async suffix from
controller action names. Both routing and link generation are impacted
by this new default.
This change doesn't affect names specified using the [ActionName]
attribute. The default behavior can be disabled with the following
code in Startup.ConfigureServices:
services.AddMvc(options =>
options.SuppressAsyncSuffixInActionNames = false);
所以你可以:
- 用
[ActionName]
装饰你的动作:
[ActionName("GetItemAsync")]
[HttpGet("{id}")]
public async Task<IActionResult> GetItemAsync(int id)
- 或配置服务时设置
SuppressAsyncSuffixInActionNames = false
:
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers(options =>
options.SuppressAsyncSuffixInActionNames = false);
我在 ASP.NET Core 中遇到了一个特殊问题。我有一个方法 returns 创建后的实体。
[HttpGet("{id}")]
public async Task<IActionResult> GetItemAsync(int id)
{
var entity = await _unitOfWork.UserRepository.FindByIdAsync(id);
if (entity == null)
return NotFound();
return Ok(entity);
}
[HttpPost]
public async Task<IActionResult> CreateUser(UserNewDto userNewDto)
{
if (ModelState.IsValid)
{
var entity = new User()
{
UserName = userNewDto.UserName,
FirstName = userNewDto.FirstName,
LastName = userNewDto.LastName,
Email = userNewDto.Email,
PhoneMobile = userNewDto.PhoneMobile,
Password = userNewDto.Password,
};
await _unitOfWork.UserRepository.AddAsync(entity);
await _unitOfWork.Complete();
return CreatedAtAction("GetItemAsync", new { entity.Id }, entity);
}
return new JsonResult("Something went wrong") { StatusCode = 500 };
}
CreateUser
方法应该在创建用户后重定向到 GetItemAsync
。相反,我收到一条错误消息
System.InvalidOperationException: No route matches the supplied values.
at Microsoft.AspNetCore.Mvc.CreatedAtActionResult.OnFormatting(ActionContext context)
at Microsoft.AspNetCore.Mvc.Infrastructure.ObjectResultExecutor.ExecuteAsyncCore(ActionContext context, ObjectResult result, Type objectType, Object value)
at Microsoft.AspNetCore.Mvc.Infrastructure.ObjectResultExecutor.ExecuteAsync(ActionContext context, ObjectResult result)
at Microsoft.AspNetCore.Mvc.ObjectResult.ExecuteResultAsync(ActionContext context)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.InvokeResultAsync(IActionResult result)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.ResultNext[TFilter,TFilterAsync](State& next, Scope& scope, Object& state, Boolean& isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.InvokeNextResultFilterAsync[TFilter,TFilterAsync]()
--- End of stack trace from previous location ---
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Rethrow(ResultExecutedContextSealed context)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.ResultNext[TFilter,TFilterAsync](State& next, Scope& scope, Object& state, Boolean& isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.InvokeResultFilters()
--- End of stack trace from previous location ---
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeFilterPipelineAsync>g__Awaited|20_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Awaited|17_0(ResourceInvoker invoker, Task task, IDisposable scope)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Awaited|17_0(ResourceInvoker invoker, Task task, IDisposable scope)
at Microsoft.AspNetCore.Routing.EndpointMiddleware.<Invoke>g__AwaitRequestTask|6_0(Endpoint endpoint, Task requestTask, ILogger logger)
at Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext context)
at Swashbuckle.AspNetCore.SwaggerUI.SwaggerUIMiddleware.Invoke(HttpContext httpContext)
at Swashbuckle.AspNetCore.Swagger.SwaggerMiddleware.Invoke(HttpContext httpContext, ISwaggerProvider swaggerProvider)
at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context)
如果我将方法名称从 GetItemAsync
更改为 GetItem
,重定向将按预期工作。我做错了什么?
这是 .net-core 3.0 中的一个问题。请参阅 Async suffix removal from controller action names:
In ASP.NET Core 3.0, ASP.NET Core MVC removes the Async suffix from controller action names. Both routing and link generation are impacted by this new default.
This change doesn't affect names specified using the
[ActionName]
attribute. The default behavior can be disabled with the following code in Startup.ConfigureServices:services.AddMvc(options => options.SuppressAsyncSuffixInActionNames = false);
所以你可以:
- 用
[ActionName]
装饰你的动作:[ActionName("GetItemAsync")] [HttpGet("{id}")] public async Task<IActionResult> GetItemAsync(int id)
- 或配置服务时设置
SuppressAsyncSuffixInActionNames = false
:public void ConfigureServices(IServiceCollection services) { services.AddControllers(options => options.SuppressAsyncSuffixInActionNames = false);