【问题标题】:Custom model binding issue自定义模型绑定问题
【发布时间】:2011-12-22 06:58:08
【问题描述】:

在我的 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 方法。我做错了什么?

附言。为了确保我至少调用了 BindModel 方法,我在我的自定义活页夹中添加了这段代码的和平,它被调试器击中:

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

【问题讨论】:

  • 你能发布一些示例模型代码吗?也许 DefaultModelBinder 过滤掉了你的一些属性......
  • 对不起,我没听懂你的想法。它不是应该为每个模型运行的全局活页夹吗?此 Id 参数未在模型中定义 - 它在默认路由内

标签: asp.net-mvc model-binding


【解决方案1】:

如果您的模型没有 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);
        }

【讨论】:

  • 非常感谢您的回答。看起来这就是我要找的东西。我会在早上试试这个
  • 这非常有效。我唯一需要做的就是实现 ContainsPrefix(因此它确实返回值,指示我是否需要搜索值)并将其放置在 QueryStringValueProviderFactory 之前,而是在 RouteValueProviderFactory 之前。再次感谢!
猜你喜欢
  • 1970-01-01
  • 2011-04-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-02-08
  • 1970-01-01
相关资源
最近更新 更多