Asp.net Vnext ModelBinding
Model Binding
本文已经同步到《Asp.net Vnext 系列教程 》中]
Model binding(绑定)简单来说就是通过遍历ValueProvider(值提供者)获取的数据对Action参数进行赋值.
在学习本篇教程,应对model binding有基础了解。
DefaultPropertyBindingPredicateProvider
DefaultPropertyBindingPredicateProvider:提供一种基于表达式的方法来提供包括的属性。
public class DefaultPropertyBindingPredicateProvider<TModel> : IPropertyBindingPredicateProvider where TModel : class { public DefaultPropertyBindingPredicateProvider(); public virtual string Prefix { get; } public virtual Func<ModelBindingContext, string, bool> PropertyFilter { get; } public virtual IEnumerable<Expression<Func<TModel, object>>> PropertyIncludeExpressions { get; } }
这个类有三个属性:
Prefix 表示前缀名
PropertyFilter :属性过滤
PropertyIncludeExpressions :属性包括表达式
来看下怎么用实例代码
private class ExcludeUserPropertiesAtParameter : DefaultPropertyBindingPredicateProvider<User> { Func<ModelBindingContext, string, bool> _defaultFilter1 = (context, propertyName) => false; public ExcludeUserPropertiesAtParameter() { } public override string Prefix { get { return "user"; } } public override IEnumerable<Expression<Func<User, object>>> PropertyIncludeExpressions { get { yield return m => m.RegisterationMonth; yield return m => m.UserName; } } }
控制器
public class BindAttributeController : Controller { public User EchoUser([Bind(typeof(ExcludeUserPropertiesAtParameter))] User user) { return user; }
User实体
public class User { [Required] public int Id { get; set; } public int Key { get; set; } [Required] public string RegisterationMonth { get; set; } public string UserName { get; set; } public Address Address { get; set; } }
Prefix 前缀名是user,也就是说请求id必需加上user作为前缀
PropertyIncludeExpressions:属性包括:
get
{ yield return m => m.RegisterationMonth; yield return m => m.UserName; }
表示:支队这个属性进行赋值。
我们来看看PropertyFilter作用
private class ExcludeUserPropertiesAtParameter : DefaultPropertyBindingPredicateProvider<User> { Func<ModelBindingContext, string, bool> _defaultFilter1 = (context, propertyName) => false; public ExcludeUserPropertiesAtParameter() { } public override string Prefix { get { return "user"; } } public override Func<ModelBindingContext, string, bool> PropertyFilter { get { return _defaultFilter1; } } }
_defaultFilter1 表达式一直返回false
全部没有赋值,
PropertyFilter:
PropertyIncludeExpressions等于null propertyFilter 将默认返回true.
FromRoute
FromQuery
FromForm
FromBody
FromHeader
FromServices
这是属性表示绑定的值从何获取
[Route("/FromAttributes/[Action]/{HomeAddress.Street}/{HomeAddress.State}/{HomeAddress.Zip}", Name = "yangwen")] public User_FromForm GetUser([FromRoute] Address homeAddress, [FromQuery] Address shippingAddress) { return new User_FromForm { HomeAddress = homeAddress, ShippingAddress = shippingAddress }; }
控制器
FromRoute:从路由绑定
FromQuery:参数绑定
控制器
[Route("/FromAttributes1",Name ="yangwen1")] public void GetUser1( [FromForm] Address officeAddress ) { }
视图
@model ModelBindingWebSite.Models.Address @using (Html.BeginRouteForm("yangwen1", FormMethod.Post)) { @Html.EditorForModel(); <input type="submit" value="Submit"> }
FromForm:表单绑定
控制器
[HttpGet("BindToModelWithInitializedValue")] public object BindToModelWithInitializedValue(BlogPostWithInitializedValue blogPost) { return new Result() { HeaderValue = blogPost.Host, HeaderValues = blogPost.Tags, ModelStateErrors = ModelState.Where(kvp => kvp.Value.Errors.Count > 0).Select(kvp => kvp.Key).ToArray(), }; }
public class BlogPostWithInitializedValue { [Required] [FromHeader] public string Host { get; set; } = "How to Make Soup"; [FromHeader] public string[] Tags { get; set; } = new string[] { "Cooking" }; public string Author { get; set; } }
FromHeader:Header绑定
控制器
public int Add(int left, int right, [FromServices] ICalculator calculator) { return calculator.Operation('+', left, right); }
IOC
services.AddSingleton<ICalculator, DefaultCalculator>();
FromServices:绑定IOC
FromBody
public void Post([FromBody]Person p)
POST http://localhost:10725/api/values?name=b&age=2HTTP/1.1
Content-Type: application/json
Host: localhost:10725
Content-Length: 30
{“Name” : “John”, “Age” : 24 }
IModelMetadataProvider
Model元数据提供者
public class AdditionalValuesMetadataProvider : IDisplayMetadataProvider { private static Guid _guid = new Guid("7d6d0de2-8d59-49ac-99cc-881423b75a76"); public void GetDisplayMetadata(DisplayMetadataProviderContext context) {
//添加附加值 context.DisplayMetadata.AdditionalValues.Add("key1", _guid); context.DisplayMetadata.AdditionalValues.Add("key2", "value2"); } }
启动类
services.AddMvc() .Configure<MvcOptions>(m => { m.ModelMetadataDetailsProviders.Add(new AdditionalValuesMetadataProvider()); });
控制器
public IReadOnlyDictionary<object, object> GetAdditionalValues([FromServices] IModelMetadataProvider provider) { var metadata = provider.GetMetadataForType(typeof(LargeModelWithValidation)); //输出附加值 return metadata.AdditionalValues; }
IModelBinder
模型绑定
private class ProductModelBinder : IModelBinder { public async Task<ModelBindingResult> BindModelAsync(ModelBindingContext bindingContext) { if (typeof(Product).IsAssignableFrom(bindingContext.ModelType)) { //实例 var model = (Product)Activator.CreateInstance(bindingContext.ModelType); model.BinderType = GetType(); var key = string.IsNullOrEmpty(bindingContext.ModelName) ? "productId" : bindingContext.ModelName + "." + "productId"; //获取值 var value = await bindingContext.ValueProvider.GetValueAsync(key); model.ProductId = (int)value.ConvertTo(typeof(int)); return new ModelBindingResult(model, key, true); } return null; } }
控制器
public string GetBinderType_UseModelBinder( [ModelBinder(BinderType = typeof(ProductModelBinder))] Product model) { return model.BinderType.FullName; }