模型绑定时对客户端传过来的数据做处理的几种方式

有时我们从客户端获取来的数据。不一定就是我们先要的,需要做一些处理 。这里我们以一个model的属性需要做处理为例子。

这里说5种解决方法。

model:

 

public class MyModel
{
   public string Encrypt  { get; set; }

   public string Lala { get; set; }
}

Controller:

    public class HomeController : Controller
    {
        public void Test(MyModel myModel)
        {

        }
    }

第一种方式:

在model里做处理,很简单也很方便,很好理解直接上代码

namespace WebApplication
{
    public class MyModel
    {
        private string encryptValue = string.Empty;
        public string Encrypt
        {
            set { encryptValue = value; }
            get
            {
                return encryptValue + "uuu";
            }
        }
        public string Lala { get; set; }
    }
}

第二种方式:
实现一个默认的模型绑定重写GetPropertyValue方法。对反回的属性值处理。PS:GetPropertyValue—使用指定的控制器上下文、绑定上下文、属性描述符和属性联编程序来返回属性值。

首选我们要创建一个特性,用来标记需要做处理的属性

model:

namespace WebApplication
{
    public class MyModel
    {
        [Test]
        public string Encrypt { get; set; }

        public string Lala { get; set; }
    }
}

TestAttribute:用来标记的特性

namespace WebApplication
{
    [AttributeUsage(AttributeTargets.Property,AllowMultiple=false,Inherited=false)]
    public class TestAttribute:Attribute
    {

    }
}

MyModelBinder:实现一个默认的模型绑定

调用父类方法获取属性值,如果满足条件,类型条件和标记条件,就返回自定义的值,否者返回原值

namespace WebApplication
{
    public class MyModelBinder:DefaultModelBinder
    {
        protected override object GetPropertyValue(ControllerContext controllerContext, ModelBindingContext bindingContext, System.ComponentModel.PropertyDescriptor propertyDescriptor, IModelBinder propertyBinder)
        {
            var value = base.GetPropertyValue(controllerContext, bindingContext, propertyDescriptor, propertyBinder);
            if(value is string &&propertyDescriptor.Attributes[typeof(TestAttribute)]!=null)
            {
                return "我对值做了处理";
            }
            return value;
        }
    }
}

添加默认模型绑定

namespace WebApplication
{
    public class MvcApplication : System.Web.HttpApplication
    {
        protected void Application_Start()
        {
            AreaRegistration.RegisterAllAreas();
            FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
            RouteConfig.RegisterRoutes(RouteTable.Routes);
            BundleConfig.RegisterBundles(BundleTable.Bundles);
            //自定义默认模型绑定
            ModelBinders.Binders.DefaultBinder = new MyModelBinder();
        }
    }
}

第三种方式:
实现一个自定义值提供器,ContainsPrefix方法判断是否满足条件,myModel:Controller里Action模型参数名

GetValue方式返回ValueProviderResult类型的结果,供模型绑定时使用

namespace WebApplication
{
    public class MyValueProvider : IValueProvider
    {
        public MyValueProvider(string value)
        {
            this.Value = value;
        }
        private string Value { get; set; }
        public bool ContainsPrefix(string prefix)
        {
            if(prefix=="myModel")
            {
                return true;
            }
            else
            {
                return false;
            }
        }

        public ValueProviderResult GetValue(string key)
        {
            MyModel model = new MyModel() { Encrypt = this.Value + "ooo" };
            return new ValueProviderResult(
                model,
                model.ToString(),
                CultureInfo.CurrentCulture);
        }
    }
}

实现一个值提供器工厂:用来提供值提供器

namespace WebApplication
{
    public class MyValueProviderFactory : ValueProviderFactory
    {
        public override IValueProvider GetValueProvider(ControllerContext controllerContext)
        {
            string value = controllerContext.HttpContext.Request["Encrypt"];
            return new MyValueProvider(value);            
        }
    }
}

添加值提供器工厂

namespace WebApplication
{
    public class MvcApplication : System.Web.HttpApplication
    {
        protected void Application_Start()
        {
            AreaRegistration.RegisterAllAreas();
            FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
            RouteConfig.RegisterRoutes(RouteTable.Routes);
            BundleConfig.RegisterBundles(BundleTable.Bundles);
            //添加一个值提供器工厂
            ValueProviderFactories.Factories.Add(new MyValueProviderFactory());
        }
    }
}

第四种方式:
实现一个自定义值提供器工厂,myModel:Controller里Action模型参数名

把myModel作为Encrypt的前缀当做NameValueCollection的key保存起来,作为NameValueCollectionValueProvider的参数

模型是树状的,但是NameValueCollection是平面的,所以以添加前缀的方式保存数据。

namespace WebApplication
{
    public class MyValueProviderFactory : ValueProviderFactory
    {
        public override IValueProvider GetValueProvider(ControllerContext controllerContext)
        {
            var value = controllerContext.HttpContext.Request["Encrypt"];
            if (value == null)
                return null;
            NameValueCollection nameValueCollection = new NameValueCollection();
            nameValueCollection.Add("myModel.Encrypt", "aaa" + value);
            return new NameValueCollectionValueProvider(nameValueCollection, CultureInfo.InvariantCulture);
        }
    }
}

添加值提供器工厂

namespace WebApplication
{
    public class MvcApplication : System.Web.HttpApplication
    {
        protected void Application_Start()
        {
            AreaRegistration.RegisterAllAreas();
            FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
            RouteConfig.RegisterRoutes(RouteTable.Routes);
            BundleConfig.RegisterBundles(BundleTable.Bundles);
            //添加一个值提供器工厂
            ValueProviderFactories.Factories.Add(new MyValueProviderFactory());
        }
    }
}

第五种方式:

实现一个自定义模型绑定,bindingContext中获取当前的值,处理后返回一个model

namespace WebApplication
{
    public class MyBinder:IModelBinder
    {
        public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
        {
            var value = bindingContext.ValueProvider.GetValue("Encrypt").AttemptedValue;
            return new MyModel { Encrypt = value + "ooxx" };
        }
    }
}

使用ModelBinder特性指定模型绑定

namespace WebApplication.Controllers
{
    public class HomeController : Controller
    {
        public void Test([ModelBinder(typeof(MyBinder))] MyModel myModel)
        {

        }
    }
}

学习和进步是一辈的事情,我们都因该不断努力去看一个更大更不一样的世界。

愿2016年,可以过的开开心心的,少些烦恼,做更优秀的项目和产品

 

posted @ 2015-12-29 17:48  世上最帅的程序员  阅读(603)  评论(3编辑  收藏  举报