MVC Controller Action called multiple times per page load.

Today I came across a real time sink of a gotcha with my MVC site. So I thought I’d share this on a post.

The issue
A standard Mvc controller action was getting called multiple times each time a GET request was made in the browser. Sometimes twice, sometimes once, and occasionally more.

Opening up Chrome dev tools to try and understand the problem, I spotted the multiple requests in the Network tab. Interstingly when I filtered by type the additional requests were showing up in the Images tab. Looking at the media type, the requests were being made the following acceptt header

image/webp,image/*,*/*

The initiator column pointed to javascript being the culprit.

chrome-dev-tools

However, this was a red herring. After a lot of code removal, view in browser, rinsing and repeating, I isolated it to the following line

<div id="hero" style="background-image: url('@Model')">

The cause
It took a while for the penny to drop, but the problem occurred when the Model was an empty string. So with nothing passed to the url property, the background image was requesting controller once the markup rendered. This was happening in a number of places in the page. So the controller was being called as many as four times each time the page was loaded.

I only tested this in Chrome, so the behaviour may not be the same across a other browsers.

The solution
As this markup was in a number of places across the site, I created an Html Helper extension, which simply checks to see if the string is null or empty.

My markup now looks like this

<section class="pageHero compactHero bottomAligned" @Html.StyleAttributeForHeroImage(Model.BackgroundImage)>

And the Helper looks like this;

public static class StyleAttributeExtensions
{
    public static MvcHtmlString StyleAttributeForHeroImage(this HtmlHelper helper, string imageUrl)
    {
        var styleAttribute = String.Format("style=\"background-image: url('{0}')\"", imageUrl);

        if (String.IsNullOrWhiteSpace(imageUrl))
        {
            styleAttribute = String.Empty;
        }
        return MvcHtmlString.Create(styleAttribute);

    }
}

So now I only have one request per controller action when each pages loads. This has resulted in a noticeable improvement in page load times.

Hope this helps someone else out.