.NET核心自定义和默认绑定相结合 [英] .NET core custom and default binding combined

查看:84
本文介绍了.NET核心自定义和默认绑定相结合的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在为视图模型创建自定义模型绑定程序,实现了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.

我认为应用默认绑定会很简单,但是还没有找到如何做到这一点的方法.我相信该解决方案将涉及ComplexTypeModelBinderComplexTypeModelBinderProvider类,但似乎无法找出解决方法.

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.

  1. 模型

  1. 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屋!

    查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆