Sunday 27 September 2020

ASP.NET Bundling and http 403 Errors

 So I'm probably late to the game in running into this, but it bit me at work last week and I thought it was worth writing up...

I made a change to one of our internal websites that involved bringing in FontAwesome so I could use some of it's widgets. I downloaded the FontAwesome CSS and font files to serve them from our internal server, and I added them to my project under the Content folder, and I created a new StyleBundle that referenced the CSS file so I could get that sweet minification. I ran up the site on my laptop and there were my new widgets. Cool. I committed and pushed my changes, had my pull request accepted, and Azure DevOps deployed the new build to the server. I ran it up on the server - and my widgets weren't showing. But, but, but, it Works On My Machine. Time for some investigation.

My first stop was to look at the console in Chrome, where there was an important clue:


A http 403 error? But where was that coming from and how did it relate to FontAwesome? Step 2 in my investigation, look at the raw request in Fiddler and see where the 403 is coming from.

So, the first request produces a 301 result, which for those of you who haven't memorised the http status codes is 'Moved Permanently' and provides a Location in the response headers for the browser to redirect to. Notice in the Fiddler screenshot that the 301 result is generated by a request to /Content/FontAwesome, which corresponds to the name of my bundle, but the 403 result comes from /Content/FontAwesome/ - which corresponds with the path in my project that I put the FontAwesome CSS files into. 
So, there's an issue with bundling when your bundle name matches a path in the file system, and the result is this 301-403 dance where your CSS files doesn't get loaded. And the solution is obvious - don't give your bundles a name that matches a path in the file system. In my case, I renamed my bundle from ~/Content/FontAwesome to ~/bundles/FontAwesome and all was right with the world.
Why did it work on my machine? Well, in one of those 'obvious in hindsight' things, I forgot that when you have debugging enabled in your web.config, ASP.NET bundling doesn't take effect and your files that would go through the bundling are actually served straight from the file system. When I ran my code locally without debugging, I saw the same behaviour on my machine. 
Why did I pick a bundle name that matched the file system in the first place? Simple - I was following the same pattern as the boilerplate bundling code gives you for StyleBundles:
bundles.Add(new StyleBundle("~/Content/css").Include(
                      "~/Content/bootstrap.css",
                      "~/Content/site.css"));

All the above relates to .Net Framework ASP.NET sites. What happens in ASP.NET Core and can you have the same issue? Well, if you go down the bundling route in ASP.NET Core, it works differently and your bundling code produces a file for you to include in your markup rather than a virtual directory. Which means there shouldn't be an issue of a virtual directory name clashing with a physical one. See the MSDN documentation for bundling here.

No comments: