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
当处理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内置的一系列模型绑定已经能够满足我们的大部分需求了,不过我们总会有一些个性化的需求,所以作为框架会对一些功能开放扩展接口,让我们开发者参于进去,实现自己的需要。
可能有纰漏或错误的地方,望指正。