How do you persist querystring values in asp.net mvc?
Asked Answered
R

4

14

What is a good way to persist querystring values in asp.net mvc?

If I have a url: /questions?page=2&sort=newest&items=50&showcomments=1&search=abcd

On paging links I want to keep those querystring values in all the links so they persist when the user clicks on the "next page" for example (in this case the page value would change, but the rest would stay the same)

I can think of 2 ways to do this:

  1. Request.Querystring in the View and add the values to the links
  2. Pass each querystring value from the Controller back into the View using ViewData

Is one better than the other? Are those the only options or is there a better way to do this?

Ribbon answered 20/5, 2009 at 19:19 Comment(0)
B
7

I would process the QueryString in the view (your option #1), instead of passing it in from the controller. This approach makes the view more self-contained, allowing you to convert it into a view control and re-use it across different views.

Note: Accessing the QueryString directly in the view may seem like a violation of the design principle of separating the Model and View, but in reality this data is a navigational concern which is related to the view, not really part of the model.

Beaty answered 20/5, 2009 at 20:57 Comment(1)
Thanks for the input and reasoning. Your note is exactly the reason I thought of passing it through ViewData.Ribbon
C
8

i use a extension method for that:

public static string RouteLinkWithExtraValues(
        this HtmlHelper htmlHelper,
        string name,
        object values)
    {
        var routeValues = new RouteValueDictionary(htmlHelper.ViewContext.RouteData.Values);

        var extraValues = new RouteValueDictionary(values);
        foreach (var val in extraValues)
        {
            if (!routeValues.ContainsKey(val.Key))
                routeValues.Add(val.Key, val.Value);
            else
                routeValues[val.Key] = val.Value;
        }

        foreach (string key in htmlHelper.ViewContext.HttpContext.Request.Form)
        {
            routeValues[key] = htmlHelper.ViewContext.HttpContext.Request.Form[key];
        }

        foreach (string key in htmlHelper.ViewContext.HttpContext.Request.QueryString)
        {
            if (!routeValues.ContainsKey(key) && htmlHelper.ViewContext.HttpContext.Request.QueryString[key] != "")
                routeValues[key] = htmlHelper.ViewContext.HttpContext.Request.QueryString[key];
        }

        var urlHelper = new UrlHelper(htmlHelper.ViewContext.RequestContext);

        return string.Format("<a href=\"{0}\">{1}</a>", urlHelper.RouteUrl(routeValues), name);
    }
Croy answered 20/5, 2009 at 20:24 Comment(1)
I never thought of this. It looks interesting but maybe too complicated for me. I was hoping there was some MVC convention that does this without having to write lines of code.Ribbon
B
7

I would process the QueryString in the view (your option #1), instead of passing it in from the controller. This approach makes the view more self-contained, allowing you to convert it into a view control and re-use it across different views.

Note: Accessing the QueryString directly in the view may seem like a violation of the design principle of separating the Model and View, but in reality this data is a navigational concern which is related to the view, not really part of the model.

Beaty answered 20/5, 2009 at 20:57 Comment(1)
Thanks for the input and reasoning. Your note is exactly the reason I thought of passing it through ViewData.Ribbon
M
1

I would just keep the values in the Session that way the paging links only need to have;

/questions?page=2

/questions?page=3

The one reason why I would not us the QueryString is because I don't want the user to see the values that I am passing to the program. It makes it way too easy for them to go into the address bar and start changing the values to 'see what happens'. With this code all they could do is change the page number.

Manon answered 20/5, 2009 at 20:7 Comment(2)
That is something I thought of for a second but wanted keep it in the querystring.Ribbon
a good reason you would want to leave &sort=newest&items=50&showcomments=1&search=abcd in the querystring is so that people can bookmark the search. Is there any reason you wouldn't want people to directly edit the &search= value in the querysting and 'see what happens'?Angkor
C
0

Here's how I done it in Asp.Net Core, first assign the query string parameters to ViewBags in your controller:

[HttpGet("/[controller]/[action]/{categoryId?}/{contractTypeId?}/{locationId?}")]
public IActionResult Index(Guid categoryId, int contractTypeId, Guid locationId)
{
    ViewBag.CategoryId = categoryId;
    ViewBag.ContractTypeId = contractTypeId;
    ViewBag.LocationId = locationId;

    ...
}

Then pass the values to your links like so:

<a asp-action="Index" asp-controller="Jobs"
   asp-route-categoryId="@teachingCategory.Id"
   asp-route-contractTypeId="@ViewBag.ContractTypeId"
   asp-route-locationId="@ViewBag.LocationId">
   @teachingCategory.Description (@teachingCategory.Rank)
</a>

<a asp-action="Index" asp-controller="Jobs"
   asp-route-categoryId="@ViewBag.CategoryId"
   asp-route-contractTypeId="@typeOfEmployment.Id"
   asp-route-locationId="@ViewBag.LocationId">
   @typeOfEmployment.Name
</a>

<a asp-action="Index" asp-controller="Jobs"
   asp-route-categoryId="@ViewBag.CategoryId"
   asp-route-contractTypeId="@ViewBag.ContractTypeId"
   asp-route-locationId="@item.Id">
   @item.Id
</a>

Note that every link keep its own actual value and pass the rest of the route values through what we passed to ViewBag.

Channelize answered 1/3, 2018 at 13:34 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.