受欢迎的博客标签

ASP.NET Core MVC 模型绑定[FromHeader],[FromQuery],[FromRoute],[FromForm]用法场景及原理(二)

Published

 

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 :属性包括表达式
来看下怎么用实例代码

 
 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; }
        }
 
控制器
public class BindAttributeController : Controller
    {
        public User EchoUser([Bind(typeof(ExcludeUserPropertiesAtParameter))] User user)
        {
            return user;
        }

User实体

public class BindAttributeController : Controller
    {
        public User EchoUser([Bind(typeof(ExcludeUserPropertiesAtParameter))] User user)
        {
            return user;
        }
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:参数绑定

 

[FromForm]:表单绑定

 

控制器

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