Click here to Skip to main content
Click here to Skip to main content

How to Bind Derived Type in MVC View

, 10 May 2013 CPOL
Rate this:
Please Sign up or sign in to vote.
How to bind Derived Type in MVC View

Introduction

Normally when we bind the Derived type (or derived type collection) to the MVC View, it always return the actual base type on controller, because our Model (business or domain entity) always has the BaseType. To persist the derived type (during postbacks), we have to create our own custom binder that actually maintain its derived type.

This tip contains a solution of persisting Derived Types binded to base type object in MVC view.

Background

I have faced a problem in my project. I have an array of base class objects, whose individual items refer to derived class objects. I need to bind this array in my MVC view, but in Model binding approach it loses the actual derived type on post back. So to resolve this problem, I have created a customized DerivedTypeModelBinder, with the help of which I am able to persist derived types binded to base class objects.

Using the Code

I have base class WarrantyBase as below:

[DataContract]
[Serializable]
[XmlInclude(typeof(AWarranty))]
[XmlInclude(typeof(BWarranty))]
[KnownType(typeof(AWarranty))]
[KnownType(typeof(BWarranty))]
public class WarrantyBase
{
}

And the other derived classes as below…

[DataContract]
[Serializable]
public class AWarranty : WarrantyBase
{

}
[DataContract]
[Serializable]
public class BWarranty: WarrantyBase
{

}

Then I have an array of Base class that I need to bind on my view as:

<% for (int i = 0; i < Model.Warranties.Count; i++)
{ %>
<tr>
<td>
<%= this.CheckBox(c => c.Warranties[i].IsSelected)%>
</td>
</tr>

When I am getting my model in Postback, I always get the base class objects and not able to convert those base objects to derived. So, I need a solution by which my view always return the actual derived type and not the base ones. So to achieve this, I have to write a DerivedTypeModelBinder which is derived from DefaultModelBinder, as shown in the below code snippet.

public class DerivedTypeModelBinder : DefaultModelBinder
{
protected override object CreateModel(ControllerContext controllerContext, 
ModelBindingContext bindingContext, Type modelType)
{
return base.CreateModel(controllerContext, bindingContext, 
GetModelType(controllerContext, bindingContext, modelType));
}
protected override ICustomTypeDescriptor GetTypeDescriptor
(ControllerContext controllerContext, ModelBindingContext bindingContext)
{
var modelType = GetModelType(controllerContext, bindingContext, bindingContext.ModelType);
return new AssociatedMetadataTypeTypeDescriptionProvider(modelType).GetTypeDescriptor(modelType);
}
private static Type GetModelType(ControllerContext controllerContext, 
ModelBindingContext bindingContext, Type modelType)
{
if (bindingContext.ValueProvider.ContainsPrefix(bindingContext.ModelName + ".BindingType"))
{
modelType = System.Type.GetType(((string[])bindingContext.ValueProvider.GetValue
(bindingContext.ModelName + ".BindingType").RawValue)[0]);
}
return modelType;
}
}

And then, you have to take a hidden control to bind the actual type in Views to persist the same during postbacks.

<%= Html.Hidden(string.Format("Warranties[{0}].BindingType", i), 
Model.Warranties[i].GetType().AssemblyQualifiedName)%>

Then the last step is to register your customized binder in Global.asax file in RegisterArea or RegisterRoute method.

// Register the binder in below place…
public override void RegisterArea(AreaRegistrationContext context)
{
RegisterAreaEmbeddedResources();
ModelBinders.Binders.Add(typeof(WarrantyBase), new Common.Helpers.DerivedTypeModelBinder());
} 

Conclusion

This solution solves the problem of binding base class object in view and getting actual derived class objects in postback.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

Abhay@Accenture

United States United States
No Biography provided

Comments and Discussions

 
GeneralMy vote of 5 PinmemberNigeE30-Aug-13 3:44 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Terms of Use | Mobile
Web03 | 2.8.141223.1 | Last Updated 10 May 2013
Article Copyright 2013 by Abhay@Accenture
Everything else Copyright © CodeProject, 1999-2014
Layout: fixed | fluid