在我的开发环境中,当我尝试加载动态生成的捆绑包时,我会收到404个响应。奇怪的是,这并没有发生在我们的生产环境中,所以这并不是真正的灾难,但它让开发有点令人沮丧。
应该发生的是:
- 在应用程序预启动(WebActivatorPreStart)时,设置DependencyResolver、Webneneneba API和MVC配置
- 在应用程序后启动(WebActivatorPostStart)时,通过依赖解析程序(比如
IMyService
)加载服务 - 实例化自定义
IBundleTransform
(JsonBundleTransform
-请参阅下面的代码) - 致电
IEnumerable<string> IMyService.ListSupportedGroups()
- 循环使用支持的组并构建自定义捆绑包(
CustomBundle
-请参阅下文…) - 将自定义捆绑包添加到
BundleTable.Bundles
- 将静态JS/CSS文件添加到
BundleTable.Bundles
中 - 在页面中引用各种捆绑包,并在浏览器中查看内容
对于自定义捆绑包,它在步骤8失败,出现404个错误。调试时,永远不会调用自定义bundle transformer。然而,正如我上面提到的,在生产中一切都很好——尽管我已经比较了配置文件,但在我的开发配置中没有发现任何遗漏,这应该会有任何效果。此外,在生产中,无论web.config中的compilation->debug值如何,捆绑内容都会正确呈现。
其他注意事项:
- 我在生产中使用IIS 7.5,在开发中使用IIS 8
- 当我在dev中设置debug="false"时,我在所有捆绑包上都会得到404
- 这是有效的,但在某个时候停止了,我无法确定何时或为什么会发生这种情况
我使用的代码如下(删除多余的代码,更改名称以保护无辜者,等等):
转换
public class JsonBundleTransform: IBundleTransform
{
public void Process( BundleContext context, BundleResponse response )
{
var bundle = context.BundleCollection.FirstOrDefault(b => b.Path == context.BundleVirtualPath) as CustomBundle;
response.Content = string.Format( ";var obj = {0};", JsonConvert.SerializeObject( bundle.KeyValues ) );
response.ContentType = "application/javascript";
response.Cacheability = HttpCacheability.Server;
}
}
自定义捆绑包
public class CustomBundle: Bundle
{
public CustomBundle( string virtualPath, IBundleTransform transform, IMyService myService, string groupId ) : base( virtualPath, transform )
{
keyValues = myService.GetKeyValuesByGroupId( groupId );
}
public IDictionary<string, string> KeyValues { get; private set; }
}
配置
public class BundleConfig
{
public static void RegisterBundles( BundleCollection bundles, IMyService myService )
{
var transform = new JsonBundleTransform();
var jsonBundles = myService
.ListSupportedGroups()
.Select( groupId =>
new CustomBundle(
string.Format( "~/resource/script/keyValues-{0}.js", groupId ),
transform,
myService,
groupId
)
);
foreach ( var jsonBundle in jsonBundles ) {
bundles.Add( jsonBundle );
}
// Static bundles added here...
}
}
渲染脚本
@Scripts.Render( Url.Content( string.Format( "~/resource/script/keyValues-{0}.js", Model.GroupId ) ) ) )
知道我在这里错过了什么吗?
提前感谢您提供的任何帮助或建议。
编辑
考虑到它正在生产中,我强烈倾向于认为这个问题是环境问题,而不是代码问题——尽管,就我而言,我还不知道它是什么。我认为最有可能的候选者是与配置或引用有关的东西(老实说,IIS版本似乎是不太可能的原因)。
如果将".js"附加到捆绑包的虚拟路径,IIS将把对这些捆绑包的任何请求解释为对静态文件的请求,除非:
- 您已指示IIS为所有请求运行所有托管模块
- 您已明确配置IIS以使用路由处理程序处理捆绑包URL
如果您比较生产和开发配置,我怀疑您会发现生产环境的"runAllManagedModulesForAllRequests"设置为"true"。
解决这个问题最简单的方法就是从捆绑包的虚拟路径中删除".js"扩展名。如果您希望保留扩展,可以配置IIS将请求传递给路由处理程序:
<system.webServer>
<handlers>
<add name="UrlRoutingHandler"
type="System.Web.Routing.UrlRoutingHandler,
System.Web, Version=4.0.0.0,
Culture=neutral,
PublicKeyToken=b03f5f7f11d50a3a"
path="/resource/script/*"
verb="GET"/>
</handlers>
</system.webServer>
您也可以启用"runAllManagedModulesForAllRequests",但这会带来性能问题,因为没有理由在整个托管管道中运行静态文件。