.NET核心自定义和默认绑定相结合 [英] .NET core custom and default binding combined
问题描述
我正在为视图模型创建自定义模型绑定程序,实现了IModelBinder
I'm creating a custom model binder for a view model, implementing IModelBinder
我的视图模型中有很多属性,其中大多数不需要任何自定义绑定.与其从ModelBindingContext
单独显式设置模型上的所有属性值,不如我能够获得为我绑定模型的框架,然后执行任何自定义绑定:
I have a lot of properties in my view model, the majority of which do not need any custom binding. Rather than explicitly set all of the property values on my model individually from the ModelBindingContext
, I would to be able to get the framework to bind the model for me, then I would carry out any custom binding:
public class ApplicationViewModelBinder : IModelBinder
{
public Task BindModelAsync(ModelBindingContext bindingContext)
{
if (bindingContext == null)
{
throw new ArgumentNullException(nameof(bindingContext));
}
// get .net core to bind values on model
// Cary out any customization of the models properties
bindingContext.Result = ModelBindingResult.Success(bindingContext.Model);
return Task.CompletedTask;
}
}
基本上,我想执行默认的模型绑定,然后应用自定义绑定,类似于此
Basically I want to carry out the default model binding, then apply custom binding, similar to the approach taken in this SO post but for .NET Core, not framework.
我认为应用默认绑定会很简单,但是还没有找到如何做到这一点的方法.我相信该解决方案将涉及ComplexTypeModelBinder
和ComplexTypeModelBinderProvider
类,但似乎无法找出解决方法.
I assumed applying the default binding would be straight forward, but haven't been able to find out how to do so. I believe the solution would involve ComplexTypeModelBinder
and ComplexTypeModelBinderProvider
classes, but can't seem to find out how to go about it.
我知道我可以在POST请求到达我的控制器方法时进行任何更改,但这似乎是错误的地方,并且这样做的时间不正确.
I know I could just make any changes when the POST request hits my controller method, but this seem the wrong place and wrong time to do so.
推荐答案
对于自定义ComplexTypeModelBinder
,您可以从ComplexTypeModelBinder
继承.
For custom ComplexTypeModelBinder
, you could inherit from ComplexTypeModelBinder
.
-
模型
Model
public class BinderModel
{
public int Id { get; set; }
public string Name { get; set; }
public string BinderValue { get; set; }
}
控制器操作
Controller Action
[HttpPost]
public void Post([FromForm]BinderModel value)
{
}
CustomBinder
CustomBinder
public class CustomBinder : ComplexTypeModelBinder
{
private readonly IDictionary<ModelMetadata, IModelBinder> _propertyBinders;
public CustomBinder(IDictionary<ModelMetadata, IModelBinder> propertyBinders)
: base(propertyBinders)
{
_propertyBinders = propertyBinders;
}
protected override Task BindProperty(ModelBindingContext bindingContext)
{
if (bindingContext.FieldName == "BinderValue")
{
bindingContext.Result = ModelBindingResult.Success("BinderValueTest");
return Task.CompletedTask;
}
else
{
return base.BindProperty(bindingContext);
}
}
protected override void SetProperty(ModelBindingContext bindingContext, string modelName, ModelMetadata propertyMetadata, ModelBindingResult result)
{
base.SetProperty(bindingContext, modelName, propertyMetadata, result);
}
}
CustomBinderProvider
CustomBinderProvider
public class CustomBinderProvider : IModelBinderProvider
{
public IModelBinder GetBinder(ModelBinderProviderContext context)
{
if (context == null)
{
throw new ArgumentNullException(nameof(context));
}
if (context.Metadata.IsComplexType && !context.Metadata.IsCollectionType)
{
var propertyBinders = new Dictionary<ModelMetadata, IModelBinder>();
for (var i = 0; i < context.Metadata.Properties.Count; i++)
{
var property = context.Metadata.Properties[i];
propertyBinders.Add(property, context.CreateBinder(property));
}
//var loggerFactory = context.Services.GetRequiredService<ILoggerFactory>();
//return new ComplexTypeModelBinder(propertyBinders, loggerFactory);
return new CustomBinder(propertyBinders);
}
return null;
}
}
注入提供程序
Inject provider
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc(options => {
options.ModelBinderProviders.Insert(0, new CustomBinderProvider());
});
}
这篇关于.NET核心自定义和默认绑定相结合的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!