我无法理解 Asp.Net core 2 中的模型绑定(bind)过程。我有一个非常简单的 API,它有一个模型。它有一些基本的验证。每当用户发布不正确的模型时,我都会尝试返回 422 unprocessableentity 以及来自模型状态的错误消息。
我想了解的两个问题如下:
如果我发布没有 ID 的请求,则会创建一个默认 ID 0 来绕过必需的属性。我假设这是为字段提供默认值的 C# 功能。有没有办法规避这个?
另一个问题是,如果我在我的 post 操作中放置一个断点并发送一个错误的请求,它甚至不会进入该方法。它使用验证属性发回 400 错误请求。这是如何运作的?请求是否会在尝试绑定(bind)到无效属性(即名称长度 > 10)时立即停止?我需要它做的是发回具有相同错误消息的 422 不可处理实体,而不是 400。
如果基于验证属性的模型状态验证失败,ASP.NET 是否甚至不进入方法?解决此问题以返回 422 错误代码的更好方法是什么?
下面是我的各种类的代码(我在创建项目时使用了API模板):
Startup.cs - 我在这里唯一添加的是我的内存上下文的单例实例
public void ConfigureServices(IServiceCollection services)
{
//services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
services.AddMvc();
services.AddSingleton<IItemRepository, ItemRepository>();
}
IItemRepository.cs - 我的 DI 界面
public interface IItemRepository
{
List<ItemModel> Items { get; set; }
void AddValue(ItemModel itemModel);
}
ItemRepository.cs - 具体实现
public class ItemRepository : IItemRepository
{
public List<ItemModel> Items { get; set; } = new List<ItemModel>();
public ItemRepository()
{
Items.AddRange(
new List<ItemModel> {
new ItemModel {Id = 1, Name = "Test1" },
new ItemModel {Id = 2, Name = "Test2" }
}
);
}
public void AddValue(ItemModel itemModel)
{
Items.Add(itemModel);
}
}
ItemModel.cs - 我的用户输入模型类
public class ItemModel
{
[Required]
public int Id { get; set; }
[MaxLength(10)]
public string Name { get; set; }
}
ValuesController.cs
[Route("api/[controller]")]
[ApiController]
public class ValuesController : Controller
{
private IItemRepository _context;
public ValuesController(IItemRepository context)
{
_context = context;
}
// GET api/values
[HttpGet]
public ActionResult<IEnumerable<string>> Get()
{
return Ok(_context.Items);
}
// GET api/values/5
[HttpGet("{id}", Name = "GetSingle")]
public ActionResult<string> Get(int id)
{
return Ok(_context.Items.Where(x => x.Id == id));
}
// Problem here - placing a breakpoint in below method does not do anytthing as it will return a 400 bad request instead of 422
[HttpPost]
public ActionResult Post([FromBody] ItemModel itemModel)
{
if (!ModelState.IsValid)
{
return new UnprocessableEntityObjectResult(ModelState);
}
ItemModel addNew = new ItemModel { Id = itemModel.Id, Name = itemModel.Name };
_context.AddValue(addNew);
return Ok(addNew);
}
}
最佳答案
对于您的第一个问题,如果您不想让该属性可以为空,您还可以放置一个范围属性 [Range(1, int.MaxValue)],但在这种情况下 0 将不是有效值。
对于你的第二个问题,如果你仍然想要 ApiControllerAttribute 的自动模型验证,但想要 422 响应代码而不是 400,你可以使用 InvalidModelStateResponseFactory 配置选项。
services.Configure<ApiBehaviorOptions>(options =>
{
options.InvalidModelStateResponseFactory = ctx =>
new UnprocessableEntityObjectResult(ctx.ModelState);
});
关于c# - API 中 POST 模型绑定(bind)问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52047921/