6

I'm passed a list of parameters. Such as "Name", "Id", "Type". There will be an many of these in url, like so:

"Name=blah1,Id=231,Type=blah1;Name=blah2,Id=2221,Type=blah1;Name=blah3,Id=45411,Type=blah3;"

I wonder if there is a way to map these query parameters to a List of objects. So, I can create an object:

MyTestObject {Name;Id;Type} and can say in my controller

Index(IList<MyTestObject> params)

params will be filled in with data from query string.

Something that is similar to http://haacked.com/archive/2008/10/23/model-binding-to-a-list.aspx

tereško
  • 58,060
  • 25
  • 98
  • 150
dev.e.loper
  • 35,446
  • 76
  • 161
  • 247
  • Have you tried implementing what was suggested in that link? I've used it before and it fulfilled my needs. – Dirk Jul 18 '11 at 20:51

5 Answers5

5

I actually followed advice in the article by Mr. Haack I created a class with all of the parameters as public properties. Then I had a view take a list of objects of that type. If the query parameter names follow a certain pattern (prepended by index) then I get a list of my object automatically populated and I don't have to do any manual parsing at all. This is the simplest solution for me.

Example:

query param object:

public class QueryParams
{
   public string Id,
   public string Name,
   public string Type
}

in controller method:

public ActionResult Index(IList<QueryParams> queryData)

then I make sure that query string is formated in the following way(prepended by index):

http://localhost/myapp/?[0].id=123&[0].Name=blah&[0].Type=Person&[1].Id=345&[1].Name=example&[1].Type=Stuff

In my controller, queryData list parameter will contain two objects populated with correct data.

dev.e.loper
  • 35,446
  • 76
  • 161
  • 247
4

You can you a values provider, and it will populate values from the querystring into a single object. This is what you would do if you're not going to create a View Model.

Transform the QueryString into a FormCollection via:

var GetCollection = new FormCollection( Request.QueryString );
Lucent Fox
  • 1,737
  • 1
  • 16
  • 24
3

You could create a custom model binder, that works off the Request.QueryString collection, rather than the regular FormCollection.

E.g:

public class MyTestObjectModelBinder : DefaultModelBinder 
{
    public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext) 
    {
        var qs = controllerContext.HttpContext.Request.QueryString;                  
        return new MyTestObject
        {
           Name = qs["Name"],
           Id = qs["Id"],
           // etc, etc
        };
    }
}

Then setup your [HttpGet] action accordingly:

[HttpGet]
public ActionResult Index([ModelBinder(typeof(MyTestObjectModelBinder))]MyTestObject m) {

}

You could also register it globally if you like, e.g on Application_Start() :

ModelBinders.Binders.Add(typeof(MyTestObject), new MyTestObjectModelBinder());

Then you just need the model on your action:

[HttpGet]
public ActionResult Index(MyTestObject m) {

}

Having said all of this, if you've got this many parameters, one must ask where do these parameters come from? Most likely a form on another page.

In which case, this should be a [HttpPost] action, with the parameters in the form collection, then the regular MVC model binding will take care of the above code for you.

RPM1984
  • 72,246
  • 58
  • 225
  • 350
  • 1
    +1 I was thinking a custom model binder too, but too lazy to write my own answer. – CRice Jul 19 '11 at 01:25
  • @RPM1984 Can I do the following? It seems to be a simple solution. http://stackoverflow.com/questions/6739211/asp-net-mvc-get-list-of-objects-from-query-string/6748667#6748667 – dev.e.loper Jul 19 '11 at 14:21
  • @dev.e.loper - if it works for you, sure. However it might make maintenance difficult, since it's not immediately clear how the binding it working, and you have to maintain two places (generation of URL, and the model convention). Custom model binders make it explicit, and a single place to maintain the binding. However, whatever works for you. – RPM1984 Jul 19 '11 at 23:26
1

Yes, ASP.NET MVC could automatically bind collections to action params, but you need to pass your params as a from values, moreover, it is looks like to many params you going pass in query string. Have look at this one http://weblogs.asp.net/nmarun/archive/2010/03/13/asp-net-mvc-2-model-binding-for-a-collection.aspx

Basically what you need to do:

1) Create your class which would contain your params

public class MyParam 
{
 public int Id {get; set;}
 public string Name {get; set;}

 //do all the rest
}

2) Create model which you would pass to your view

public class MyViewModel
{
  IList<MyParam> MyParams {get; set;}
}

3) Create your collection in your [HttpGet] action and pass that to your view:

[HttpGet]
public virtual ActionResult Index()
{
   MyViewModel model = new MyViewModel();
   model.MyParams = CreateMyParamsCollection();

   return View(model);
}

4) Iterate your collection in the view

@model MyViewModel

@{int index = 0;}

@foreach (MyParam detail in Model.MyParams)
{
  @Html.TextBox("MyParams[" + index.ToString() + "].Id", detail.Id)
  @Html.TextBox("MyParams[" + index.ToString() + "].Name", detail.Name)

  index++;
} 

5) Than on your [HttpPost] action you may catch your params in collection

[HttpPost]
public virtual ActionResult Index(MyViewModel model)

or

[HttpPost]
public virtual ActionResult Index(IList<MyParam> model)

P.S

Moreover, if you want to get all your form params in controller you may simple go like that:

[HttpPost]    
public virtual ActionResult Index(FormCollection form)
Sviatoslav V.
  • 671
  • 6
  • 18
angularrocks.com
  • 26,767
  • 13
  • 87
  • 104
0

On a related note, I was looking for a way to enumerate through the QueryString name-value collection, and this is what I came up with:

        var qry =HttpContext.Request.QueryString;

        if (qry.HasKeys())
        {
            foreach (var key in qry)
            {
                if(key != null)
                    var str= String.Format("Key:{0}, value:{1} ", key, qry.Get(key.ToString()));
            }
        }

This code will give you all the names and their values in the QueryString.

Erik K.
  • 1,024
  • 12
  • 13
  • You can't use the str variable declaration in a for each statement. The str variable declaration should be before the for each statement. – miguelbgouveia Sep 10 '15 at 09:06
  • Does not really matter. See the following comment http://stackoverflow.com/questions/1884906/declaring-a-variable-inside-or-outside-an-foreach-loop-which-is-faster-better#comment1785311_1884957 – Erik K. Sep 10 '15 at 15:25
  • The problem is when the code is compiled in Visual Studio 2013 we get a compiler error if you declare the variable in a for each loop. Maybe there is some configuration that could prevent this, but by default we get that compiler error. – miguelbgouveia Sep 10 '15 at 16:17