Asp.net Vnext ModelBinding

时间:2023-03-09 02:48:08
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; }
}

Asp.net Vnext  ModelBinding


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

Asp.net Vnext  ModelBinding

全部没有赋值,
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
};
}

Asp.net Vnext  ModelBinding

控制器

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"> }

Asp.net Vnext  ModelBinding

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 > ).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; }
}

Asp.net Vnext  ModelBinding

FromHeader:Header绑定

控制器

        public int Add(int left, int right, [FromServices] ICalculator calculator)
{
return calculator.Operation('+', left, right);
}

IOC

    services.AddSingleton<ICalculator, DefaultCalculator>();

Asp.net Vnext  ModelBinding

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;
}

Asp.net Vnext  ModelBinding

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;
}

Asp.net Vnext  ModelBinding