在 .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 提供的开箱即用的绑定(bind):
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 反序列化(以优雅的方式)吗?
最佳答案
您可以查看自定义模型绑定(bind)。
创建自己的模型绑定(bind)器:实现 IModelBinder 接口(interface)的类:
/// <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); }
注册您的 Binder :
services.AddMvc().Services.Configure<MvcOptions>(options => { options.ModelBinders.Insert(0, new YourCustomModelBinder()); });
MVC github repo 和“Custom Model Binding”文章可能有帮助:
关于c# - .Net Core MVC反序列化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41835778/