Reputation: 4341
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
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
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
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
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