在.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
我当然可以在MyController中编写我的Create方法来解析提交值的请求(querystring / form / body),并相应地创建我的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;
}
我的两个问题是:
>我是否正在重新发明既定模式?
>我可以拦截MVC反序列化(以优雅的方式)吗?
最佳答案 您可以查看自定义模型绑定.
>创建自己的模型绑定器:实现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”文章可能有所帮助: