views:

219

answers:

2

http:www.site1.com/?sid=555

I want to be able to have the sid parameter and value persist whether a form is posted or a link is clicked.

If the user navigates to a view that implements paging, then the other parameters in the querystring should be added after the sid.

http:www.site1.com/?sid=555&page=3

How can I accomplish this in Asp.Net Mvc 2?

[Edit]

The url I mentioned on top would be the entry point of the application, so the sid will be included in the link.

Within the application links like:

<%= Html.ActionLink("Detail", "Detail", new { controller = "User", 
                                              id = item.UserId })%>

should go to:
http:www.site1.com/user/detail/3?sid=555

This question is different than what Dave mentions, as the querystring parameter is persisting throughout the site.

A: 

Possible Duplicate:

http://stackoverflow.com/questions/889732/how-do-you-persist-querystring-values-in-asp-net-mvc

I agree with the accepted answer to the question linked above. Querystring parameters are not designed for data persistence. If a setting (i.e. sid=555) is intended to persist through a session, use Session state or your Model to save that data for use across requests.

Dave Swersky
+1  A: 

Firstly, I'd say if the value needs to be persisted throughout the session then you should store it in Session and check that its still valid on each action call. This can be done through a custom action attribute you add to the controller / actions required. If the value is required then when the value is checked you can re-drect to a login page or similar if not present or its expired.

Anyway, that said I thought I'd have a crack at getting it working. My first thought would be to create a custom action filter attribute which took the value of the querstring and stored it in session in OnActionExecuting and then OnResultExecuted would add the key back to the querystring. But as QueryString in Request is a read-only collection you can't do it directly.

So, whats now available to you?

Option #1 - Add it to all calls to Html.ActionLink() manually

or ...

Option #2 - Override a version of ActionLink which automatically adds the value for you. This can be achived like so. I wouldn't recommend doing this though.

Start off with the custom attribute.

public class PersistQueryStringAttribute : ActionFilterAttribute
{
    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        var sid = filterContext.RequestContext.HttpContext.Request.QueryString["sid"];

        if (!string.IsNullOrEmpty(sid))
        {
            filterContext.RequestContext.HttpContext.Session["sid"] = sid;
        }

        base.OnActionExecuting(filterContext);
    }
}

All this does is check the request querystring for the required key and if its available add it into the session.

Then you override ActionLink extention method to one of your own which adds the value in.

public static class HtmlHelperExtensions
{
    public static MvcHtmlString ActionLink<TModel>(this HtmlHelper<TModel> helper, string text, string action, string controller, object routeValues)
    {
        var routeValueDictionary = new RouteValueDictionary(routeValues);

        if (helper.ViewContext.RequestContext.HttpContext.Session["sid"] != null)
        {
            routeValueDictionary.Add("sid", helper.ViewContext.RequestContext.HttpContext.Session["sid"]);    
        }

        return helper.ActionLink(text, action, controller, routeValueDictionary, null);
    }
}

On each of the action which is going to be called apply the attribute (or apply it to the controller), eg:

[PersistQueryString]
public ActionResult Index()
{
    ViewData["Message"] = "Welcome to ASP.NET MVC!";

    return View();
}

Note

As the query value gets put into session it will be applied for the life of the session. If you want to check that the value is there and the same each request you will need to do some checking in the attribute overridden method.

Finally

I've purely done this as a "can it be done" exercise. I would highly recommend against it.

Cheers

WestDiscGolf