最近在使用 MVC 开发的时候,遇到一个对我来说“奇怪的问题”,就是使用 BundleTable 进行 CSS、JS 文件绑定,然后使用 Styles.Render、Scripts.Render 进行获取,但总是获取不到绑定的 CSS、JS 文件,然后报“404错误”,话说再多,不如一个代码示例。

BundleConfig 配置代码:

public class BundleConfig
{
// For more information on bundling, visit http://go.microsoft.com/fwlink/?LinkId=301862
public static void RegisterBundles(BundleCollection bundles)
{
bundles.Add(new ScriptBundle("~/bundles/test.js").Include(
"~/Scripts/bootstrap.js",
"~/Scripts/respond.js")); bundles.Add(new StyleBundle("~/bundles/test.css").Include(
"~/Content/bootstrap.css",
"~/Content/site.css"));
}
}

视图获取:

<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>@ViewBag.Title - My ASP.NET Application</title>
@Styles.Render("~/bundles/test.css")
@Scripts.Render("~/bundles/test.js")
</head>

运行结果:

这个问题我相信大家应该都遇到过,当然前提条件是按照我上面那种写法,问题出来了,那该如何解决呢?因为你不知道问题出在哪,所以只能进行反复的尝试,最后我无意间把 .css 和 .js 后缀去掉就可以了,在上一个开发项目我就是这么干的,然后现在开发的项目又遇到这个问题,这就引起了我的重视,当然这不是一个解决方法,只是你不知道它背后的东西罢了。

小标签:当使用 VS 调试模式时,即 web.config 中 debug="true",使用 BundleConfig.RegisterBundles 进行注册是没有效果的,但是可以展示,只不过没有起到“绑定”文件的作用,解决方式是,需要手动在 Application_Start 代码中添加:BundleTable.EnableOptimizations = true;

除了把 .css 和 .js 后缀去掉,网上搜索,还有一种解决方法就是,在 web.config 添加如下配置:

  <system.webServer>
<modules runAllManagedModulesForAllRequests="true">
</modules>
</system.webServer>

runAllManagedModulesForAllRequests 这个东西,之前我也遇到过,但不是像这次使用 Styles.Render、Scripts.Render 引起的,而是使用 MapRoute 进行 .htm 文件路由配置的时候,出现“404”错误,然后在 web.config 添加上面的配置就可以了,我还纪录了一篇博文:【记录】ASP.NET MVC MapRoute .htm 不起作用,哎,当时并没有深入进行研究 runAllManagedModulesForAllRequests,只是认为既然能解决问题就行了,现在一想,其实心里有点后怕,为什么这样说?看下面就知道了。

runAllManagedModulesForAllRequests 到底是什么东西呢?其实从它名字上面,你就可以明白一点,这也就是命名好的好处啊,咳咳,说白了,其意思就是为所有 Modules 管理请求的一个开关,如果设置为 true,就是把所有请求到 Modules 的通道打通了,没有任何阻拦,那 Modules 又是什么呢?字面意思可以理解为“模块”或“单元”的意思,它是属于 Web 服务器的东西,和 Web 应用程序不太相关,Web 应用程序只是对它发起一个请求,Modules 的相关东西,可以看下这一篇非常好的文章:IIS Modules Overview

使用 IIS 部署站点的时候,在点击站点,右侧会有一个“主页”,我们会看到 Modules 的“身影”:

点击“模块”,就可以看到 IIS 所有的默认 Modules:

所有 Module 的具体说明可以查看:Module Reference,我们看一个等会我们要用到的 Module-StaticFileModule(静态文件管理模块):

  • Description: Sends out static files with the file extension .html, .jpg, as well as many others. The staticContent/mimeMap configuration collection determines the list of file extensions.
  • Configuration sections: system.webServer/staticContent
  • Dependencies: None.
  • Potential issues when removing this module: Static files no longer become served. Requests for files return a 404 Not Found error indicating that no handler was matched.

上面说到,使用 MapRoute 进行 .htm 文件路由配置,出现“404错误”,我原本是想通过配置 StaticFileModule 进行解决,试过之后发现不行,staticContent/mimeMap 配置中,IIS 默认是有 .htm 配置的,具体为:<mimeMap fileExtension=".htm" mimeType="text/html"/>,详细博文介绍:IIS 6中mimemap属性的默认设置,而且最重要的是 StaticFileModule 是管理所有静态文件请求的,其实 MapRoute 进行 .htm 文件路由配置的请求,是到不了 StaticFileModule 模块处理的,要不然早就可以访问了,URL 路由配置有一个单独的模块-UrlMappingsModule,这部分内容后面再了解。

至于 Styles.Render、Scripts.Render 获取包含后缀绑定的“404错误”,可以用下面配置进行解决:

  <system.webServer>
<modules>
<add name="BundleModule" type="System.Web.Optimization.BundleModule" />
</modules>
</system.webServer>

其实上面这两个问题的“另类”解决方式,归根到底就是想避免使用 runAllManagedModulesForAllRequests="true",为什么要避免使用它?当然是有原因的,在说这个之前,再来看一个有意思的问题,可能和这个不太相关,但我还是想说一下。

先来看一段 web.config 配置:

<configuration>
<system.web>
<authentication mode="Forms">
<forms name="MembershipCookie"
loginUrl="Login.aspx"
protection="All"
timeout="525600"
slidingExpiration="true"
enableCrossAppRedirects="true"
path="/" />
</authentication>
<authorization>
<deny users="?" />
</authorization>
</system.web>
<location path="Default.aspx">
<system.web>
<authorization>
<allow users="*"/>
</authorization>
</system.web>
</location>
</configuration>

这段代码表示什么意思呢?authorization 配置的用户访问类型为“普通用户授权后才能访问”,location/authorization 是对某一页面进行身份验证,针对 Default.aspx 的身份验证类型为“匿名可访问”,并且 Default.aspx 为此站点的默认访问文档,可以理解为此站点出了 Default.aspx,其他页面访问都是需要身份验证的,然后跳转到 Login.aspx。

运行后,你会发现其实并不是这么回事,比如访问 www.mysite.com,按照配置应该会访问 www.mysite.com/Default.aspx,但是你会发现,它会跳转到 www.mysite.com/Login.aspx,为什么会这样呢?其实是 IIS 版本更新的问题,Stack Overflow 中详细的问题描述:ASP.NET 2.0 and 4.0 seem to treat the root url differently in Forms Authentication,在他问题描述中,尝试用 UrlRewriter,但是还是没有起到效果,最后做了一个测试:

ASP.NET Version  Url                                 Behaviour
-------------------------------------------------------------------------
2.0 http://example.com Renders Default.aspx
2.0 http://example.com/Default.aspx Renders Default.aspx
4.0 http://example.com Redirects to Login.aspx
4.0 http://example.com/Default.aspx Renders Default.aspx

相关的两篇 IIS 更新说明:

第一篇博文主要是说明 IIS 的一个更新,具体内容可以简化为:After this patch is applied, ASP.NET 4 applications can handle requests for extensionless URLs. Therefore, managed HttpModules that run prior to handler execution will run. 什么意思?就是处理程序增加了一个"*"的映射,也就是说,比如文中提到的,更新之前只能访问如下 URL:www.example.com/ExampleSite/ExampleFile.,注意后面是有“点”的,也就是只能访问有扩展名的 URL,更新之后,可以访问无扩展名的 URL,也就是可以把那个“点”去掉,这样蕴含什么意思呢?注意上面英文的后面一句话,这句话就说明了后面那篇博文的问题原因。

后面一篇博文主要也是说明,上面 Stack Overflow 中所描述的那个问题,比如我访问 www.mysite.com,更新之前,会根据配置文件中的“默认文档”,找到相关页面后,再根据 web.config 中的身份验证配置,进行处理并显示,如果按照上面的 web.config 配置,访问的是 www.mysite.com/Default.aspx(匿名用户),但是更新后,IIS 就可以处理无扩展名的 URL,得到响应的 URL 后,会立马交给 Modules 进行处理,首先就是 UrlAuthentication、FromsAuthentication 模块进行身份验证处理,发现是“非法用户”,然后就跳转到了 www.mysite.com/Login.aspx,而直接访问 www.mysite.com/Default.aspx,会先走配置文件的 location 身份验证说明,因为更新针对的是“无扩展名”的 URL,而 www.mysite.com/Default.aspx 是有扩展名的 URL,说了那么多,微软最后给出的解决方案是:

<configuration>
<system.webServer>
<handlers>
<remove name="ExtensionlessUrl-Integrated-4.0" />
<remove name="ExtensionlessUrl-ISAPI-4.0_64bit" />
<remove name="ExtensionlessUrl-ISAPI-4.0_32bit" />
</handlers>
</system.webServer>
</configuration>

其实这个问题和 runAllManagedModulesForAllRequests 不太相关,但它可以带你思考 URL 和 Modules 之间的“微妙关系”,至于为什么避免使用 runAllManagedModulesForAllRequests="true",我贴出两篇博文:

这篇博文就到这,后面解决一下不配置 runAllManagedModulesForAllRequests="true",使用 MapRoute 进行 .htm 文件路由配置,出现的“404错误”。

参考资料:

塞翁失马,焉知非福:由 Styles.Render 所引发 runAllManagedModulesForAllRequests="true" 的思考的更多相关文章

  1. 【续集】塞翁失马,焉知非福:由 Styles.Render 所引发 runAllManagedModulesForAllRequests="true" 的思考

    在上一篇中,还有个遗留问题没有解决,就是 ASP.NET MVC MapRoute .htm 不起作用,如果不使用 runAllManagedModulesForAllRequests="t ...

  2. 关于MVC4.0中@Styles.Render用法与详解

    本文分享于http://keleyi.com/a/bjac/q74dybjc.htm文章,感觉写的蛮好所以就拿过来做笔记了,希望对大家有帮助 最近公司的新项目用了MVC 4.0,接下来一步步把 工作中 ...

  3. 在_Layout模版中使用@Styles.Render()没有效果

    刚才有测试一个功能,就是在_Layout母版中使用了@Styles.Render()时行Render样式文件,所有在此母版下的视图均没有应用到样式,没有效果.是什么原因? 经查证资料,原来Insus. ...

  4. ASP.NET MVC 4 RC的JS/CSS打包压缩功能 Scripts.Render和Styles.Render

    打包(Bundling)及压缩(Minification)指的是将多个js文件或css文件打包成单一文件并压缩的做法,如此可减少浏览器需下载多个文件案才能完成网页显示的延迟感,同时通过移除JS/CSS ...

  5. mvc中Scripts.Render、Styles.Render

    一.配置BundleConfig.cs文件 1.首先要在App_Start 里面BundleConfig.cs 文件里面 添加要包含的css文件 2.BundleConfig就是一个微软新加的 一个打 ...

  6. c# MVC中 @Styles.Render索引超出下标

    @Styles.Render( "~/Content/bootstrap/css", "~/Content/mycss") 提示索引超出下标 后来发现市boot ...

  7. @Styles.Render

    1.@Styles.Render 在页面上可以用@Styles.Render("~/Content/css") 来加载css 首先要在App_Start 里面BundleConfi ...

  8. mvc4.0 @Styles.Render(转)

    1.@Styles.Render 在页面上可以用@Styles.Render("~/Content/css") 来加载css 首先要在App_Start 里面BundleConfi ...

  9. MVC 中Scripts.Render、Styles.Render

    在ASP.NET MVC项目中,可以在视图中利用Scripts.Render.Styles.Render统一加载js.css文件,需要利用BundleConfig类来Add 各种Bundle,例如:b ...

随机推荐

  1. log4net写入mysql完整例子

    1,创建表log   CREATE TABLE `log` ( `id`  int(11) NOT NULL AUTO_INCREMENT , `log_datetime`  timestamp NO ...

  2. 怎么将java web 项目导入idea 中

    1.将 java web 项目导 入idea 中, 显示 然后进行 Configure 配置. 2. 点击 open module settings. 3. 4. 选择jar包. 5. 6. 配置to ...

  3. bzoj 刷水

    bzoj 3856: Monster 虽然是sb题,,但是要注意h可能<=a,,,开始忘记判了WA得很开心. #include <iostream> #include <cst ...

  4. Java ArrayList和Vector、LinkedList与ArrayList、数组(Array)和列表集合(ArrayList)的区别

    ArrayList和Vector的区别ArrayList与Vector主要从二方面来说.  一.同步性:   Vector是线程安全的,也就是说是同步的,而ArrayList是线程序不安全的,不是同步 ...

  5. PHP中include()与require()的区别说明

    require 的使用方法如 require("MyRequireFile.php"); .这个函数通常放在 PHP 程序的最前面,PHP 程序在执行前,就会先读入 require ...

  6. MySQL流程函数

    #如果value是真,返回t:否则返回f if(value,t f) #如果value1不为空,返回value1,否则返回value2 ifnull(value1,value2) #如果value1是 ...

  7. angular input标签只能单向传递数据的问题

    angularjs input标签只能单向传递数据的问题 <ion-view title = "{{roomName}}" style = "height:90%; ...

  8. siteserver cms选择栏目搜索无效

    标签必须以空格分开,且option 的value必须给id不能给名称

  9. <web Font的使用>

    使用font-face将字体引入web中 先将字体文件复制到项目的font文件夹中,CSS样式如下: @font-face { font-family: 'iconfont'; /*字体名称*/ sr ...

  10. USACO翻译:USACO 2012 JAN三题(3)

    USACO 2012JAN(题目三) 一.题目概览 中文题目名称 放牧 登山 奶牛排队 英文题目名称 grazing climb lineup 可执行文件名 grazing climb lineup ...