Story Details for articles

StyleBundle 403 Error - Solved!

kahanu
Author:
Version:
Views:
45425
Date Posted:
2/6/2013 4:13:35 PM
Date Updated:
2/6/2013 4:13:35 PM
Rating:
4.79/14 votes
Framework:
ASP.NET MVC 4
Platform:
Windows
Programming Language:
C#
Technologies:
.Net 4.5
Tags:
stylebundle, scriptbundle, 403 Forbidden, ASP.NET MVC, css, javascript, KendoUI
Demo site:
Home Page:
Share:
This article will attempt to explain the reasons for the 403 Forbidden error when using the StyleBundles or ScriptBundles in an ASP.NET MVC 4 application in build mode, and explain how to solve the issues.

In this article, I'll show you how to build a site so that it works in Debug or Release mode using the StyleBundles and ScriptBundles.  I'll demonstrate these techniques with this website template.

sample web site

The Virtual Path Matters!

Apart from what you've probably heard and read in various Forums or Stackoverflow posts regarding the way to work with the StyleBundle and ScriptBundle classes, the "virtualpath" parameter of the classes DOES matter, as far as how it is named.  Some answerers have gotten this right.

Let me clarify this, if you have ALL of your CSS files in the root of the Content folder, then no, it doesn't matter.  It only matters if you have various folders inside the Content folder that can contain many different sets of styles for various reasons, and you want to maintain that folder structure.

I'll show you how to keep those folders without having to drop everything down to the root.

What you need to do is match the bundle name with the actual virtual path to your files!

I'll explain this in a moment, but let me show you what the framework does with the bundles from Debug mode to Release mode.

Let's say I have a Content folder with my CSS files and images in a structure like this:

content folder

This is how I want to keep my files so they are separate from each other. 

So let's say I've installed the halcyonic HTML into the _Layout.cshtml page.  And I've then created a StyleBundle like this:

bundles.Add(new StyleBundle("~/Content/halcyonic").Include(
    "~/Content/halcyonic/css/style.css",
    "~/Content/halcyonic/css/5grid/responsive.css"));

... this will work fine in Debug mode and return a path as:

http://localhost:32290/Content/halcyonic/css/images/someimage.png

But if I were to run this in Release mode, by changing the "debug" attribute on the compilation element in the web.config file to false...

<compilation debug="false" targetFramework="4.5" />

... and then run the application, I would get dreaded 403 Forbidden error and my page layout would break.  And you can clearly see below that my page doesn't have any styles attached.

broken site

And this is what the path to the same image file would look like in Release mode:

http://localhost:32290/Content/images/someimage.png

Obviously we can see that the path changed when changing to Release mode, but what happened?  I fuddled over this for a long time and was determined to figure it out and finally found a pattern.

If I changed the parameter name of the bundle to something that more closely matched to the actual path to the files, it started working.  So if you look at the picture of the Content folder and it's file structure again, you can see that the CSS file, style.css, lives in the /Content/halcyonic/css folder.

So I tried:

bundles.Add(new StyleBundle("~/Content/halcyonic/css").Include(
                "~/Content/halcyonic/css/style.css",
                "~/Content/halcyonic/css/5grid/responsive.css"));

Of course, each time I made a change here I had to update the Render method in the _Layout.cshtml page.

@Styles.Render("~/Content/halcyonic/css")

... and this too didn't work.  I got the same 403 Forbidden error.

So then I found out that the last part of the virtualPath is essentially a throw away name.  It doesn't really mean anything or have any other impact other than telling the framework that the information before it is important.  I'll tell you why in a second.

So then I tried this:

bundles.Add(new StyleBundle("~/Content/halcyonic/css/styles").Include(
                "~/Content/halcyonic/css/style.css",
                "~/Content/halcyonic/css/5grid/responsive.css"));

@Styles.Render("~/Content/halcyonic/css/styles")

... and it worked!

fixed site

Why does this work?

Let's take a closer look at why this now works.

bundles.Add(new StyleBundle("~/Content/halcyonic/css/styles").Include(
                 "~/Content/halcyonic/css/style.css",
                 "~/Content/halcyonic/css/5grid/responsive.css"));

I've lined up the StyleBundle parameter with the included files paths to show you how they correlate with each other.  Notice that they all match up to the last slash before the style sheet.  This is the important thing to remember.  Make the bundle parameter match the path up to the location of the style sheet, and then add a name, any name after that.

This will work:

bundles.Add(new StyleBundle("~/Content/halcyonic/css/foo").Include(
                 "~/Content/halcyonic/css/style.css",
                 "~/Content/halcyonic/css/5grid/responsive.css"));

@Styles.Render("~/Content/halcyonic/css/foo")

foo virtual path

It doesn't matter what the trailing name is. The framework will ignore it, but you need it to tell the framework that everything before it will be used as the virtualPath in Release mode.  If /css was the trailing name, then it would say that it will look for the files in /Content/halcyonic, which is wrong.

And before you say, "Well why can't I put just a trailing slash after css, as in /Content/halcyonic/css/?" (notice the trailing slash).  That also won't work.  While the CSS will render Ok, some images may break, so put in a name with no trailing slash.

So end the virtualPath parameter with a name without a trailing slash.

Using this method will also allow you to use the relative image paths in the CSS file.  One thing I've found that always works the best is to have the images folder as a child underneath the style sheet.

For KendoUI Users

To allow your KendoUI widgets to work in Release mode and Debug mode, here are the bundles and Render methods:

bundles.Add(new ScriptBundle("~/bundles/kendo/2012.3.1401/kendoscripts").Include(
        "~/Scripts/kendo/2012.3.1401/kendo.web.*", // or kendo.all.*
        "~/Scripts/kendo/2012.3.1401/kendo.aspnetmvc.*"));
 
// The Kendo CSS bundle
bundles.Add(new StyleBundle("~/Content/kendo/2012.3.1401/kendostyles").Include(
        "~/Content/kendo/2012.3.1401/kendo.common.*",
        "~/Content/kendo/2012.3.1401/kendo.default.*"));

@Styles.Render("~/Content/kendo/2012.3.1401/kendostyles")
@Scripts.Render("~/bundles/jquery","~/bundles/kendo/2012.3.1401/kendoscripts")

You would just change the version folder name to yours.

Conclusion


So that's essentially it!  And just to be clear, this same procedure would be used for the ScriptBundle classes as well.

I know there's a lot here, but hopefully it's pretty straight forward and understandable.  This should prevent you from having any more issues with getting the the CSS and Scripts to render properly in Release mode.

Have fun!

Comments

  • daniel.sirz@gmail.com
    Posted By: Daniel
    On: 5/17/2013 1:03:18 AM

    Hi kahanu,

    it's early in the morning and this article "made my day"! Thanks for sharing!

    Daniel

  • info@kingwilder.com
    Posted By: King Wilder
    On: 5/17/2013 11:45:15 AM
    @Daniel - I'm glad it helped.
  • dkellycollins@gmail.com
    Posted By: Devin
    On: 5/30/2013 11:46:33 AM
    Had this error while in debug mode! Thanks for the help.
  • info@kingwilder.com
    Posted By: King Wilder
    On: 5/30/2013 12:06:21 PM
    @Devin - I'm glad the article helped.
  • drewid@drewspring.com
    Posted By: drevange
    On: 6/5/2013 3:28:39 AM
    Thanks!  Saved the day.  Tremendously useful and well document article.
  • info@kingwilder.com
    Posted By: King Wilder
    On: 6/5/2013 11:33:33 AM
    @drevange - thanks for the kind words, I'm glad it helped you out.
  • leniel@gmail.com
    Posted By: Leniel Macaferi
    On: 6/11/2013 6:18:19 PM

    Hey King Wilder,

    You're the same guy that provided the awesome SecurityGuard... https://github.com/kahanu/Security-Guard

    While searching for 403 forbidden related to style bundling I found you once again.

    Hooray... now I got it forever and ever!

    Using this method will also allow you to use the relative image paths in the CSS file.

    This is the biggest win.

    Thank you very much for the detailed post.

    Best,

    Leniel
    http://leniel.net

  • info@kingwilder.com
    Posted By: King Wilder
    On: 6/11/2013 6:32:27 PM
    @Leniel - Hi, how are things? I'm glad you found this solution helpful.  It was something I was determined to figure out and pass on to the community, if I got it right.  :^)
  • beat@erikdewilde.nl
    Posted By: Erik de Wilde
    On: 8/2/2013 3:02:58 AM

    Awesome!

    I've spend days figuring out why it didn't work in release mode...

    Thank you sooo much ;)

  • info@kingwilder.com
    Posted By: King Wilder
    On: 8/4/2013 7:00:59 PM
    @Erik de Wilde - I'm glad it helped.
  • donboyle@ymail.com
    Posted By: yupdon
    On: 8/27/2013 3:42:10 PM

    Others and I are very greatful for this post! I couldn't thank you enough.

    On a side note, do you have any idea why .min files are having issues? specifically KendoUI.min files?

    Thanks for any update!

  • info@kingwilder.com
    Posted By: King Wilder
    On: 8/27/2013 4:26:15 PM
    @yupdon - off hand, no I don't know why the Kendo min files are having problems.  Make sure you have the bundles as described above with the asterisk (*) placed correctly after the dot.  This will either include the .min for releases, or not for debugging.
  • lugerogo@hotmail.com
    Posted By: luferogo
    On: 10/22/2013 12:05:30 PM

    Thank you very much dude! My problem was solved...  Still I want the official explanation from microsoft for this behaviour.. From my opinion this is an issue.

    Thanks again!

  • mdavis@nyditot.com
    Posted By: Mark
    On: 12/3/2013 2:11:59 PM
    So just last night I resolved an issue based on a question you posted on the Telerik forums and the very next morning I resolved my very next issue with this post.  Small world!  Anyway, thank you very, very much.  I'm sure this has saved me weeks' worth of head banging.
  • mdavis@nyditot.com
    Posted By: Mark
    On: 12/3/2013 2:11:59 PM
    I may be way off base here but I think the issue is that when running in Debug the bundles aren't even created.  The bundle's constituent files are simply sent to the client separately using their physical paths.  If these files then reference other resources with a relative path (i.e. "./someImage.png") they will find them by using their own path as the starting point.  When running in Release, bundles are created and accessed via a "virtual" path.  I use the quotes because the virtual path isn't mapped to any physical path.  It's just a moniker that identifies the bundle.  BUT, when these bundeles files reference a relative path they're using this "virtual" path as the starting point which leads to nowhere unless to specify the physical path as kahanu suggest.
  • info@kingwilder.com
    Posted By: King Wilder
    On: 12/3/2013 8:33:41 PM
    @Mark - I'm glad I was able to help with my article.  The other thing that occurs is that if you use a wildcard "*" for the filename extension, as is sometimes shown in the default Bundle file with the jquery files, the "min" files will be used for Release mode if available, and non-min files will be used for debug mode.  This is a nice feature.  But there is a bug with the Microsoft.Web.Optimization bundler that sometimes ends up choking on lines of CSS or javascript code that contain forward slashes with other characters like "@".  You may see that your files are not rendered, and that may be the reason.  Just an interesting tidbit that I recently found out about.
  • pushpa.ponugoti@gmail.com
    Posted By: pushpa
    On: 12/13/2013 1:36:46 PM

    Thank you, kahanu

    its solved my problem

  • info@kingwilder.com
    Posted By: King Wilder
    On: 12/13/2013 8:04:58 PM
    @pushpa - I'm glad it helped.
  • hdevejian@gmail.com
    Posted By: hdevejian
    On: 3/18/2014 8:48:06 PM
    Thank you sir!
  • jason.xge@gmail.com
    Posted By: Jason Ge
    On: 3/27/2014 10:58:17 PM

    Thanks for the posting. It solved my issue.

    However, in your conclusion, you said this also applies to ScriptBundle. In your example, 

    bundles.Add(new ScriptBundle("~/bundles/kendo/2012.3.1401/kendoscripts").Include(

            "~/Scripts/kendo/2012.3.1401/kendo.web.*"// or kendo.all.*

            "~/Scripts/kendo/2012.3.1401/kendo.aspnetmvc.*"));

    The virtual path in ScriptBundle "~/bundles/kendo/2012.3.1401/kendoscripts" does not match the virtual path in Include method.

    Is there anything I undertand wrong?

    Thanks,

    Jason

  • lamphattai100590@gmail.com
    Posted By: TPL
    On: 3/28/2014 8:16:31 PM

    Thank you very much, I spent whole day to try to fix it. Thank you.

    I will keep your blog on top.

    Best regard

    TPL

  • info@kingwilder.com
    Posted By: King Wilder
    On: 3/30/2014 10:01:13 PM

    @Jason Ge - I'm going to update my article, but for scripts it doesn't need to work the same way.  For example, for Kendo script bundles you can simple be created like this:

    bundles.Add(new ScriptBundle("~/bundles/kendo").Include(
                    "~/Scripts/kendo/2014.1.321/jquery.min.js",
                    "~/Scripts/kendo/2014.1.321/kendo.all.min.js"));

    I have this working in many projects.  Give it a try.

  • andrew.clear@nwcadence.com
    Posted By: Andrew Clear
    On: 4/22/2014 5:58:46 PM
    A thousand, thousand times thank you. The contradictory and misleading information on this topic was driving me insane.
  • info@kingwilder.com
    Posted By: King Wilder
    On: 4/22/2014 7:37:39 PM
    @Andrew Clear - I'm glad it helped.
  • dpnminh@gmail.com
    Posted By: maya
    On: 5/25/2014 9:52:06 AM
    Thanks a lot. It was a great help and explanation :).
  • test@test.com
    Posted By: AnonimousDev
    On: 6/26/2014 7:28:38 AM
    Wow man! This helps me a lot! Many thanks!
  • info@kingwilder.com
    Posted By: King Wilder
    On: 6/26/2014 12:06:53 PM
    @maya and @AnonimousDev, you are very welcome.  I'm glad it helped.
  • rosdikasim@yahoo.com
    Posted By: rosdi
    On: 7/9/2014 8:59:32 PM
    Thanks!.. it finally working!.. I was on the verge of disabling bundling altogether until I found your page from stackoverflow. Thank you very much!
  • rosdikasim@yahoo.com
    Posted By: rosdi
    On: 7/9/2014 8:59:32 PM
    Thanks!.. it finally working!.. I was on the verge of disabling bundling altogether until I found your page from stackoverflow. Thank you very much!
  • ebarford@gmail.com
    Posted By: Ed
    On: 7/31/2014 3:50:12 AM

    I'll think you'll find the problem was that IIS was attempting to serve a physical path and not the bundle.

    This is why you get a 403 (you don't have permission to access the path).

    So as long as your bundle name doesn't match an actual path on the server you should be fine.

  • srinu.k19@gmail.com
    Posted By: Srinivas kotha
    On: 9/18/2014 3:25:14 AM

    This is very usefull for us

  • indra.lawi@opal-holding.com
    Posted By: Indy
    On: 10/6/2014 5:54:20 AM

    Hi Kahanu,

    Thanks a lot for this very helpful article.
    You save my day. I ran into the same issue after deploying our ASP.NET app to IIS.


  • arifa@techlogix.com
    Posted By: Arifa
    On: 10/17/2014 6:36:14 AM
    Superb!!
    thanks alot, It helped
  • rahul.shrestha89@gmail.com
    Posted By: rahul
    On: 10/29/2014 3:57:01 PM
    How does it work for images?
  • info@kingwilder.com
    Posted By: King Wilder
    On: 10/29/2014 4:50:03 PM

    @rahul - this article is only for bundling CSS style sheets and javascript files, not images.

    If you are talking about the images referenced in a CSS file, then you have to make sure the path to those images is correct in the CSS file, and then it will work.  As a rule, I usually move the /images folder inside the folder my CSS file is in, this way the path to the CSS images can be referenced like:

    background-image: url(images/myimage.jpg);

    Instead of trying some path like:

    background-image: url(../../images/myimage.jpg);

    I hope that answers your question.

  • bairi.rakesh@gmail.com
    Posted By: Rakesh
    On: 1/20/2015 9:16:36 PM
    Thanks It very Usefull for Me :)
  • maskeee@gmail.com
    Posted By: Maske
    On: 1/27/2015 3:36:23 AM

    Thanks! 

    muchas gracias ; )

  • albert-dnl@hotmail.com
    Posted By: Daniel
    On: 4/1/2015 3:42:38 PM
    Awesome :D you save a lot of hours.
  • notquitesilver@outlook.com
    Posted By: yesbox
    On: 4/9/2015 5:08:07 AM
    Is it just me or is this yet another stupid Microsoft bug? Anyways thanks a lot for clearing this up.
  • info@kingwilder.com
    Posted By: King Wilder
    On: 4/9/2015 7:57:06 AM
    @yesbox - I think it's more that it's not intuitively written and there's no documentation to back up how it's supposed to be used.  It's unfortunate.
  • rodrigueznik@ymail.com
    Posted By: enzo
    On: 5/22/2015 12:52:13 AM

    Hi!

    This article saved my day (and my job) for the second time! Thanks a lot!

    regards,

    enzo

  • ana.manzan@gmail.com
    Posted By: Aninha
    On: 6/12/2015 3:24:16 AM

    Lifesaver article! Really good, helped a lot! Thanks for it!

    :)

  • info@kingwilder.com
    Posted By: King Wilder
    On: 6/12/2015 7:42:25 AM
    @Aninha - I'm glad it helped.  :^)
  • msmit@savitar.co.za
    Posted By: DominionZA
    On: 7/1/2015 10:09:02 AM
    This was just brilliant. I have done so many MVC apps with Kendo, and never encountered this - until tonight.
    I deployed a new project to our live server and bang - 403 error. I figured out it was to do with Kendo but had no idea how to fix it. A quick Google resulted in this article, and I am now live.

    Thanks a lot dude. You truly are a King.
  • info@kingwilder.com
    Posted By: King Wilder
    On: 7/1/2015 11:03:46 AM
    @DominionZA - I'm glad the article helped.  :^)
  • abinash.sil668@gmail.com
    Posted By: Abinash
    On: 9/29/2015 11:27:22 PM

    Good Afternoon sir.

    This article really helped me out.

  • deva11p11@gmail.com
    Posted By: Dev
    On: 11/12/2015 4:35:23 AM
    Thanks.... You saved my lots of time
  • lincoln@thecloudeveloper.com
    Posted By: Lincoln Pires
    On: 11/20/2015 9:25:03 AM
    Man, I've lost a lot of time, but it really works!!!
    Thanks. :)
  • info@kingwilder.com
    Posted By: King Wilder
    On: 11/21/2015 8:16:00 AM
    I'm glad everyone is finding this helpful.  :^)
  • slowtea@dsl.pipex.com
    Posted By: owenlt
    On: 2/1/2016 10:18:37 AM

    Found this article after 2 hours of banging my head against the wall.  Hit 'refresh' and said outloud "there's no way this is gonna work" ... as my perfectly styled webpage opened in front of me!


  • info@kingwilder.com
    Posted By: King Wilder
    On: 2/1/2016 10:56:42 AM

    @owenlt - I'm sorry you have some drywall to fix, but hopefully this article will save more unsuspecting walls.  :^)

  • todkar.anand@gmail.com
    Posted By: Anand
    On: 2/6/2016 7:41:02 PM
    Awesome, thanks. This helped a lot.
  • sriramshiva93@gmail.com
    Posted By: sriram shiva
    On: 2/16/2016 12:43:26 AM

    Hi kahanu,

    Really very good  article

    Thanks for sharing!

    Regards,

    Sriram.

  • darkends12@gmail.com
    Posted By: PepeFlores
    On: 4/7/2016 10:16:09 AM

    Gracias, me funcionó perfectamente!!!!.

  • darkends12@gmail.com
    Posted By: PepeFlores
    On: 4/7/2016 10:16:09 AM

    Gracias, me funciono Perfectamente !!!.

    A mi me pasaba Que CUANDO ejecutaba la aplicacion directly from depuración en Visual Studio, los Estilos me cargaban Y Todo funcionaba bien, Pero CUANDO desplegaba en Servidor en el IIS Los Estilos ya no cargaban y salia de error 403 lo prohibido. Se solucionó agregando es es BlundleConfig.cs en La Línea:

     bundles.Add (nueva StyleBundle ( "~ / contenido / css") ----> se le adicionó CUALQUIER Numero yo escogí "Estilos" y quedo Así:

     bundles.Add (nueva StyleBundle ( "~ / contenido / CSS / Estilos")

    Y Por Último en el diseño, en: 

     @ Styles.Render ( "~ / contenido / css") ---> tambien adicioné la Palabra "Estilos" y quedo asi:

    @ Styles.Render ( "~ / contenido / CSS / Estilos")

    Y de correoproblema se solucionó mi problema.

  • info@kingwilder.com
    Posted By: King Wilder
    On: 4/15/2016 10:44:08 AM
    @PepeFlores - sorry for the late response, I was away.  I don't speak spanish so I can't get everything you are saying.  It seems like you are saying when you deployed your application you still got the 403 error and was able to fix it by adding the "Estilos" to the path.  This sounds like what my article is saying, but if that wasn't your issue and you got it to work, then good job.  Thank you for your comment.
  • shaper@web.de
    Posted By: shaper
    On: 4/16/2016 9:58:46 AM

    Hi kahanu,

    thanks for your post. I came across your site struggling with this issue while deploying my App to Windows Azure in Release mode. I also use Kendo UI and the images were missing.

    Thanks very much for your help.

    Regards

    Sven

  • irjsdkrjs@aol.com
    Posted By: A random dev
    On: 5/11/2016 5:12:57 AM
    One more person who was close to abandoning my bundling project until I came across this - gave the me the info I needed to tie it all together. Thanks for taking the time to document all this!
  • subajs@gmail.com
    Posted By: suba
    On: 5/26/2016 3:37:43 PM

    Thanks for this useful information !

    Timely help and saved my RnD time :)

  • candy@breakfast.com
    Posted By: candy for breakfast
    On: 6/22/2016 3:30:49 PM
    this was killing me, thanks a bunch
  • yuexuanwo@qq.com
    Posted By: yuexuanwo
    On: 7/4/2016 11:54:05 PM
    thanks for your share,it's very helpful.thanks again!
  • 000maher00@gmail.com
    Posted By: maher
    On: 10/9/2016 1:32:34 PM
    realy thank you
  • thomas@tw.tw
    Posted By: thomas
    On: 2/21/2017 10:55:58 PM
    thank you , it's really very helpful
  • thomas@tw.tw
    Posted By: thomas
    On: 2/21/2017 10:55:58 PM
    thank you , it's really very helpful
  • sushraj37@gmail.com
    Posted By: sushil
    On: 3/6/2017 8:46:52 AM
    Thank you for sharing it. Its really helpful for me

 

User Name:
(Required)
Email:
(Required)