Asp.Net Core 模型绑定 浅析

Web开发中常需要在Controller的操作方法中获取客户端传递过来的值

注:Asp.Net Core Web Api

我们常常会这样写

[Route("TestApi")]
        [HttpPost]
        public string TestApi2([FromForm]string arg1, [FromForm]int arg2, [FromForm]DateTime date,[FromForm]float float1)
        {
            return "Success";
        }

在Controller的操作方法被执行时,由客户端传递的KV 键值对会被映射到方法的参数上,完成这个映射过程的操作就是模型绑定。

模型绑定的原理:

Asp.Net Core项目启动时,会初始化一系列内置的模型绑定器  IModelBinderProvider

Asp.Net Core 模型绑定 浅析_第1张图片

当处理Http请求进行模型绑定时,会顺序调用注册的模型绑定器,根据需要需要使用匹配的模型绑定器,模型绑定内部会完成http请求数据到Controller 操作方法参数的转换和装配过程,这期间并没有做神秘的事情,仅仅是从原始Request对象中 Form 、QueryString 、Header等Http请求头,根据key获取原始数据 一般为 String和Stream类型,然后根据当前BindMode的ModeType进行类型转换,最后赋值给ModelBindingContext 的Result属性,剩下的工作(注入到操作方法对应参数)由Asp.Net Core完成。

以上就是Asp.Net Core模型绑定的主要过程。

 

自定义模型绑定器

1.建立一个类,实现 IModelBinder接口,在这个类里完成从Http请求中获取数据到模型的过程

public class MyModelBinder : IModelBinder
    {
        public Task BindModelAsync(ModelBindingContext bindingContext)
        {
            string key = bindingContext.ModelName;

            if (String.IsNullOrEmpty(key))
            {
                key = bindingContext.FieldName;
            }


            string val = bindingContext.HttpContext.Request.Form[key];

            if (String.IsNullOrEmpty(val))
            {
                val = bindingContext.HttpContext.Request.Query[key];
            }

            if (String.IsNullOrEmpty(val))
            {
                return Task.CompletedTask;
            }

            if (bindingContext.ModelType == typeof(string))
            {
                bindingContext.Model = val;
            }

            if (bindingContext.ModelType == typeof(int))
            {
                bindingContext.Model = int.Parse(val);
            }

            if (bindingContext.ModelType == typeof(long))
            {
                bindingContext.Model = long.Parse(val);
            }

            if (bindingContext.ModelType == typeof(float))
            {
                bindingContext.Model = float.Parse(val);
            }

            if (bindingContext.ModelType == typeof(double))
            {
                bindingContext.Model = double.Parse(val);
            }

            if (bindingContext.ModelType == typeof(short))
            {
                bindingContext.Model = short.Parse(val);
            }

            if (bindingContext.ModelType == typeof(DateTime))
            {
                bindingContext.Model = DateTime.Parse(val);
            }

            if (bindingContext.Model != null)
            {
                bindingContext.Result = ModelBindingResult.Success(bindingContext.Model);
            }

            if (bindingContext.ModelType == typeof(IFormFile))
            {
                bindingContext.Model = bindingContext.HttpContext.Request.Form.Files[0];
            }

            bindingContext.Result = ModelBindingResult.Success(bindingContext.Model);

            return Task.CompletedTask;
        }
    }

2.实现 IModelBinderProvider接口,包装上面实现的模型绑定器。

public class MyModelBinderProvider : IModelBinderProvider
    {
        public IModelBinder GetBinder(ModelBinderProviderContext context)
        {
            if (context == null)
            {
                throw new ArgumentNullException(nameof(context));
            }
            return new BinderTypeModelBinder(typeof(MyModelBinder));

        }
    }

3. 将我们的模型绑定提供程序 Provider注册到Asp.Net Core模型提供程序队列中。

public void ConfigureServices(IServiceCollection services)
        {
            services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2)
                .AddMvcOptions(options =>
                {
                    options.ModelBinderProviders.Insert(0,new MyModelBinderProvider());
                });
        }

以上就是模型绑定的一般过程,其实Asp.net内置的一系列模型绑定已经能够满足我们的大部分需求了,不过我们总会有一些个性化的需求,所以作为框架会对一些功能开放扩展接口,让我们开发者参于进去,实现自己的需要。

可能有纰漏或错误的地方,望指正。

你可能感兴趣的:(C#,Asp.Net,Core)