The Background:
We are supplied with html files - 'wrappers' - from our client, into which we need to inject the content that we produce. They have different wrappers for different pages and we have to inject the corresponding content into a special tag that they supply in the wrapper.
The wrapper file name corresponds to the name of the action method. So for the example below, a custom action filter is executed which will determine the name of the wrapper and then call a method in the BaseController (which every controller implements) which will load the wrapper and inject our content into it.
[WrapperAction]
public ActionResult Home()
{
return View();
}
The reason I put this in an ActionFilter is because I didn't want to be calling the BaseController
's method to populate the wrapper in every action method that needed a wrapper. I thought it was much tidier to decorate the method with the ActionFilterAttribute
WrapperAction
is defined as follows:
public class WrapperAction : ActionFilterAttribute
{
public override void OnActionExecuted(ActionExecutedContext aec)
{
var baseController = (BaseController)filterContext.Controller;
string wrapper = aec.RequestContext.RouteData.Values["action"].ToString();
baseController.PopulateWrapper(wrapper);
}
}
and PopulateWrapper
is defined as
public void PopulateWrapper(string wrapperName)
{
// get wrapper file from disk
Wrapper wrapper = _wrapperService.GetWrapper(Site.Id, wrapperName);
// populate the file with our CSS (it already has its own pre-populated CSS)
// our CSS file is determined by the id of a Site object.
AppHelper.PopulateWrapperCss(wrapper, this.Site.Id);
// make wrapper sections available to the Master page,
// split so that we can place our content around them
ViewData["WrapperTop"] = wrapper.WrapperTop;
ViewData["WrapperMiddle"] = wrapper.WrapperMiddle;
ViewData["WrapperBottom"] = wrapper.WrapperBottom;
}
The Dilema:
Now however, a new requirement has come in. There are some new tags in the wrapper that I need to populate, and I have to populate them with different data depending on the action method that calls the wrapper. That data is determined in the action methods, but the data needs to be used in the PopulateWrapper method that gets called by the WrapperAction
.
I now need to have a method similar to
AppHelper.PopulateWrapperTags(wrapper, this.TagData);
and I need to have some way for BaseController's TagData property to be populated with data. I can asign the property in the action method like follows
[WrapperAction]
public ActionResult Home()
{
base.TagData = GetTagData();
return View();
}
but that kind of defeats the point of me having the WrapperAction in the first place because I don't want to have to be referring to the BaseController like that.
The Question:
Is there a way for me to supply WrapperAction with the data it needs to populate the wrapper with? Do I need to take the hit and start calling
var tagData = GetTagData();
string wrapperName = RouteData.Values["action"].ToString();
base.PopulateWrapper(wrapperName, tagData);
in every controller? Is there a better way for me to do this?