views:

182

answers:

2

Hi,

I have a View for creating a customer that contains numerous textboxes. After the user tabs out of each textbox I want to use JQuery to call a Controller method that will check in the DataBase and look for any possible matches, the controller will then send content and I will use jQuery to dynamically show the possible matches (Similar to what Stack Overflow does when you enter in your question and shows Related Questions).

My question is, I have 15 textboxes and would like to send that data from each back with each call. I'd like to avoid having my Controller method with a signature like

Public ActionResult CheckMatches(string param1, string param2... string param15)

Is there an easier way to pass multiple paramers as a single object, like FormCollection?

A: 

Javascript:

 var data = { foo: "fizz", bar: "buzz" };
 $.get("urlOfAction", data, callback, "html")

Action:

 public ActionResult FooAction(MegaParameterWithLotOfStuff param)

And a custom model binder:

public class MegaParameterWithLotOfStuffBinder : IModelBinder
{
    public object GetValue(ControllerContext controllerContext,
        string modelName, Type modelType,
        ModelStateDictionary modelState)
    {
        var param = new MegaParameterWithLotOfStuff();

        param.Foo = controllerContext.
            HttpContext.Request.Form["foo"];
        param.Bar = controllerContext.
            HttpContext.Request.Form["bar"];

        return customer;
    }
}

Global.asax:

protected void Application_Start()
{
    ModelBinders.Binders[typeof(MegaParameterWithLotOfStuff)] =
        new MegaParameterWithLotOfStuffBinder();
}

Or binding filter+action combo:

 public class BindMegaParamAttribute: ActionFilterAttribute
    {
        public override void OnActionExecuting
             (ActionExecutingContext filterContext)
        {
            var httpContext = filterContext.HttpContext;

            var param = new MegaParameterWithLotOfStuff();

            param.Foo = httpContext.Request.Form["foo"];
            param.Bar = httpContext.Request.Form["bar"];

            filterContext.ActionParameters["param"] = param;
            base.OnActionExecuted(filterContext);
        }
    }

Action:

[BindMegaParam]
public ActionResult FooAction(MegaParameterWithLotOfStuff param)
Arnis L.
You don't need a custom model binder to do that; the default model binder will work.
Craig Stuntz
When using the Binding Filter+action combo example that you gave, what object is the [BindMegaParam] given for the actionResult? How does this know to use the BindMegaParamAttribute? Is this the convention over configuration and it appends Attribute to the object name given?
Fermin
Yes, it is. "Attribute" part is optional when you apply attribute.
Arnis L.
I know Craig. Realized that when i was finished to wrote that long stuff and felt kind a stupid. Then thought - there should be more info for a proper info (my approach is more flexible if params needs to be changed) and then just drop it and left for any comments. :)
Arnis L.
i mean - more info for a proper answer...
Arnis L.
+3  A: 

All you need to do is create a type with properties the same name as the names of your textboxes:

public class CheckMatchesAguments
{
    public string Param1 { get; set; }
    public string Param2 { get; set; }
    // etc.
}

Then change your action to:

public ActionResult CheckMatches(CheckMatchesAguments arguments)

That's all!

Be warned, though: If CheckMatchesAguments has any non-nullable properties (e.g., ints), then values for those properties must be in the FormCollection, or the default model binder won't bind anything in the type. To fix this, either include those properties, too, in the form, or make the properties nullable.

Craig Stuntz