最近在使用 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. dd——留言板再加验证码功能

    1.找到后台-核心-频道模型-自定义表单 2.然后点击增加新的自定义表单 diyid 这个,不管他,默认就好 自定义表单名称 这个的话,比如你要加个留言板还是投诉建议?写上去呗 数据表  这个不要碰, ...

  2. jsfl脚本设置导出AS链接名遇到的奇怪问题

    今天写jsfl脚本发现一个奇怪的问题,脚本用于对库对象设置AS链接名,代码如下: var item = fl.getDocumentDOM().library.items[0];var exportN ...

  3. sqlserver 连接mysql

    配置与电脑相对应的odbc   http://dev.mysql.com/downloads/connector/odbc/

  4. opencv算法学习

    1.改变图像的亮度和对比度: 算法介绍:对每一点像素值的r,g,b,值进行乘法和加法的运算. 代码使用: ; y < image.rows; y++ ) { ; x < image.col ...

  5. jvm的内存分配总结

    最近看了周志明版本的<深入理解Java虚拟机>第一版和第二版,写的很好,收获很多,此处总结一下.   jvm中内存划分:   如上图,一共分为五块,其中: 线程共享区域为: 1.java堆 ...

  6. Jmeter之参数化

    Jmeter参数化分为两类,一类是在badboy录制脚本时进行参数化,二是再Jmeter里进行参数化 一:badboy录制脚本时进行参数化的步骤 1.脚本录制成功后->在左下角,点击variab ...

  7. C#_技巧:.net下C++调用C#的dll

    C#编译一个dll,比如命名空间为Csharp,里面有个类A,字段x,产生一个Csharp.dll C++ 配置,让C++支持CLR C++调用方法: #include <iostream> ...

  8. 在Android上使用qemu-user运行可执行文件

    在Android上使用qemu-user运行可执行文件 作者:寻禹@阿里聚安全 前言 QEMU简要介绍: QEMU可以解释执行可执行程序.既然QEMU可以解释执行可执行程序,那么QEMU就能够知道执行 ...

  9. MySQL 正则表达式

    介绍 正则表达式用来描述或者匹配符合规则的字符串.它的用法和like比较相似,但是它又比like更强大,能够实现一些很特殊的规则匹配:正则表达式需要使用REGEXP命令,匹配上返回"1&qu ...

  10. 跟vczh看实例学编译原理——三:Tinymoe与无歧义语法分析

    文章中引用的代码均来自https://github.com/vczh/tinymoe.   看了前面的三篇文章,大家应该基本对Tinymoe的代码有一个初步的感觉了.在正确分析"print ...