在.netcore应用程序中,我想提供以下(简化):
// Create a new record, assume it returns an ID=1
https://site/MyController/Save?FirstName=John&LastName=Doe&Status=Active
// Update the record without full state
PUT https://site/MyController/1
{
'DOB': '1/1/1970',
'Status': null
}
我想将此第二个电话转换为:
UPDATE MyModel SET DOB = '1/1/1970' AND Status=NULL WHERE Id = 1
我当然可以在Create
中编写MyController
方法来解析提交值的请求(查询字符串/表单/正文),并相应地创建我的SQL。
但是,我更喜欢遵循MVC约定并利用MVC提供的绑定:
public async Task<MyModel> Save(string id, [FromBody]MyModel instance)
{
await _MyRepository.UpdateAsync(id, message);
return message;
}
这里的问题是实例看起来像这样:
{
'FirstName': null,
'LastName': null,
'DOB': '1/1/1970',
'Status': null
}
此时我无法确定Db中哪些字段应为NULL ,哪些字段应单独保留。
我实现了一个包装类:
这会稍微改变我的方法签名,但不会给开发人员带来负担:
public async Task<MyModel> Save(string id, [FromBody]MyWrapper<MyModel> wrapper
{
await _MyRepository.UpdateAsync(id, wrapper.Instance, wrapper.DirtyProperties);
return wrapper.Instance;
}
我的两个问题是:
答案 0 :(得分:1)
您可以查看自定义模型绑定。
创建自己的模型binder:实现IModelBinder接口的类:
/// <summary>
/// Defines an interface for model binders.
/// </summary>
public interface IModelBinder
{
/// <summary>
/// Attempts to bind a model.
/// </summary>
/// <param name="bindingContext">The <see cref="ModelBindingContext"/>.</param>
/// <returns>
/// <para>
/// A <see cref="Task"/> which will complete when the model binding process completes.
/// </para>
/// <para>
/// If model binding was successful, the <see cref="ModelBindingContext.Result"/> should have
/// <see cref="ModelBindingResult.IsModelSet"/> set to <c>true</c>.
/// </para>
/// <para>
/// A model binder that completes successfully should set <see cref="ModelBindingContext.Result"/> to
/// a value returned from <see cref="ModelBindingResult.Success"/>.
/// </para>
/// </returns>
Task BindModelAsync(ModelBindingContext bindingContext);
}
注册您的活页夹:
services.AddMvc().Services.Configure<MvcOptions>(options => {
options.ModelBinders.Insert(0, new YourCustomModelBinder());
});
MVC github repo和“Custom Model Binding”文章可能有所帮助:
答案 1 :(得分:0)
PUT动词需要整个实体,但您可以发送带有增量的HTTP PATCH。关于这完成如何完成的官方文档很少,但我确实找到了这个link,它说明了如何使用JSONPatchDocument实现这一点,它基本上完成了你的拦截类所做的事情。