I’m experimenting with MVC, and my question is – where I had Page_Load logic in Master Pages with WebForms, where should it go in MVC? Here’s the business case:
- Different Host Headers should cause different Page Titles to be displayed on the site’s (one) Master Page, therefore all pages. For example, if the host header is hello.mydomain.com, the page title should be ‘Hello World’ for all pages/views, while goodbye.mydomain.com should be ‘Goodbye World’ for all pages/views.
- If the host header is different than anything I have in the list, regardless of where in the application, it should redirect to /Error/NoHostHeader.
Previously, I’d put this in the MasterPage Load() event, and it looks like in MVC, I could do this either in every controller (doesn’t feel right to have to call this functionality in every controller), or somewhere in Global.asax (seems too… global?).
Edit: I have gotten this to work successfully using the Global.asax method combined with a Controller for actually processing the data. Only problem at this point is, all of the host header information is in a database. I would normally store the ‘tenant’ information if you will in a Session variable and only do a DB call when it’s not there; is there a better way to do this?
There is no 1:1 equivalent in MVC for a reason, let’s just recapitulate how to think about it the MVC way:
Model: ‘Pages of this site are always requested in a certain context, let’s call it the tenant (or user, topic or whatever your sub domains represent). The domain model has a property representing the tenant of the current request.’
View: ‘Render the page title depending on the tenant set in the model.’
Controller: ‘Set the tenant in the model depending on the host header’.
Keep in mind that what we want to avoid is mixing controller, view and business logic. Having controller logic in more then one place or a place, that is not called ‘controller’ is not a problem, as long as it remains separated.
And now the good thing: You could do this ‘MVC style’ even with Web Forms, and the solution still works with ASP.NET MVC!
You still have the request lifecycle (not the page lifecycle), so you could implement a custom HttpModule that contains this part of the controller logic for all requests. It handles the BeginRequest event, checks for the host header, and stores the tenant to something like HttpContext.Current.Items[‘tenant’]. (Of course you could have a static, typed wrapper for this dictionary entry.)
Then all your model objects (or a model base class, or whatever is appropriate for your solution) can access the HttpContext to provide access to this information like this:
Advantages:
Update re your edit: I don’t like the idea of holding the state in the session, especially if your session cookie might apply not only to each sub domain, but to all domains. In this case you might serve inconsistent content if users visted another sub domain before. Probably the information in the database that is mapping host headers to tenants won’t change very often, so you can cache it and don’t need a database lookup for every request.