3

在我的开发环境中,当我尝试加载动态生成的包时收到 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. 在页面中引用各种捆绑包并在浏览器中查看内容。

对于具有 404 错误的自定义捆绑包,它在第 8 步失败。调试时,从不调用自定义捆绑转换器。然而,正如我上面提到的,在生产中一切正常——尽管我已经比较了配置文件并且看不到我的开发配置中缺少任何应该有任何影响的东西。此外,在生产环境中,无论 web.config 中的 compiler->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 版本似乎不太可能)。

4

1 回答 1

1

如果将“.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”,但这会带来性能问题,因为没有理由通过整个托管管道运行静态文件。

于 2014-02-03T18:56:21.857 回答