3

I've the following class structure.

public BaseClass
{
    public int Id { get; set; }
    public string Name { get; set; }
}

public ClassOne : BaseClass
{

}

public ClassTwo : BaseClass
{

}

My Controller is like this

public TestController : Controller
{
     public ActionResult ClassOne()
     {
          ClassOne model = new ClassOne();
          return View("Create",model);
     }

     public ActionResult ClassTwo()
     {
          ClassTwo model = new ClassTwo();
          return View("Create",model);
     }         

My View ("Create") is like this :

     @model MvcApplication.Models.BaseClass

     @using(Html.BeginForm("Post","Test",FormMethod.Post))
     {
            @Html.HiddenFor(model => mode.Id)
            @Html.TextBoxFor(model => model.Name)
            <input type="submit" value="Submit"/>
     }

My Post Action is the same for both the models i.e. ClassOne & ClassTwo. On Post how can I know which model is passed in the Post Action whether it is ClassOne or ClassTwo.

     [HttpPost]
     public ActionResult Post(BaseClass model)
     {
          /* Code */
     }
4
  • Have you tried using "is" in your controller ? (i.e. if(model is a ClassTwo) Commented Nov 20, 2013 at 14:28
  • 1
    I don't see how this is possible. When the post action is invoked, the model binder will try and bind to the parameters of the method - and in the process instantiate an instance of the BaseClass with no knowledge of the original type passed in to the view when rendering it - any anyway - the model type for the view is the BaseClass so.. i just don't see it.. Commented Nov 20, 2013 at 14:35
  • Exactly as I answered. You should write custom ModelBinder and store actual type name inside your form and then create appropriated class in your model binder Commented Nov 20, 2013 at 14:36
  • There are different techniques. Have a look at the answer here, and the ops own solution stackoverflow.com/a/19450985/150342 Commented Nov 20, 2013 at 15:07

6 Answers 6

2

Inside the post just check the type. Either by if(model is ClassOne) or if(model.GetType() == typeof(ClassOne))

Sign up to request clarification or add additional context in comments.

1 Comment

This will not work. Without storing extra information about the type, whether that's in a hidden field, or from ViewBag / ViewData, there is no way for the model binder to infer the type. As far as it will be concerned, it will have created the base type.
2

I'm not sure that it is possible without creating your own ModelBinder. In this case you'll always get in your action instance of BaseType class.

3 Comments

I agree. When the post action is invoked, the model binder will try and bind to the parameters of the method - and in the process instantiate an instance of the BaseClass with no knowledge of the original type passed in to the view when rendering it.
All, what you need for successful implementation of your model binder is information about current model type. You may store it in view as hidden field for example and in your model binder at the beginning get this info, create property of appropriate type and fill it.
This technique does it without creating a ModelBinder stackoverflow.com/questions/7222533/polymorphic-model-binding/…
1

You can use typeof():

if(model.GetType() == typeof(ClassOne)){
 // do something
}else {
 // do something else.
}

Edit:

thanks to @JoreanVannevel

if(model is ClassOne){}

3 Comments

Shorthand: if model is ClassOne.
@JeroenVannevel agreed..:-)
No you can't. The model binder doesn't have any way to distinguish between the type that has been constructed and the base class itself. This is not the same as normal polymorphism.
0

You can just check the type of the object.

if(model.GetType() == typeof(ClassOne))
{
    // Do something
}

1 Comment

See above. There is not sufficient information for the model binder to make any distinction about which of the derived types it constructed without extra information being provided.
0

Jonah, You should use one model for a view. Now you can do two things

First thing,

you can use custom model binder see here http://www.codeproject.com/Articles/605595/ASP-NET-MVC-Custom-Model-Binder

or (Second thing),

in Html.Beginform also place hidden field to for identifying type (like 1 for ClassOne , 2 for ClassTwo). and now create a third class which has distinct property of both ClassTwo and ClassOne , common property of BaseClass and a extra property for type information.(do not use any type of validation here) for the post use the newly created type, then check the type field.

Comments

0

your problem is action can't judge which type.because view to action the type is loose. but we can get type at view and send the type to the action.

view like this: @model MvcApplication.Models.BaseClass

 @using(Html.BeginForm("Post","Test",FormMethod.Post))
 {
        @Html.HiddenFor(model => mode.Id)
        @Html.TextBoxFor(model => model.Name)
        @Html.Hidden("type", model.GetType().Tostring())

        <input type="submit" value="Submit"/>
 }

action like this:

[HttpPost]
 public ActionResult Post(BaseClass model)
 {
      /* Code */
      if(Request["type"] == typeof( ClassOne).Tostring())
      {
      } 
      if(Request["type"] == typeof( ClassTwo ).Tostring())
      {
      } 
 }

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.