ASP.NET CssMinify,HttpContextBase

标签 asp.net css asp.net-mvc asp.net-mvc-4 minify

我有一个 ASP.NET 应用程序,它需要为 View 设置多个布局。有一个正常的 Web 布局,以及一个没有依赖项的自包含页面的“静态”布局(用作文档管理系统中的显示模板)。

让 View 切换其布局非常容易。

因此,全合一页面布局需要将其所有 CSS 包含在 <style> 中页面内的标记。我找到了一种方法来找出 bundle 中的文件并编写了如下方法:

@MyCode.IncludeCSS("~/StaticLayout/css")

它读取包中的 CSS 文件并将其内容发送到 <style> 内的页面中标签。

但我想缩小 CSS。

我找不到关于 System.Web.Optimization.CssMinify 的任何文档.您需要调用 Process方法,需要 BundleContext .那么……找到一个,创造一个? MSDN isn't much use :

public BundleContext(
    HttpContextBase context,
    BundleCollection collection,
    string bundleVirtualPath
)

Parameters
    context
        Type: System.Web.HttpContextBase
        The context.

嗯,这绝对有用。我无法知道 context (类型上下文)是上下文,直到雷德蒙德的某个大脑膨胀的智力巨人从他忙碌的午睡中抽出一些时间用他肥大的小爪子在它前面推一个确定的文章,然后在一滩温暖的口水中昏倒.

尽管如此,我仍然不知道它是什么,也不知道您从哪里得到它,谷歌也不知道。 HttpContext.Current不是从它派生的,也没有(我能找到的)属性。

This page有一些关于正常捆绑的好信息,但它假设框架将以传统方式进行捆绑并提供捆绑内容,作为单独请求的资源。

有人做过吗?

最佳答案

埃德·普朗克特,

如果您将其用作 HTML 助手,则 HttpContextBase可以从ViewContext.HttpContext中获取属性(property)。可以这样创建。

public static IHtmlString BundleCss(this HtmlHelper html, string outputPath, params string[] cssFilePaths)
{
    var collection = new BundleCollection();
    foreach (var cssFilePath in cssFilePaths)
        collection.Add(new Bundle(cssFilePath));

    var bundler = new BundleContext(html.ViewContext.HttpContext, collection, outputPath);
    //... ommitted code
    System.Web.Optimization.CssMinify minify = new CssMinify();
    minify.Process(bundler, response);
    //... TODO: Grab the response content and return
}

是的,这是一个使用 HTML 帮助程序的基本示例。如果这不能回答您的问题,请告诉我。

编辑:重新阅读问题后,我正在澄清我的回答。所以以上有助于找到 HttpContextBase问题的属性(property)。但是我认为问题是如何实际读取文件的内容,缩小它们并将它们放入 <style> 中。页面上的标记。

我试着写下我自己对您的要求的解释,并提出了以下一组类

我的 CssOutputBundler 类:

public class CssOutputBundler
{
    static readonly Dictionary<string, string> cachedOutput = new Dictionary<string, string>();
    readonly string tempFileOutputPath;
    readonly HtmlHelper helper;
    readonly IList<string> virtualFilePaths;

    public CssOutputBundler(HtmlHelper helper, string tempFileOutputPath)
    {
        if (helper == null)
            throw new ArgumentNullException("helper null");
        if (string.IsNullOrWhiteSpace(tempFileOutputPath))
            this.tempFileOutputPath = tempFileOutputPath;
        this.helper = helper;
        this.virtualFilePaths = new List<string>();
        this.tempFileOutputPath = tempFileOutputPath;
    }

    public CssOutputBundler Add(string cssFilePath)
    {
        if (!this.virtualFilePaths.Contains(cssFilePath))
            this.virtualFilePaths.Add(cssFilePath);
        return this;
    }

    public IHtmlString Minify()
    {
        if (helper == null)
            throw new ArgumentNullException("helper null");

        string cache_string = string.Join(",", this.virtualFilePaths);
        if(cachedOutput.ContainsKey(cache_string))
            return formatResponse(File.ReadAllText(cachedOutput[cache_string]));
        var bundle = new StyleBundle(this.tempFileOutputPath).Include(this.virtualFilePaths.ToArray());
        var collection = new BundleCollection();
        collection.Add(bundle);
        var context = new BundleContext(helper.ViewContext.HttpContext, collection, "");
        var response = bundle.GenerateBundleResponse(context);
        System.Web.Optimization.CssMinify minify = new CssMinify();
        minify.Process(context, response);
        string serverPath = helper.ViewContext.HttpContext.Server.MapPath(this.tempFileOutputPath);
        string outputPath = Guid.NewGuid().ToString() + ".css";
        while(File.Exists(Path.Combine(serverPath, outputPath)))
            outputPath = Guid.NewGuid().ToString() + ".css";

        File.WriteAllText(outputPath, response.Content);
        cachedOutput[cache_string] = outputPath;
        return formatResponse(response.Content);
    }

    IHtmlString formatResponse(string responseContent)
    {
        StringBuilder responseBuilder = new StringBuilder();
        responseBuilder.AppendLine("<style type=\"text/css\">");
        responseBuilder.Append(responseContent);
        responseBuilder.AppendLine("</style>");
        return helper.Raw(responseBuilder.ToString());
    }
}

好的,上面的类看起来很复杂,但它所做的只是创建一个内部路径列表,供打包器打包和缩小。当调用 Minify 方法时,它将虚拟路径格式化为字符串,用作缓存键。这就是我们确定是否已经捆绑和缩小这些脚本的方式。

如果我们从存储在 HDD 上的临时捆绑脚本中读取。

注意: 我使用硬盘存储而不是内存存储。这可以通过将完整内容填充到静态字典或其他缓存介质中轻松更改。

如果此文件集尚未打包、缩小等,那么我们将继续打包和缩小该集。最后我们将文件存储到硬盘上并返回响应。所以这很简单。

现在要实现这个类,我刚刚编写了一个快速的 HTML Helper,因为 Minification 类支持 Add 的链接。文件方法可以很好地实现。

HTML 助手:

public static CssOutputBundler BundleCss(this HtmlHelper helper, string outputVirtualPath)
{
    return new CssOutputBundler(helper, outputVirtualPath);
}

好的, bundler 的基本实现。现在这个助手接受字符串 outputVirtualPath这是存储临时文件的虚拟路径。如果您确实决定取消保存到 HDD 并使用缓存系统,您可以从帮助程序和类中删除此参数。

最后,这可以在您的 View 中用作...

@Html.BundleCss("~/Content/").Add("~/Content/Site.css").Add("~/Content/themes/base/jquery-ui.css").Minify();

哪里~/Content/是硬盘上用于存储缩小文件的虚拟路径。然后我们添加两个文件 "~/Content/Site.css"~/Content/themes/base/jquery-ui.css .最后调用返回 html 字符串的 minify 方法。比如……

<style type="text/css">
.ui-helper-hidden{display:none}.ui-helper-hidden-accessible{position:absolute!important;clip:rect(1px 1px 1px 1px);clip:rect(1px,1px,1px,1px)} ....more css
</style>

干杯。

关于ASP.NET CssMinify,HttpContextBase,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21269035/

相关文章:

c# - 如何将 XML 返回到响应流?

c# - 一个 View 中的 MVC 多个模型

javascript - 在行中找到某些文本,然后隐藏这些行

javascript - jquery 将类添加到 if, else 语句中的变量

html - 从中心到特定位置的 CSS 动画

c# - 如何在 asp.net MVC View 中有条件地设置模型?

asp.net - 仅增加特定网页上的请求超时

asp.net-mvc - ASP.NET MVC 适用于复杂的 Web 应用程序吗?

asp.net-mvc - 在 EF5 迁移中将字段定义为自动增量

c# - 将可空位数据库列绑定(bind)到 GridView 中的 CheckBox - 空时崩溃