asp.net-mvcasp.net-mvc-3c#-4.0razormodelbinder

How to convert a http-request into the right object?


In my ASP.Net MVC3 project I have created a ModelBinder which binds a basemodel. In my View i create a object from a Model that inherit from my basemodel. Now i wan´t to know which Model was created via reflection in my ModelBinder when i press the submit-button, but how?

ModelBinder:

public class MBTestBinder : IModelBinder
{
    public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
    {
        //need to know which Model was created -> convert into the right object
        //reflection?
    }
}

Models:

[ModelBinder(typeof(MBTestBinder))]
public class MBTest
{
    public string Name { get; set; }
    public MBTest()  {}
}

public class MBAbl : MBTest
{
    public MBAbl()  {}
    public string House { get; set; }
}

View:

@model ModelBinderProject.Models.MBTest

@using (Html.BeginForm("Index", "Home")) {
<fieldset>
    <div class="editor-field">
        @Html.EditorForModel(Model)
    </div>
    <p>
        <input type="submit" value="Create" />
    </p>
</fieldset>

Controller:

public ActionResult Create(MBTest testItem)
{
    //on init get a view from a class that hast inherit the class MBTest
    if (testItem.Name == null ) testItem = new MBAbl();

    return View(testItem);
}

edit:

with bindingContext.ValueProvider.GetValue("House") i can get the value of the Form but bindingContext.ModelType thinks that my Model is MBTest


Solution

  • Finaly i solved it with the workaround of carrying the name of the model in my model and dynamically create the right model in the modelbinder. If you know a better solution plz show me :-)

    HomeController:

    // CREATE
    public ActionResult About(MBTest testItem)
    {
        if (testItem == null)
        {
            testItem = new MBAbl();
            testItem.Model = "MBAbl";
        }
    
        return View(testItem);
    }
    

    Models:

    public class MBTest
    {
        public MBTest()  {}
    
        [HiddenInput]
        public string Model { get; set; }
    
        public string Name { get; set; }
    }
    
    public class MBAbl : MBTest
    {
        public MBAbl()  {}
    
        public string House { get; set; }
    }
    
    public class MBAb2 : MBTest
    {
        ...
    }
    

    ModelBinder:

    public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
    {
        if (controllerContext == null) throw new ArgumentNullException("controllerContext");
        if (bindingContext == null) throw new ArgumentNullException("bindingContext");
    
        //string 'Model' is needed in the base class
        var modelType = bindingContext.ValueProvider.GetValue("Model");
    
        if (modelType != null && !string.IsNullOrEmpty(modelType.AttemptedValue))
        {
            string projectName = System.Reflection.Assembly.GetExecutingAssembly().GetName().Name;
    
            Type classtype = Type.GetType(string.Format("{0}.Models.{1}", projectName, modelType.AttemptedValue));
            PropertyInfo[] properties = classtype.GetProperties();
    
            var classObject = classtype.GetConstructor(new Type[] { }).Invoke(null);
    
            foreach (PropertyInfo propertie in properties)
            {
                var value = bindingContext.ValueProvider.GetValue(propertie.Name).AttemptedValue;
                classtype.GetProperty(propertie.Name).SetValue(classObject, value, null);
            }
    
            return classObject;
        }
        return null;
    }