自定义模型绑定问题

时间:2011-11-04 18:41:56

标签: asp.net-mvc model-binding

在我的MVC 3解决方案中,我希望将查询字符串中的所有ID都加密。要解密我从DefaultModelBinder继承并覆盖BindProperty方法的URL:

 public class CryptedIdBinder : DefaultModelBinder
{   

    protected override void BindProperty(ControllerContext controllerContext, ModelBindingContext bindingContext, System.ComponentModel.PropertyDescriptor propertyDescriptor)
    {
        if (propertyDescriptor.Name.ToLower() == "id")
        {
            propertyDescriptor.SetValue(bindingContext.Model, CryptoHelper.Decrypt(controllerContext.HttpContext.Request.Form["id"]));
            return;
        }

        base.BindProperty(controllerContext, bindingContext, propertyDescriptor);
        return;
    }

之后我在Application_Start上的global.asax中设置了新的DefaultBinder:

System.Web.Mvc.ModelBinders.Binders.DefaultBinder = new CryptedIdBinder();

我没有从IModelBinder继承,因为我想更改解决方案中id字段的绑定逻辑

问题是从不调用BindProperty方法。我做错了什么?

PS。为了确保我至少调用BindModel方法,我在自定义绑定器中添加了这个代码的和平,并且它被调试器命中:

public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
    {
        return base.BindModel(controllerContext, bindingContext);
    }

1 个答案:

答案 0 :(得分:2)

如果您的模型当然没有Id属性,则不会调用BindProperty。因为它调用了模型属性。如果我理解你的问题,你需要的是转换每个Id命名查询字符串参数。在这种情况下,您需要一个自定义值提供程序而不是一个模型绑定器。关于价值提供者,这是good article。写一个很容易:

public class MyValueProviderFacotry : ValueProviderFactory
{
    public override IValueProvider GetValueProvider(ControllerContext controllerContext)
    {
        return new MyValueProvider(controllerContext);
    }
}

public class MyValueProvider : IValueProvider
{
    private ControllerContext controllerContext;

    public MyValueProvider(ControllerContext controllerContext)
    {
        this.controllerContext = controllerContext;
    }

    public bool ContainsPrefix(string prefix)
    {
        return true;
    }

    public ValueProviderResult GetValue(string key)
    {
        if (key.ToLower() == "id")
        {
           var originalValue =  controllerContext.HttpContext.Request.QueryString[key]; 
           var transformedValue = CryptoHelper.Decrypt(orignalValue );
           var result = new ValueProviderResult(transformedValue,originalValue,CultureInfo.CurrentCulture);
            return result;
        }
        return null;
    }
}

在global.asax中:

 protected void Application_Start()
        {
            AreaRegistration.RegisterAllAreas();
            ValueProviderFactories.Factories.Insert(4, new MyValueProviderFacotry()); //Its need to be inserted before the QueryStringValueProviderFactory
            RegisterGlobalFilters(GlobalFilters.Filters);
            RegisterRoutes(RouteTable.Routes);
        }