Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I use Url.Action with list parameters?

Say I have an action method:

[HttpGet]
public ActionResult Search(List<int> category){
    ...
}

The way the MVC model binding works, it expects a list of category like this:

/search?category=1&category=2

So my questions are:

How do I create that link using Url.Action() if I just hardcode it?

Url.Action("Search", new {category=???}) //Expect: /search?category=1&category=2

How do I create that link using Url.Action() if my input is a list of int?

var categories = new List<int>(){1,2}; //Expect: /search?category=1&category=2

Url.Action("Search", new {category=categories}) //does not work, 
like image 250
Kjensen Avatar asked Feb 14 '14 17:02

Kjensen


People also ask

What is url action?

A URL action is a hyperlink that points to a web page, file, or other web-based resource outside of Tableau. You can use URL actions to create an email or link to additional information about your data.

How do you pass a model object in url action?

You can convert the model into an JSON object by using the the build-in JSON-helper,like this: $(this). load('@Url. Action("CreatePartial")',@Html.


Video Answer


3 Answers

Instead of using an Anonymous Type, build a RouteValueDictionary. Format the parameters as parameter[index].

@{
    var categories = new List<int>() { 6, 7 };

    var parameters = new RouteValueDictionary();

    for (int i = 0; i < categories.Count; ++i)
    {
        parameters.Add("category[" + i + "]", categories[i]);
    }
}

Then,

@Url.Action("Test", parameters)
like image 119
Sam B Avatar answered Oct 16 '22 20:10

Sam B


Build the querystring yourself, it's evident that UrlHelper was not designed for this use case.

Using:

   static class QueryStringBuilder {

      public static string ToQueryString(this NameValueCollection qs) {
         return ToQueryString(qs, includeDelimiter: false);
      }

      public static string ToQueryString(this NameValueCollection qs, bool includeDelimiter) {

         var sb = new StringBuilder();

         for (int i = 0; i < qs.AllKeys.Length; i++) {

            string key = qs.AllKeys[i];
            string[] values = qs.GetValues(key);

            if (values != null) {
               for (int j = 0; j < values.Length; j++) {

                  if (sb.Length > 0)
                     sb.Append('&');

                  sb.Append(HttpUtility.UrlEncode(key))
                     .Append('=')
                     .Append(HttpUtility.UrlEncode(values[j]));
               }
            }
         }

         if (includeDelimiter && sb.Length > 0)
            sb.Insert(0, '?');

         return sb.ToString();
      }
   }

You can write this:

var parameters = new NameValueCollection {
  { "category", "1" },
  { "category", "2" }
};

var url = Url.Action("Search") + parameters.ToQueryString(includeDelimiter: true);
like image 3
Max Toro Avatar answered Oct 16 '22 18:10

Max Toro


Instead Type Casting to “object” or “object[]” or using RouteValueDictionary. A simple way to achieve the same is using “Newtonsoft.Json”

If using .Net Core 3.0 or later;

Default to using the built in System.Text.Json parser implementation.

@using System.Text.Json;

…….

@Url.Action(“ActionName”, “ControllerName”, new {object = JsonConvert.SerializeObject(‘@ModalObject’)  }))

If stuck using .Net Core 2.2 or earlier;

Default to using Newtonsoft JSON.Net as your first choice JSON Parser.

@using Newtonsoft.Json;

…..

@Url.Action(“ActionName”, “ControllerName”, new {object = JsonConvert.SerializeObject(‘@ModalObject’)  }))

you may need to install the package first.

PM> Install-Package Newtonsoft.Json

Then,

public ActionResult ActionName(string modalObjectJSON)
{
    Modal modalObj = new Modal();
    modalObj = JsonConvert.DeserializeObject<Modal>(modalObjectJSON);

}
like image 1
Siddarth Modi Avatar answered Oct 16 '22 20:10

Siddarth Modi