views:

139

answers:

4

I have a simple, but probably common problem on how to inject HTML inside an ASP.NET MVC master page. I have a google analytics tracking code that sits on my master page. The code looks like this:

var _gaq = _gaq || [];
_gaq.push(['_setAccount', 'UA-XXXXX-1']);
_gaq.push(['_trackPageview']);
// need to inject ecommerce code here
(function () {
    // google analytics code here
})();

I'm using ecommerce tracking and I want to inject the "cart" information in side this HTML on the receipt page (and ONLY on this page). So I do something like this:

var _gaq = _gaq || [];
_gaq.push(['_setAccount', 'UA-XXXXX-1']);
_gaq.push(['_trackPageview']);
<% if(ViewData["googleanalytics"]!=null) {%>
<%= ViewData["googleanalytics"] %>
<% } %>
(function () {
    // google analytics code here
})();

Then in the controller, I have code that looks like this:

[HttpGet]
public ActionResult Receipt()
{
    var receipt = // get receipt model

    // get google analytics javascript. This function pulls
    // the data from the receipt model
    ViewData["googleanalytics"] = GetAnalyticsInfo(receipt); 

    return View(receipt);
}

This whole thing seems like a little bit of a kludge and I was wondering if anybody had better ideas to handle this situation?

A: 
Praveen
The issue is you're still not pulling the google analytics code for the particular receipt.
Keltex
+1  A: 

Can you split the javascript into two parts:

At the top of your master page, put:

var _gaq = _gaq || [];
_gaq.push(['_setAccount', 'UA-XXXXX-1']);
_gaq.push(['_trackPageview']);

At the bottom of your master page, put:

(function () {
    // google analytics code here
})();

And then, somewhere in your receipt page's view (where it will be output in between the two pieces of javascript from the master page), put

<% if(ViewData["googleanalytics"]!=null) {%>
<%= ViewData["googleanalytics"] %>
<% } %>

Worth a try?

Carson63000
A little brittle, but It will work!
Keltex
+2  A: 

I think I misread your original question. If this has to happen on only one page, then adding a filter would be a 'cleaner' option.

Filter:

public sealed class GAFilter: ActionFilterAttribute
{
   public override void OnActionExecuting(ActionExecutingContext filterContext)
   {
       filterContext.Controller.ViewData["googleanalytics"] = GetAnalyticsInfo();
       base.OnActionExecuting(filterContext);
   }

   private MvcHtmlString GetAnalyticsInfo()
   {
   }
}

Action:

[GA]
public ActionResult ()

{ return View(); }

It would be nice if you could bind a strongly-typed viewmodel to a MasterView but the current MVC framework does not allow that. ViewData is your friend for pushing info from a Controller into a Master.

Praveen
For the life of me, I can't get it to format correctly. :(
Praveen
Since GetAnalyticsInfo() requires access to the model, how would I get this information?
Keltex
When you say Model, are you referring to the ViewModel or the DataModel? I would just keep this info in the web.config's App settings or get from a Config DB.
Praveen
Either one. Let's say the ViewModel for argument's sake. The point is that the GetAnalyticsInfo() must return the user-specific receipt information. And this is generated in the controller.
Keltex
Per my understanding, there is no ViewModel for a MasterView since a View can have only one ViewModel.You have access to the Controller via the ActionExecutingContext.Update: see code in my answer below.
Praveen
Did my solution work Keltex?
Praveen
A: 

public override void OnActionExecuting(ActionExecutingContext filterContext) { MyController myController = (MyController)filterContext.Controller; myController.GetAnalyticsInfo(); base.OnActionExecuting(filterContext); }

Praveen