How to bind URL parameters to model properties with different names

Polaris878 picture Polaris878 · Dec 14, 2011 · Viewed 15.4k times · Source

Okay, lets say I have a URL like so, which is mapped via HTTP verb GET to the controller action I have below:

GET /foo/bar?sort=asc&r=true

How can I bind this to my model Bar on my controller action I have below:

class Bar {
    string SortOrder { get; set; }
    bool Random { get; set; }
}

public ActionResult FooBar(Bar bar) {
    // Do something with bar
    return null;
}

Note that the property names won't and can't necessarily match the names of the URL parameters. Also, these are OPTIONAL url parameters.

Answer

Max Toro picture Max Toro · Dec 14, 2011

It's not supported out of the box, but you could do this:

class BarQuery : Bar { 

   public string sort { get { return SortOrder; } set { SortOrder = value; } }
   public bool r { get { return Random; } set { Random = value; } }
}

public ActionResult FooBar(BarQuery bar) {
    // Do something with bar
}

You could implement a custom IModelBinder, but it's much easier to do manual mapping.


If you can change the Bar class you can use this attribute:

class FromQueryAttribute : CustomModelBinderAttribute, IModelBinder { 

   public string Name { get; set; }

   public FromQueryAttribute() { }

   public FromQueryAttribute(string name) { 
      this.Name = name;
   }

   public override IModelBinder GetModelBinder() { 
      return this;
   }

   public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext) {
      return controllerContext.HttpContext.QueryString[this.Name ?? bindingContext.ModelName];
   }
}

class Bar {

    [FromQuery("sort")]
    string SortOrder { get; set; }

    [FromQuery("r")]
    bool Random { get; set; }
}

public ActionResult FooBar(Bar bar) {
    // Do something with bar
    return null;
}