Alexander Taran
Alexander Taran

Reputation: 6725

How do I access query string parameters in asp.net mvc?

I want to have different sorting and filtering applied on my view I figured that I'll be passing sorting and filtering params through query string:

@Html.ActionLink("Name", "Index", new { SortBy= "Name"})

This simple construction allows me to sort. View comes back with this in query string:

?SortBy=Name

Now I want to add filtering and i want my query string to end up with

?SortBy=Name&Filter=Something

How can I add another parameter to list of already existing ones in ActionLink? for Example:

user requests /Index/

view has

 @Html.ActionLink("Name", "Index", new { SortBy= "Name"})

and

 @Html.ActionLink("Name", "Index", new { FilterBy= "Name"})

Links: The first one looks like /Index/?SortBy=Name and The second is /Index/?FilterBy=Name

I want when user pressed sorting link after he applied some filtering - filtering is not lost, so i need a way to combine my params. My guess is there should be a way to not parse query string, but get collection of parameters from some MVC object.

Upvotes: 40

Views: 68106

Answers (5)

user170868
user170868

Reputation: 41

Use ActionLinkCombined instead of ActionLink

        public static string ActionLinkCombined(this HtmlHelper htmlHelper, string linkText, string actionName,
                                            object routeValues)
    {
        var dictionary = new RouteValueDictionary();
        foreach (var pair in htmlHelper.ViewContext.Controller.ValueProvider)
            dictionary[pair.Key] = pair.Value.AttemptedValue;
        if (routeValues != null)
        {
            foreach (PropertyDescriptor descriptor in TypeDescriptor.GetProperties(routeValues))
            {
                object o = descriptor.GetValue(routeValues);
                dictionary[descriptor.Name] = o;
            }
        }
        return htmlHelper.ActionLink(linkText, actionName, dictionary);
    }

Upvotes: 4

Brian Cauthon
Brian Cauthon

Reputation: 5534

My solution is similar to qwerty1000's. I created an extension method, ActionQueryLink, that takes in the same basic parameters as the standard ActionLink. It loops through Request.QueryString and adds any parameters found to the RouteValues dictionary that are not already present (so we can overwrite the original query string if needed).

To preserve the existing string but not add any keys the usage would be:

<%= Html.ActionQueryLink("Click Me!","SomeAction") %>

To preserve the existing string and add new keys the user would be:

<%= Html.ActionQueryLink("Click Me!","SomeAction", new{Param1="value1", Param2="value2"} %>

The code below is for the two usages, but it should be pretty easy to add other overloads to match the other ActionLink extensions as needed.

    public static string ActionQueryLink(this HtmlHelper htmlHelper,
        string linkText, string action)
    {
        return ActionQueryLink(htmlHelper, linkText, action, null);
    }

    public static string ActionQueryLink(this HtmlHelper htmlHelper, 
        string linkText, string action, object routeValues)
    {
        var queryString =
            htmlHelper.ViewContext.HttpContext.Request.QueryString;

        var newRoute = routeValues == null 
            ? htmlHelper.ViewContext.RouteData.Values 
            : new RouteValueDictionary(routeValues);

        foreach (string key in queryString.Keys)
        {
            if (!newRoute.ContainsKey(key)) 
                newRoute.Add(key, queryString[key]);
        }
        return HtmlHelper.GenerateLink(htmlHelper.ViewContext.RequestContext,
            htmlHelper.RouteCollection, linkText, null /* routeName */, 
            action, null, newRoute, null);
    }

Upvotes: 12

Alexander Taran
Alexander Taran

Reputation: 6725

so far the best way I figured out is to create a copy of ViewContext.RouteData.Values and inject QueryString values into it. and then modify it before every ActionLink usage. still trying to figure out how to use .Union() instead of modifying a dictionary all the time.

<% RouteValueDictionary   tRVD = new RouteValueDictionary(ViewContext.RouteData.Values); %>

<% foreach (string key in Request.QueryString.Keys )
    {
         tRVD[key]=Request.QueryString[key].ToString();
    } %>

<%tRVD["SortBy"] = "Name"; %>
                <%= Html.ActionLink("Name", "Index", tRVD)%>

Upvotes: 30

syed Ahsan Jaffri
syed Ahsan Jaffri

Reputation: 1124

MVC4

@Html.ActionLink("link text","action",new { @id = 5, @name = "textName", @abc = "abc" })

OR

 @Html.ActionLink("link text", "action", "controller", new { @id = 5, @name = "textName", @abc = "abc" }, new { @class = "cssClass" })

querystring would be like:

yourDomainRout/action/5?name=textName&abc=abc

it would have class="cssClass"

Upvotes: 2

Mehrdad Afshari
Mehrdad Afshari

Reputation: 422320

<%= Html.ActionLink("Name", "Index", new { SortBy= "Name", Filter="Something"}) %>

To preserve the querystring you can:

<%= Html.ActionLink("Name", "Index", 
     String.IsNullOrEmpty(Request.QueryString["SortBy"]) ? 
        new { Filter = "Something" } : 
        new { SortBy=Request.QueryString["SortBy"], Filter="Something"}) %>

Or if you have more parameters, you could build the link manually by using taking Request.QueryString into account.

Upvotes: 8

Related Questions