ASP.Net MVC / Web API自定义动态捆绑包在生产中工作但不在Dev中工作

时间:2013-09-02 16:00:33

标签: c# asp.net-mvc asp.net-mvc-4 web-optimization

在我的开发环境中,当我尝试加载动态生成的bundle时,我收到了404响应。奇怪的是,这不是在我们的生产环境中发生的,所以它不是真正的灾难性的,但它使开发有点令人沮丧。

应该发生的事情是:

  1. 在应用程序预启动(WebActivator PreStart)时,设置依赖性解析器,Web API和MVC配置。
  2. 在应用程序发布后(WebActivator PostStart),通过依赖项解析器加载服务(假设为IMyService)。
  3. 实例化自定义IBundleTransformJsonBundleTransform - 请参阅下面的代码)。
  4. 致电IEnumerable<string> IMyService.ListSupportedGroups()
  5. 循环支持的论坛并构建自定义论坛(CustomBundle - 见下文......)。
  6. 将自定义捆绑包添加到BundleTable.Bundles
  7. 将静态JS / CSS文件添加到BundleTable.Bundles
  8. 在网页中引用各种捆绑包,并在浏览器中查看内容。
  9. 对于包含404错误的自定义捆绑包,它在步骤8中失败。调试时,永远不会调用自定义包变换器。然而,正如我上面提到的,一切都在生产中运行良好 - 虽然我已经比较了配置文件,并且看不到我的开发配置中应该有任何影响的任何遗漏。此外,在生产中,无论web.config中的编译&gt; 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版本似乎不太可能)。

1 个答案:

答案 0 :(得分:1)

如果将“.js”附加到捆绑软件的虚拟路径,IIS会将对这些捆绑包的任何请求解释为对静态文件的请求,除非:

  • 您已指示IIS为所有请求运行所有托管模块
  • 您已明确配置IIS以使用路由处理程序
  • 处理捆绑网址

如果比较生产和开发配置,我怀疑你会发现生产环境的“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”,但这会产生性能问题,因为没有理由在整个托管管道中运行静态文件。