0

I've got a view that looks like this: enter image description here

With this view I'm filtering records which are in a database. Each "filter" is a SearchViewModel which has a class definition like this:

public class SearchViewModel
{
   //Property has a property called "SqlColumnName"
   public Property Property { get; set; }
   public Enums.SearchOperator Operator { get; set; }
   public string Value { get; set; }
}

I'm now trying to find a solution how to build a actionlink to this site and passing in a List<SearchViewModel>(). So I'm trying to accomplish something like this: http://url/Index?property=Typ&Operator=2&Value=4&property=ServerName&Operator=1&Value=server

I've tried to solve my problem with this http://haacked.com/archive/2008/10/23/model-binding-to-a-list.aspx/ but this guy is calling the Action with a POST and i need to call it with a GET request.

So how to pass a list of objects to a mvc controller action with an actionlink?

EDIT

I think i need to say, that POST request is not an option because i need that link in an onClick event of a div element.

M.G
  • 1,061
  • 9
  • 19
  • You should not try to pass complex data via a GET request. You should use POST. – Shyju Jan 04 '16 at 15:42
  • Have you try, in second link solution, to change the Action from POST to GET and see the result? – erikscandola Jan 04 '16 at 15:44
  • Actually, GET is not for sending a lot of data to server. You should use POST request for it, query string or use additional query params if you want to achieve this with GET – Andrew Jan 04 '16 at 15:51
  • I've tried to change the action to GET and yes this gives me the right output in a test environment but this link need to be stored in an c# object which will generate a morris.js donut and the onclick event will then use this link – M.G Jan 04 '16 at 15:52

2 Answers2

0

You could construct a link with the following parameters that should work:

http://url/Index?%5B0%5D0.property=Typ&%5B0%5D0.Operator=2&%5B0%5D0.Value=4&%5B1%5D0.property=ServerName&%5B1%5D0.Operator=1&%5B1%5D0.Value=server

Also notice that there are restrictions in the length of query string parameters. Those restrictions vary between the browsers. So it's probably a better approach to simply generate a link with an id that would allow you to retrieve the corresponding collection on the server (from your datastore):

http://url/Index?id=123
Darin Dimitrov
  • 1,023,142
  • 271
  • 3,287
  • 2,928
0

ActionLink helper method renders an anchor tag. It is ok to pass few query string items via a link. Remember Query string has a limit about how much data you can pass and it varies from browser to browser.

What you should be doing is a form posting. You can do a form posting on a click event on a div with the help of a little javascript.

Let's create a new view model for our search page

public class SearchVm
{
    public List<SelectListItem> Operators { set; get; } 
    public List<SearchViewModel> Filters { set; get; }
}
public class SearchViewModel
{
    //Property has a property called "SqlColumnName"
    public Property Property { get; set; }
    public SearchOperator Operator { get; set; }
    public string Value { get; set; }
}

So in your GET action, You will send a list of SearchViewModel to the view.

public ActionResult Index()
{
    var search = new SearchVm
    {
        Filters = new List<SearchViewModel>
        {
            new SearchViewModel {Property = new Property {SqlColumn = "Name"}},
            new SearchViewModel {Property = new Property {SqlColumn = "Age"}},
            new SearchViewModel {Property = new Property {SqlColumn = "Location"}}
        }
    };
   //Convert the Enums to a List of SelectListItem 
   search.Operators= Enum.GetValues(typeof(SearchOperator)).Cast<SearchOperator>()
        .Select(v => new SelectListItem
        {
            Text = v.ToString(),
            Value = ((int)v).ToString()
        }).ToList();

   return View(search);

}

And in your view, which is strongly typed to your SearchVm view model, We will manipulate the form field names so that the model binding will work when the form is submitted.

@model SearchVm    
@using (Html.BeginForm())
{
    var i = 0;
    foreach (var criteria in Model.Filters)
    {
        <label>@criteria.Property.SqlColumn</label>

        @Html.HiddenFor(f => f.Filters[i].Property.SqlColumn)            
        @Html.DropDownList("Filters[" + i+ "].Operator",Model.Operators)
        @Html.TextBoxFor(f=>f.Filters[i].Value)
        i++;
    }
    <div id="someDiv">Search button using Div</div>
    <input type="submit" value="Search" />
}

And your HttpPost action method to handle the form submit.

[HttpPost]
public ActionResult Index(SearchVm model)
{
   foreach(var f in model.Filters)
   {
     //check f.Property.SqlColumn, f.Value & f.Operator            
   }
  // to do :Return something useful
}

If you want the form to be submitted on the click event on the div, Listen to the click event on the specific div and call the submit method on the form the div resides in.

<script>
 $(function () {
     $("#someDiv").click(function(e) {
         $(this).closest("form").submit();
     });
 });
</script>
Community
  • 1
  • 1
Shyju
  • 214,206
  • 104
  • 411
  • 497
  • Thanks for your hard work, but unfortunately the way you descriped is the next step in my workflow. My workflow looks like this: an ActionLink calls the Action "Index". The action renders the SearchFilters and present them to the user. A search button will send this filters to another action which is calling the database. My need is to pre set those filters in the "Index" action. – M.G Jan 05 '16 at 06:47