0

Is it possible for an action controller to accept a literal object. For example, I have several views in which I would like to post various models from to a single controller that can then determine the incoming model object for further processing.

Model sample:

public class Model1
{
   // properties, etc.
}

public class Model2
{
   // properties, etc.
}

public class Model3
{
   // properties, etc.
}

controller sample:

[HttpPost]
public ActionResult ProcessModel(Object anyModel)
{
   // determine the model
   if((anyModel as Model1) != null)
   {
     var model1 = anyModel as Model1;
     // continue with code
   }
   else if((anyModel as Model2) != null)
   {
     var model2 = anyModel as Model2;
     // continue with code
   }
   // continue with model check, etc.       
}

I've tried, but my controller does not appear to be picking up the model as my object parameter remains empty. Is this possible?

user1206480
  • 1,798
  • 3
  • 28
  • 45

3 Answers3

7

Have a quick read about how model binding works... The model binder (which takes whatever is posted to your Action and turns it into the anyModel parameter uses the type of the parameter to determine what to do.

Since the type is Object it can't do anything.

My guess (depending on what you're trying to achieve) is that you can have several Action overloads each with a different type of Model as the parameter which then call common code.

[HttpPost]
public ActionResult ProcessModel(Model1 anyModel){}

[HttpPost]
public ActionResult ProcessModel(Model2 anyModel){}

[HttpPost]
public ActionResult ProcessModel(Model3 anyModel){}

That said it's a bit odd to have one action which takes lots of different models. There's a good chance you're better off doing something else.

Your question might gather a better answer if you say what you're trying to achieve

Paul D'Ambra
  • 7,629
  • 3
  • 51
  • 96
  • 3
    I don't think you can have multiple actions with the same name (regardless of parameters). – zimdanen Aug 01 '13 at 21:54
  • 3
    The parameters have to be different types. http://csharpindepth.com/Articles/General/Overloading.aspx – Paul D'Ambra Aug 01 '13 at 21:55
  • 1
    Although having just re-read your comment (probably time for me to sleep) @zimdanen - yep... while you can definitely have methods overloaded that way and Actions *should* just be methods I've never actually done it so don't know if MVC or model binding would barf – Paul D'Ambra Aug 01 '13 at 21:57
  • 2
    There you go... http://stackoverflow.com/a/436935/222163 MVC does barf but you can add an attribute to each Action to distinguish them. That said I do think it's better to do something else instead :) – Paul D'Ambra Aug 01 '13 at 22:02
2

The Default Asp.NET ModelBinder cannot bind generic Objects this way. You should take a look here to understand how the model will be build back in the server by the DefaultModelBinder: Understanding ASP.NET MVC Model Binding.

Given that your form has many Models, you should encapsulate them into a ViewModel to do this kind of operation.

The ViewModel should looks like this:

public class MyViewModel
{
  public Model1 Model1 {get; set;}
  public Model1 Model2 {get; set;}
  public Model1 Model3 {get; set;}
}

And the controller:

[HttpPost]
public ActionResult ProcessModel(MyViewModel myViewModel)
{
  // determine the model
  if(myViewModel.Model1 != null)
  {
    // continue with code
  }
  else if(myViewModel.Model2 != null)
  {
    // continue with code
  }
  // continue with model check, etc.       
}
Fals
  • 6,813
  • 4
  • 23
  • 43
1

Recently I faced the same issue and resolved it as below:

Step 1: From javascript pass 2 parameter :

First, pass model name as String for identification which model is coming

Second, Pass data from javascript using JSON.stringify(data). where your data can be from Model1, Model2 , Model3 etc.

Step2: In your controller:

[HttpPost]
public ActionResult ProcessModel(string modelName, string anyModel)
{
   switch(modelName)  {
      case "Model1":
             var modelValue= JsonDeserialize<Model1>(anyModel);
              // do something 
           break;
     case "Model2": 
            var modelValue= JsonDeserialize<Model2>(anyModel); 
            // do something
           break;
    }
}

You Need One method like below:

public T JsonDeserialize<T>(string jsonModel){
return JsonConvert.DeserializeObject<T>(jsonModel, jsonSettings);
}

JsonConvert need namespace "Newtonsoft.Json".

You also need to declare jsonSettings as below

         JsonSerializerSettings jsonSettings= new JsonSerializerSettings
    {
        TypeNameHandling = TypeNameHandling.All,
        DefaultValueHandling = DefaultValueHandling.Ignore
    };

This solution is kind of workaround. There is one more solution. you can check that also: How can I make a Controller Action take a dynamic parameter?

Hope this helps.

Community
  • 1
  • 1
Tapash
  • 762
  • 9
  • 7