Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/321.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何使Microsoft Bundle输出JavaScript而不是HTML脚本标记_C#_Asp.net_Asp.net Mvc 4_Bundle - Fatal编程技术网

C# 如何使Microsoft Bundle输出JavaScript而不是HTML脚本标记

C# 如何使Microsoft Bundle输出JavaScript而不是HTML脚本标记,c#,asp.net,asp.net-mvc-4,bundle,C#,Asp.net,Asp.net Mvc 4,Bundle,我正在构建一个基于ASP.NETMVC4的jQuery插件,我希望使用该标准 现在,通常情况下,当我使用捆绑机时,最终用途如下: @Scripts.Render(BundleConfig.jsBundleFile) 在调试中使用如下输出: <script src="/Scripts/..."></script> <script src="/Scripts/..."></script> <script src="/Scripts/..."&g

我正在构建一个基于ASP.NETMVC4的jQuery插件,我希望使用该标准

现在,通常情况下,当我使用捆绑机时,最终用途如下:

@Scripts.Render(BundleConfig.jsBundleFile)
在调试中使用如下输出:

<script src="/Scripts/..."></script>
<script src="/Scripts/..."></script>
<script src="/Scripts/..."></script>
<script src="/Scripts/..."></script>
<script src="/Scripts/..."></script>
<script src="/Scripts/..."></script>
在发行版中,我会得到缩小的内容

从这个例子中,我看到bundler在默认情况下无法做到这一点。但我想知道是有一个扩展可以做到这一点,还是另一个迷你库可以做到这一点?虽然我更喜欢微软捆绑包

在我自己关于如何扩展System.Web.Optimizer的研究中,我发现了
System.Web.Optimization
项目,据说该项目到目前为止还不是开源的,这使得扩展对于没有真正研究它的人来说有点困难

编辑:我知道我不能真正扩展System.Web.Optimizer,所以我选择了一个折衷的解决方案,这就是我最终使用的解决方案

在控制器中:

public JavaScriptResult jQueryComponent()
{
    JavaScriptResult ret = new JavaScriptResult();
    ClientSettings Model = new ClientSettings();

#if DEBUG
    List<string> jsFiles = App_Start.BundleConfig.Main.FilesToBeBundledJS;
    StringBuilder bundleBuilder = new StringBuilder();

    foreach (string file in jsFiles)
    {
        bundleBuilder.Append(System.IO.File.ReadAllText(Server.MapPath(file)));
    }

    ViewBag.bundledJS = bundleBuilder.ToString();
#else
    StringBuilder urlBuilder = new StringBuilder("http://localhost");

    int port = Request.Url.Port;
    if (port != -1) {
        urlBuilder.Append(':');
        urlBuilder.Append(port);
    }

    urlBuilder.Append(Scripts.Url(App_Start.BundleConfig.Main.jsBundleFile));

    WebClient wc = new WebClient();
    byte[] raw = wc.DownloadData(urlBuilder.ToString());
    string bundledJS = System.Text.Encoding.UTF8.GetString(raw);

    ViewBag.bundledJS = bundledJS;
#endif

    ret.Script = RenderRazorViewToString("~/Views/Main/jQueryComponent.cshtml", Model);

    return ret;
}

private string RenderRazorViewToString(string viewName, object model)
{
    ViewData.Model = model;
    using (StringWriter sw = new StringWriter())
    {
        ViewEngineResult viewResult = ViewEngines.Engines.FindPartialView(ControllerContext, viewName);
        ViewContext viewContext = new ViewContext(ControllerContext, viewResult.View, ViewData, TempData, sw);
        viewResult.View.Render(viewContext, sw);
        viewResult.ViewEngine.ReleaseView(ControllerContext, viewResult.View);
        return sw.GetStringBuilder().ToString();
    }
}
欢迎提出任何关于如何改进此功能的想法,以及对捆绑机的适当扩展。

虽然有效,但这还远远不够理想,我很清楚这一点。

除非您有其他选择,否则请不要批评这种方法。

创建自己的类和稳定的缩小器更容易

对于迷你型,您可以使用以下其中一种:

  • (请注意,webfleed已经包含了Ajax Minifier,如果同时添加两个NuGet包,可能会发生冲突)
您的自定义类应:

  • 静止
  • 包含一个
    列表
    以保存每个捆绑包中的文件
  • 在字典中,要保存捆绑包名称及其文件:
    dictionary
    带有捆绑包名称
    string
    ,以及文件名列表
    list
要创建非精简版本,只需将所有文件读入一个字符串,其中包含可用于此操作的任何类(对于ezample
StringBuilder
StringWriter
StreamReader
文件
)。如果需要模拟绑定器中的通配符名称,请使用
目录
,或者使用
正则表达式

读取的结果应该存储在静态字典中,该字典保存包名称和包内容(用于缓存,避免反复读取相同的文件)

最后,你需要缩小它

您可以根据两种不同的情况来切换minificacion:

  • c#code
    #ifdef debug
    中调试的定义<代码>#endif这取决于在configuration manager中选择的解决方案配置:调试/发布
使用YUI压缩机缩小尺寸:

  JavaScriptCompressor jsCompressor = new JavaScriptCompressor();
  jsCompressor.ObfuscateJavascript = true; // Optional
  string minified = jsCompressor.Compress(originalScript);
使用MS Ajax缩小器缩小:

  Minifier min = new Minifier();
  string minified = min.MinifyJavaScript(originalScript);
您还应该将缩小的版本存储在静态字典中,以缓存它们

这是一个基本的工作示例:

public class MyMinifier
{
    protected static Dictionary<string,List<string>> VirtualPathsInBundle
        = new Dictionary<string, List<string>>();

    protected static Dictionary<string, string> OriginalJavascriptInBundle
        = new Dictionary<string, string>();

    protected static Dictionary<string, string> MinifiedJavascriptInBundle
        = new Dictionary<string, string>();

    public static void AddBundle(string bundleName, params string[] virtualPaths)
    {
        VirtualPathsInBundle.Add(bundleName, virtualPaths.ToList());
    }

    public static string GetOriginalJavaScript(string bundleName)
    {
        if (!OriginalJavascriptInBundle.ContainsKey(bundleName))
        {
            var physicalFilePaths = VirtualPathsInBundle[bundleName]
                .Select(vp => HttpContext.Current.Server.MapPath(vp));
            // If you use wildcards, expand them here...
            StringBuilder scripts = new StringBuilder();
            foreach (var path in physicalFilePaths)
            {
                scripts.AppendFormat("// path: {0}", path);
                scripts.AppendLine();
                scripts.Append(File.ReadAllText(path));
            }
            OriginalJavascriptInBundle.Add(bundleName, scripts.ToString());
        }
        return OriginalJavascriptInBundle[bundleName];
    }

    public static string GetMinifiedJavaScript(string bundleName)
    {
        if (!MinifiedJavascriptInBundle.ContainsKey(bundleName))
        {
            Minifier minifier = new Minifier();
            MinifiedJavascriptInBundle[bundleName]
                = minifier.MinifyJavaScript(GetOriginalJavaScript(bundleName));
        }
        return MinifiedJavascriptInBundle[bundleName];
    }
}
公共类MyMinifier
{
受保护的静态字典VirtualPathsInBundle
=新字典();
受保护的静态字典原始JavaScriptInBundle
=新字典();
受保护的静态字典MinifiedJavascriptInBundle
=新字典();
公共静态void AddBundle(字符串bundleName,参数string[]virtualPath)
{
添加(bundleName,virtualPath.ToList());
}
公共静态字符串GetOriginalJavaScript(字符串bundleName)
{
如果(!OriginalJavascriptInBundle.ContainsKey(bundleName))
{
var physicalfilepath=VirtualPathsInBundle[bundleName]
.Select(vp=>HttpContext.Current.Server.MapPath(vp));
//如果使用通配符,请在此处展开它们。。。
StringBuilder脚本=新建StringBuilder();
foreach(PhysicalFilePath中的变量路径)
{
AppendFormat(“//路径:{0}”,路径);
scripts.AppendLine();
scripts.Append(File.ReadAllText(path));
}
原始JavaScriptInBundle.Add(bundleName,scripts.ToString());
}
返回原始JavaScriptInBundle[bundleName];
}
公共静态字符串GetMinifiedJavaScript(字符串bundleName)
{
如果(!MinifiedJavascriptInBundle.ContainsKey(bundleName))
{
Minifier Minifier=新Minifier();
MinifiedJavascriptInBundle[bundleName]
=minifier.MinifyJavaScript(GetOriginalJavaScript(bundleName));
}
返回MinifiedJavascriptInBundle[bundleName];
}
}

您可以执行BundleHandler所做的操作:基于虚拟路径(与您将使用的虚拟路径相同)获取一个
@Script.Render
),然后编写

简言之:

@Html.Raw(BundleTable.Bundles.GetBundleFor("~/VIRTUALPATH").GenerateBundleResponse(new BundleContext(this.Context, BundleTable.Bundles, string.Empty)).Content)
编辑:要在调试中获取未统一的内容,我们可以做什么:再次获取捆绑包,但不是生成响应,而是创建并写入它们的内容()


您是否尝试过Visual studio Web Essentials插件内置的捆绑功能?这个bundler在编译时而不是运行时绑定,这似乎适合您的需要@Andrew我不是一个真正的插件迷(插件在公司内很难推广,除非它们是MS插件),但从快速浏览到我,这为项目创建了一个单独的缩小文件,我可以将其包含到我的项目中。我更喜欢Web中的解决方案。Optimizer是我可以更新文件(在已部署的项目上)并让它们为客户端组合成一个JS文件,也就是说,所有的缩小都是在运行时完成的,而不是在项目部署中。为什么开发jquery插件需要简单javascript中的所有.JS?我开发了很多,但我看不出原因。也许你不应该尝试这样做,而应该改变你面对这个问题的方式。如果我理解你为什么认为你需要这个,希望我能给你展示好的选择。我从来都不需要它,在生产中有几个插件。它不是一个组件
public class MyMinifier
{
    protected static Dictionary<string,List<string>> VirtualPathsInBundle
        = new Dictionary<string, List<string>>();

    protected static Dictionary<string, string> OriginalJavascriptInBundle
        = new Dictionary<string, string>();

    protected static Dictionary<string, string> MinifiedJavascriptInBundle
        = new Dictionary<string, string>();

    public static void AddBundle(string bundleName, params string[] virtualPaths)
    {
        VirtualPathsInBundle.Add(bundleName, virtualPaths.ToList());
    }

    public static string GetOriginalJavaScript(string bundleName)
    {
        if (!OriginalJavascriptInBundle.ContainsKey(bundleName))
        {
            var physicalFilePaths = VirtualPathsInBundle[bundleName]
                .Select(vp => HttpContext.Current.Server.MapPath(vp));
            // If you use wildcards, expand them here...
            StringBuilder scripts = new StringBuilder();
            foreach (var path in physicalFilePaths)
            {
                scripts.AppendFormat("// path: {0}", path);
                scripts.AppendLine();
                scripts.Append(File.ReadAllText(path));
            }
            OriginalJavascriptInBundle.Add(bundleName, scripts.ToString());
        }
        return OriginalJavascriptInBundle[bundleName];
    }

    public static string GetMinifiedJavaScript(string bundleName)
    {
        if (!MinifiedJavascriptInBundle.ContainsKey(bundleName))
        {
            Minifier minifier = new Minifier();
            MinifiedJavascriptInBundle[bundleName]
                = minifier.MinifyJavaScript(GetOriginalJavaScript(bundleName));
        }
        return MinifiedJavascriptInBundle[bundleName];
    }
}
@{
    var context = new BundleContext(this.Context, BundleTable.Bundles, string.Empty);
    var bundle = BundleTable.Bundles.GetBundleFor("~/VIRTUALPATH");
    var response = bundle.GenerateBundleResponse(context);
    var content = response.Content;

    this.WriteLiteral(content);
}
@Html.Raw(BundleTable.Bundles.GetBundleFor("~/VIRTUALPATH").GenerateBundleResponse(new BundleContext(this.Context, BundleTable.Bundles, string.Empty)).Content)
@{
    var context = new BundleContext(this.Context, BundleTable.Bundles, string.Empty);
    var bundle = BundleTable.Bundles.GetBundleFor("~/VIRTUALPATH");

    if (BundleTable.EnableOptimizations)
    {
        var response = bundle.GenerateBundleResponse(context);
        var content = response.Content;

        this.WriteLiteral(content);
    }
    else
    {
        var files = bundle.EnumerateFiles(context);

        foreach (var file in files)
        {
            var stream = file.VirtualFile.Open();

            using (var reader = new StreamReader(stream))
            {
                this.Output.Write("{0}{1}", reader.ReadToEnd(), bundle.ConcatenationToken);
            }
        }
    }
}