Проблема привязки пользовательской модели - PullRequest
2 голосов
/ 04 ноября 2011

В моем решении MVC 3 я хочу, чтобы все идентификаторы в строке запроса были зашифрованы.Чтобы расшифровать URL-адреса, которые я унаследовал от DefaultModelBinder и переопределил метод BindProperty:

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

После этого я установил новый DefaultBinder в global.asax для Application_Start:

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

Я не наследовал от IModelBinderпотому что я хочу изменить логику привязки только для полей идентификатора в решении.

Проблема в том, что метод BindProperty никогда не вызывается.Что я делаю не так?

PS.Чтобы быть уверенным, что я вызываю хотя бы метод BindModel, я добавил код этого кода в свой пользовательский механизм связывания, и он был отлажен отладчиком:

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

1 Ответ

2 голосов
/ 04 ноября 2011

Если ваши модели не имеют свойств Id, BindProperty не будет вызываться.Потому что он вызвал свойства модели.Если я понял ваш вопрос, вам нужно преобразовать каждый Id именованный параметр строки запроса.В этом случае вам нужен пользовательский поставщик значений вместо связывателя моделей.Это хорошая статья о поставщиках стоимости.И это довольно просто написать:

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