常规路由不反序列化 json 正文请求(ASP.NET 核心 API)
Conventional Routing doesn't deserialize json body requests (ASP.NET Core API)
问题
在控制器和操作上使用 ApiControllerAttribute 和 RouteAttribute,一切正常。
当我更改代码以使用传统路由时,请求中的标识 属性 始终设置为空。
带有 ApiControllerAttribute 的代码(请求中加载的标识)
[ApiController]
[Route("api/[controller]")]
Public Class Main : ControllerBase
{
[HttpPost(nameof(GetExternalRemoteExternal))]
public async Task<GetByIdentityResponse<RemoteExternal>> GetExternalRemoteExternal(GetByIdentityRequest<RemoteExternalIdentity> request)
{
return await GetExternal<RemoteExternal, RemoteExternalIdentity>(request);
}
}
startup.cs
app.UseEndpoints(endpoints => endpoints.MapControllers());
具有常规路由的代码(请求具有空标识)
Public Class Main : ControllerBase
{
[HttpPost]
public async Task<GetByIdentityResponse<RemoteExternal>> GetExternalRemoteExternal(GetByIdentityRequest<RemoteExternalIdentity> request)
{
return await GetExternal<RemoteExternal, RemoteExternalIdentity>(request);
}
}
startup.cs
app.UseEndpoints(endpoints => endpoints.MapControllerRoute(
name: "default",
pattern: "api/{controller}/{action}")) //Not work even with "api/{controller}/{action}/{?id}"
常用码
public class GetByIdentityRequest<TIDentity> : ServiceRequest
where TIDentity : BaseIdentity
{
public TIDentity Identity { get; set; }
}
public class RemoteExternalIdentity : BaseIdentity
{
public int IdX { get; set; }
}
JSON
{"$id":"1","Identity":{"$id":"2","IdX":10000}}
API LINK
.../api/Main/GetExternalRemoteExternal
[ApiController]
attribute adds a few conventions to controllers that enables some opinionated behaviors, including binding source parameter inference 使复杂的参数默认从 body 绑定。
由于您不能将 [ApiController]
属性与基于约定的路由一起使用(因为约定之一就是为了防止这种情况发生),您可以使用带有参数的显式 [FromBody]
来强制它们从 JSON 正文解析:
public class Main : ControllerBase
{
[HttpPost]
public async Task<GetByIdentityResponse<RemoteExternal>> GetExternalRemoteExternal(
[FromBody] GetByIdentityRequest<RemoteExternalIdentity> request)
{
return await GetExternal<RemoteExternal, RemoteExternalIdentity>(request);
}
}
问题
在控制器和操作上使用 ApiControllerAttribute 和 RouteAttribute,一切正常。
当我更改代码以使用传统路由时,请求中的标识 属性 始终设置为空。
带有 ApiControllerAttribute 的代码(请求中加载的标识)
[ApiController]
[Route("api/[controller]")]
Public Class Main : ControllerBase
{
[HttpPost(nameof(GetExternalRemoteExternal))]
public async Task<GetByIdentityResponse<RemoteExternal>> GetExternalRemoteExternal(GetByIdentityRequest<RemoteExternalIdentity> request)
{
return await GetExternal<RemoteExternal, RemoteExternalIdentity>(request);
}
}
startup.cs
app.UseEndpoints(endpoints => endpoints.MapControllers());
具有常规路由的代码(请求具有空标识)
Public Class Main : ControllerBase
{
[HttpPost]
public async Task<GetByIdentityResponse<RemoteExternal>> GetExternalRemoteExternal(GetByIdentityRequest<RemoteExternalIdentity> request)
{
return await GetExternal<RemoteExternal, RemoteExternalIdentity>(request);
}
}
startup.cs
app.UseEndpoints(endpoints => endpoints.MapControllerRoute(
name: "default",
pattern: "api/{controller}/{action}")) //Not work even with "api/{controller}/{action}/{?id}"
常用码
public class GetByIdentityRequest<TIDentity> : ServiceRequest
where TIDentity : BaseIdentity
{
public TIDentity Identity { get; set; }
}
public class RemoteExternalIdentity : BaseIdentity
{
public int IdX { get; set; }
}
JSON
{"$id":"1","Identity":{"$id":"2","IdX":10000}}
API LINK
.../api/Main/GetExternalRemoteExternal
[ApiController]
attribute adds a few conventions to controllers that enables some opinionated behaviors, including binding source parameter inference 使复杂的参数默认从 body 绑定。
由于您不能将 [ApiController]
属性与基于约定的路由一起使用(因为约定之一就是为了防止这种情况发生),您可以使用带有参数的显式 [FromBody]
来强制它们从 JSON 正文解析:
public class Main : ControllerBase
{
[HttpPost]
public async Task<GetByIdentityResponse<RemoteExternal>> GetExternalRemoteExternal(
[FromBody] GetByIdentityRequest<RemoteExternalIdentity> request)
{
return await GetExternal<RemoteExternal, RemoteExternalIdentity>(request);
}
}