【问题标题】:MVC4 bundles by host name按主机名的 MVC4 捆绑包
【发布时间】:2013-01-04 17:37:59
【问题描述】:

我是 MVC 新手。

我知道如何创建捆绑包,它很简单,而且是一个很棒的功能:

  bundles.Add(new StyleBundle("~/content/css").Include(
    "~/content/main.css",
    "~/content/footer.css",
    "~/content/sprite.css"
    ));

但是假设您的应用程序可以在不同的域下访问,并根据主机名使用不同的 css 提供不同的内容。

如何让捆绑包根据主机名包含不同的文件? 在我的 RegisterBundles 所在的应用程序开始(就像我开始使用的 MVC 标准互联网应用程序一样)我什至不知道主机名。

最佳做法是什么?

如果我在注册捆绑包时有可用的主机名,我可以为当前主机名选择正确的 .css 文件。 例如,我可以在应用程序开始请求上注册捆绑包,并以某种方式检查它是否已经注册,如果没有,为请求的主机名选择正确的文件并注册它?

如果是,怎么做?

编辑 1

在过去的两个小时里,我对这个话题进行了更深入的研究,让我提出我的解决方案,希望比我更擅长 MVC 的人可以纠正我的方法,如果有错误。

我换了:

@Styles.Render("~/Content/css")

与:

@Html.DomainStyle("~/Content/css")

这只是一个简单的助手:

public static class HtmlExtensions
{
  public static IHtmlString DomainStyle(this HtmlHelper helper, string p)
  {
    string np = mynamespace.BundleConfig.RefreshBundleFor(System.Web.Optimization.BundleTable.Bundles, "~/Content/css");

    if (!string.IsNullOrEmpty(np))
      return Styles.Render(np);
    else
    {
      return Styles.Render(p);
    }
  }
}

RefreshBundleFor 在哪里:

public static string RefreshBundleFor(BundleCollection bundles, string p)
{
  if (bundles.GetBundleFor(p) == null)
    return null;

  string domain = mynamespace.Utilities.RequestUtility.GetUpToSecondLevelDomain(HttpContext.Current.Request.Url);

  string key = p + "." + domain;

  if (bundles.GetBundleFor(key) == null)
  {
    StyleBundle nb = new StyleBundle(key);

    Bundle b = bundles.GetBundleFor(p);
    var bundleContext = new BundleContext(new HttpContextWrapper(HttpContext.Current), BundleTable.Bundles, p);

    foreach (FileInfo file in b.EnumerateFiles(bundleContext))
    {
      string nf = file.DirectoryName + "\\" + Path.GetFileNameWithoutExtension(file.Name) + "." + domain + file.Extension;
      if (!File.Exists(nf))
        nf = file.FullName;

      var basePath = HttpContext.Current.Server.MapPath("~/");
      if (nf.StartsWith(basePath))
      {
        nb.Include("~/" + nf.Substring(basePath.Length));
      }
    }
    bundles.Add(nb);
  }

  return key;
}

而 GetUpToSecondLevelDomain 只是从主机名中返回二级域,因此 GetUpToSecondLevelDomain("www.foo.bar.com") = "bar.com"。

怎么样?

【问题讨论】:

    标签: c# asp.net-mvc-4 bundle


    【解决方案1】:

    过于复杂 - Request 对象在 Application_Start 中可用。只需使用:

    var host = Request.Url.Host;
    

    在您注册您的捆绑包之前,并根据返回的值有条件地注册您的捆绑包。

    更新 使用域密钥注册所有捆绑包:

    StyleBundle("~/content/foo1.css")...
    StyleBundle("~/content/foo2.css")...
    

    然后在所有控制器都继承的基础控制器中,您可以构建捆绑包名称以传递给视图:

    var host = Request.Url.Host;  // whatever code you need to extract the domain like Split('.')[1]
    ViewBag.BundleName = string.Format("~/content/{0}.css", host);
    

    然后在布局或视图中:

    @Styles.Render(ViewBag.BundleName)
    

    【讨论】:

    • 但我怀疑这还不够。 Application_Start 仅在应用程序启动时调用,同一应用程序上的多个域意味着它在来自一个域的第一个请求时启动,但在来自其他域的后续请求时启动?
    • 您将消耗大量 CPU 时间来尝试对每个请求进行捆绑和优化,这很可能会减慢您的响应速度并破坏捆绑/最小化的目的。您最好一次捆绑/最小化所有特定于域的捆绑包,然后使用布局和/或控制器来选择正确的捆绑包。
    • 我建议在布局中这样做,几个简单的 if 语句就完成了。我不喜欢布局、视图等方面的逻辑,但这是一个很好的例外。
    • 但是我不会在每个请求上捆绑最小化,我只在第一次找不到捆绑包时这样做,这就是“if (bundles.GetBundleFor(key) == null)”的目的, 如果它与 null 不同,则什么也不做。
    • @viperguynaz 请求对象在 Application_Start 中不可用,请参阅 stackoverflow.com/questions/5750030/…
    猜你喜欢
    • 2012-06-21
    • 1970-01-01
    • 1970-01-01
    • 2012-11-20
    • 2013-07-03
    • 2012-03-28
    • 2013-04-02
    • 2012-07-22
    • 2012-06-06
    相关资源
    最近更新 更多