c# - POST 模型绑定不适用于带有 .net core c# 的命名空间路由约定
问题描述
我一直在尝试使用命名空间路由来动态构建一些 API,而无需担心对路由进行硬编码。但是,我确实从MSDN中找到了一个使用命名空间和文件夹结构作为 API 结构的示例。这是我必须使用命名空间路由的示例:
public class NamespaceRoutingConvention : Attribute, IControllerModelConvention
{
private readonly string _baseNamespace;
public NamespaceRoutingConvention(string baseNamespace)
{
_baseNamespace = baseNamespace;
}
public void Apply(ControllerModel controller)
{
var hasRouteAttributes = controller.Selectors.Any(selector => selector.AttributeRouteModel != null);
if (hasRouteAttributes)
{
return;
}
var namespc = controller.ControllerType.Namespace;
if (namespc == null) return;
var templateParts = new StringBuilder();
templateParts.Append(namespc, _baseNamespace.Length + 1, namespc.Length - _baseNamespace.Length - 1);
templateParts.Replace('.', '/');
templateParts.Append("/[controller]/[action]/{environment}/{version}");
var template = templateParts.ToString();
foreach (var selector in controller.Selectors)
{
selector.AttributeRouteModel = new AttributeRouteModel()
{
Template = template
};
}
}
}
这是控制器:
namespace Backend.Controllers.Api.Project.Core
{
public class UserController : ApiBaseController
{
public UserController()
{
}
[HttpPost]
public IActionResult Login(LoginInput loginInput) // <-- loginInput properties return null
{
if (!ModelState.IsValid) return BadRequest();
return Ok(user);
}
}
}
在Startup.cs
namespace Backend
{
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
// Let's use namespaces as the routing default way for our APIs
services.AddControllers(options =>
{
options.Conventions.Add(new NamespaceRoutingConvention(typeof(Startup).Namespace + ".Controllers"));
});
}
}
}
一切正常,除了当我触发POST
api 调用Login
操作时,LoginInput
不会填充我通过Postman
ie发送的值{"username": "value", "password": "sample"}
,它总是返回null
值。我不确定我做错了什么NamespaceRoutingConvention
。请记住,如果我将其删除并在控制器中对路由进行硬编码,例如:
[ApiController]
[Route("api/project/core/[controller]/[action]/proda/v1")]
它按预期工作。有任何想法吗?
解决方案
尝试改用这个:
[HttpPost]
public IActionResult Login([FromBody]LoginInput loginInput)
{
if (!ModelState.IsValid) return BadRequest();
return Ok(user);
}
我认为通过设置AttributeRouteModel
,您可以防止通过ApiControllerAttribute
在 Controller 中执行其工作来调用中间件,因此不应用将对象参数视为主体的默认设置。
虽然这是一个猜测,我一直无法在源代码中找到相应的代码。