StarCub
StarCub

Reputation: 4341

Asp.net MVC 3 global querystring?

I'm building a generic web application for two business groups. The logo/banner needs to be changed based on the querystring. For example, if the url is http://foo.com/test?bg=a it shows the logo for business group a and if the url is http://foo.com/test?bg=b it shows the logo for business group b. This is not a problem if I only had one action. But I have many actions.

I could check the query string on all actions but there must be a nice way to do it. I have an perception that I need to do something with the routing stuff but just don't know how. Can anyone please let me know how to do it?

Upvotes: 3

Views: 1161

Answers (4)

TheCodeKing
TheCodeKing

Reputation: 19240

You can write a Custom Routing Handler and use routing to extract the querystring as a parameter, and pass into RouteData where it can be accessed anywhere.

public class RouteWithQueryStringValueHandler : MvcRouteHandler
{
    private readonly string key;

    public RouteWithQueryStringValueHandler(string key)
        : base()
    {
        this.key = key;
    }

    protected override IHttpHandler GetHttpHandler(RequestContext requestContext)
    {
        var request = requestContext.HttpContext.Request;
        var qsValue = requestContext.HttpContext.Request[key];
        var router = base.GetHttpHandler(requestContext);
        requestContext.RouteData.DataTokens[key] = qsValue;
        return router;
    }
}

Register as follows:

routes.Add(new Route("{controller}/{action}/{id}", 
                 new RouteValueDictionary(
                         new { controller = "Home", 
                               action = "Index",
                               id = UrlParameter.Optional 
                         }),
                 new RouteWithQueryStringValueHandler("bg")));

Get the logo for Routing data:

var logo = RouteData.DataTokens["bg"];

Upvotes: 6

Darin Dimitrov
Darin Dimitrov

Reputation: 1039598

You could write a custom helper method which based on the query string parameter will append a given class name to some div. Then of course you would have different class definitions in your CSS file applying a background-image.

For example:

public static class HtmlExtensions
{
    public static string BannerClass(this HtmlHelper html)
    {
        var bg = html.ViewContext.Controller.ValueProvider.GetValue("bg");
        if (bg == null || string.IsNullOrEmpty(bg.AttemptedValue))
        {
            // no bg parameter => return a default class
            return "default_banner";
        }

        if (string.Equals("a", bg.AttemptedValue))
        {
            return "banner_a";
        }
        else if (string.Equals("b", bg.AttemptedValue))
        {
            return "banner_b";
        }

        // unknown value for the bg parameter => return a default class
        return "default_banner";
    }
}

and then in your _Layout you could apply this class to some placeholder like a div or even the body:

<div class="@Html.BannerClass()">OK</div>

This way it will always be applied for all view in your application.

Now all that's left is to define your CSS rules for the different banners:

.default_banner {
    background-image: url('../images/default_banner.png')
}

.banner_a {
    background-image: url('../images/banner_a.png')
}

.banner_b {
    background-image: url('../images/banner_b.png')
}

Upvotes: 1

Plymouth223
Plymouth223

Reputation: 1925

Place some code in your master page(s) to make the decision as to which banner to display based on the query string. Ideally the code wouldn't be completely inline i.e. it'd be in a helper class.

Upvotes: 0

Erik Philips
Erik Philips

Reputation: 54676

If you are using Razor (and I believe this does break the separation of responsibilities guideline) change the _ViewStart.cshtml to do it.

@{
    if (/* Context.QueryString Params, not at my development box*/)
    {
        Layout = "~/Views/Shared/Layout-Group1.cshtml";
    }
    else
    {
        Layout = "~/Views/Shared/Layout-Group2.cshtml";
    }
}

I prefer this route because it makes any future requests (layout + css + javascript) fairly easy because they can all be updated within the Layout.

Upvotes: 0

Related Questions