Daniel Moses
Daniel Moses

Reputation: 5858

.NET MVC Action parameter of type object

If I have a simple controller routed as follows:

context.MapRoute(
            "Default",
            "{controller}/{action}",
            new { controller = "Base", action = "Foo"}
        );

And the controller Foo action is as follows:

[HttpPost]
public ActionResult Foo(object bar) { ... }

How will bar be bound? I have debugged and see it is a string, but I'm not sure if it will always be marshalled to a string.

Basically I want to have the method accept a bool, List<int>, and int. I can send up a type parameter and do the model binding myself from the post. (The post is a form post).

Here are my current posts &bar=False or &bar=23 or &bar[0]=24&bar[1]=22.

I know I can look at the post inside the Foo action method, but I want some input on the best way to handle this in MVC3

Upvotes: 4

Views: 4784

Answers (2)

moribvndvs
moribvndvs

Reputation: 42497

A custom model binder is one option, which you could apply to your parameter. Your binder could do best guess at the type (unless MVC gets a better hint from the context, it will just assume string). However, that won't give you strongly typed parameters; you'd have to test and cast. And while that's no big deal...

Another possibility which would give you strong typing in your controller actions would be to create your own filter attribute to help MVC figure out which method to use.

[ActionName("SomeMethod"), MatchesParam("value", typeof(int))]
public ActionResult SomeMethodInt(int value)
{
   // etc
}

[ActionName("SomeMethod"), MatchesParam("value", typeof(bool))]
public ActionResult SomeMethodBool(bool value)
{
   // etc
}

[ActionName("SomeMethod"), MatchesParam("value", typeof(List<int>))]
public ActionResult SomeMethodList(List<int> value)
{
   // etc
}


public class MatchesParamAttribute : ActionMethodSelectorAttribute
{
     public string Name { get; private set; }
     public Type Type { get; private set; }

     public MatchesParamAttribute(string name, Type type)
     { Name = name; Type = type; }

     public override bool IsValidForRequest(ControllerContext context, MethodInfo info)
     {
             var val = context.Request[Name];

              if (val == null) return false;

             // test type conversion here; if you can convert val to this.Type, return true;

             return false;
     }
}

Upvotes: 3

Richard
Richard

Reputation: 22016

In this case I would probably create a custom ModelBinder:

http://buildstarted.com/2010/09/12/custom-model-binders-in-mvc-3-with-imodelbinder/

then maybe use a dynamic object to allow for multiple types. See here

MVC3 ModelBinder for DynamicObject

Upvotes: 3

Related Questions