model-view-controllerdefaultmodelbindercustom-model-binder

What method or property should be overwritten in custom Model Binding?


I have a custom binding scenario for an MVC app that requires two pieces of functionality

1) A generic, reusable custom binder that allows mapping of form/query properties to class properties.

2) A class specific custom binder that splits a given form/query parameter into a dictionary (or two properties).

The first requirement was accomplished with a solution I found via Google (I apologize that I cannot provide a link as I forget where I found it).

In essence, there are two pieces

public class BindAliasAttribute : Attribute {
    ...
    public string Alias { get; set; }
    ...
}

which gets used like

public class SearchRequest {
   ...
   [BindAlias("q")]
   public string SearchTerms { get; set; }
   ...
}

With the second piece being

public class AliasModelBinder : DefaultModelBinder {
   ...
   protected override ProperyDescriptorCollection GetModelProperties(ControllerContext controllerContext, ModelBindingContext bindingContext) {
      var returnProps = base.GetModelProperties(controllerContext, bindingContext);

      // check model for properties with alias attribute
      // add additional PropertyDescriptors as needed
   }
   ...
}

My problem is with requirement #2. In this case, there is an additional property on the SearchRequest class

public class SearchRequest {
   ...
   [BindAlias("q")]
   public string SearchTerms { get; set; }
   ...
   [BindAlias("s")]
   public IDictionary<string, string> SortOrder { get; set; }
   ...
}

where the key of the Dictionary is a field name and the value of the Dictionary item is the order (ascending or descending)

with sample uses of

/Search?...s=Score DESC...
/Search?...s=ModifiedDate ASC&s=OwningUser DESC...

The logic I need to bind the form/query values will be something like

// loop through each form/query parameter of SortOrder or s
// get the value and split it on the space
// add thw two split values to the SortOrder property as new dictionary item

I know I should inherit from DefaultModelBinder again...or in this case AliasModelBinder (which in turn inherits from DefaultModelBinder) in order to support the Alias, but my problem is that I am not sure which method to override. There seems to be very little (i.e almost none) information of the best way to re-use DefaultModelBinder.

My other question involves the best way to use two custom model binders. As far as I know there is no model binder chaining. Is there any way for me to accomplish requirement #2 without #2's solution explicitly having to know about solution #1? Requirement #2 cares about taking a single value and splitting it into a dictionary. Does it really care that the value for the SortOrder property came from an aliased form/query parameter?

Any help would be appreciated.

Thank you.

Jason


Solution

  • I have been mainly overriding OnModelUpdated() in some cases I had to override BindModel but very rarely. In OnModelUpdated your model has already been hydrated but you can still change it in any way you see fit as well as having full access to the controller and ModelBinding contexts.