2013-04-08 185 views
9

有没有人有任何想法如何在保持自定义编码风格的同时从Razor引擎输出缩小的HTML和JavaScript?ASP.NET MVC C#剃刀缩小

例如:我想以下代码:

<div 
    @if (Model.Name != string.Empty) 
     @:id="@Model.Name" 
> 
</div> 

要被输出为<div id="DivId"></div>

+0

另一种解决方案是将HTML标记作为字符串存储在一个JSON属性,并使用正则表达式 – Catalin 2013-04-08 11:49:37

回答

12

http://arranmaclean.wordpress.com/2010/08/10/minify-html-with-net-mvc-actionfilter/。 有一个例子用于创建自定义动作过滤器从WhiteSpaces清除HTML

更新:源代码引自上面。

用于去除 “空白”

using System; 
using System.IO; 
using System.Text; 
using System.Web.Mvc; 
using System.Text.RegularExpressions; 

namespace RemoveWhiteSpace.ActionFilters 
{ 
    public class WhiteSpaceFilter : Stream 
    { 

     private Stream _shrink; 
     private Func<string, string> _filter; 

     public WhiteSpaceFilter(Stream shrink, Func<string, string> filter) 
     { 
      _shrink = shrink; 
      _filter = filter; 
     } 


     public override bool CanRead { get { return true; } } 
     public override bool CanSeek { get { return true; } } 
     public override bool CanWrite { get { return true; } } 
     public override void Flush() { _shrink.Flush(); } 
     public override long Length { get { return 0; } } 
     public override long Position { get; set; } 
     public override int Read(byte[] buffer, int offset, int count) 
     { 
      return _shrink.Read(buffer, offset, count); 
     } 
     public override long Seek(long offset, SeekOrigin origin) 
     { 
      return _shrink.Seek(offset, origin); 
     } 
     public override void SetLength(long value) 
     { 
      _shrink.SetLength(value); 
     } 
     public override void Close() 
     { 
      _shrink.Close(); 
     } 

     public override void Write(byte[] buffer, int offset, int count) 
     { 
      // capture the data and convert to string 
      byte[] data = new byte[count]; 
      Buffer.BlockCopy(buffer, offset, data, 0, count); 
      string s = Encoding.Default.GetString(buffer); 

      // filter the string 
      s = _filter(s); 

      // write the data to stream 
      byte[] outdata = Encoding.Default.GetBytes(s); 
      _shrink.Write(outdata, 0, outdata.GetLength(0)); 
     } 
    } 
} 

流类ActionFilter类:

public class WhitespaceFilterAttribute : ActionFilterAttribute 
{ 

    public override void OnActionExecuting(ActionExecutingContext filterContext) 
    { 

     var request = filterContext.HttpContext.Request; 
     var response = filterContext.HttpContext.Response; 

     response.Filter = new WhiteSpaceFilter(response.Filter, s => 
       { 
        s = Regex.Replace(s, @"\s+", " "); 
        s = Regex.Replace(s, @"\s*\n\s*", "\n"); 
        s = Regex.Replace(s, @"\s*\>\s*\<\s*", "><"); 
        s = Regex.Replace(s, @"<!--(.*?)-->", ""); //Remove comments 

        // single-line doctype must be preserved 
        var firstEndBracketPosition = s.IndexOf(">"); 
        if (firstEndBracketPosition >= 0) 
        { 
         s = s.Remove(firstEndBracketPosition, 1); 
         s = s.Insert(firstEndBracketPosition, ">"); 
        } 
        return s; 
       }); 

     } 

} 

而在最后的上面的用法:

[HandleError] 
[WhitespaceFilter] 
public class HomeController : Controller 
{ 
    ... 
} 
+1

你应该编辑你的答案以包含一个例子,因为链接应该死掉。 – 2015-04-23 17:09:24

+0

@ ashley-medway应对这整个例子将是困难的。因为我将不得不复制文本和图像。你不觉得吗? – 2015-04-23 18:09:41

+1

这可能是困难的,但其正确的做法否则这个职位可能会变得毫无用处。 – 2015-04-23 21:34:31

4

我不认为有什么办法可以做到这一点。为了避免标签汤我平时比较喜欢编写自定义的助手:

@using(Html.MyDiv(Model.Name)) 
{ 
    ... put the contents of the div here 
} 

和这里的自定义助手如何可能看起来像:

public static class HtmlExtensions 
{ 
    private class Div : IDisposable 
    { 
     private readonly ViewContext context; 
     private bool disposed; 

     public Div(ViewContext context) 
     { 
      this.context = context; 
     } 

     public void Dispose() 
     { 
      this.Dispose(true); 
      GC.SuppressFinalize(this); 
     } 

     protected virtual void Dispose(bool disposing) 
     { 
      if (!this.disposed) 
      { 
       this.disposed = true; 
       context.Writer.Write("</div>"); 
      } 
     } 
    } 

    public static IDisposable MyDiv(this HtmlHelper html, string id) 
    { 
     var div = new TagBuilder("div"); 
     if (!string.IsNullOrEmpty(id)) 
     { 
      div.GenerateId(id); 
     } 
     html.ViewContext.Writer.Write(div.ToString(TagRenderMode.StartTag)); 
     return new Div(html.ViewContext);    
    } 
} 

或者你也可以做一个标记汤:

<[email protected](Model.Name != string.Empty ? string.Format(" id=\"{0}\"", Html.AttributeEncode(Model.Name)) : string.Empty)> 
</div> 
+1

自定义助手从JSON属性中删除多余的HTML标记会一直在我的建议:) – 2013-04-08 11:35:05

2

也许您在寻找Meleze.Web

Meleze.Web是优化ASP.NET MVC 3.0和MVC 4.0应用程序的工具箱。
它提供了Razor视图的HTML,JS和CSS缩小以及返回页面的缓存。

达林季米特洛夫写一下这里:ASP.Net MVC Razor Views - Minifying HTML at build time

,但我认为让gzip是更好的解决方案,你可以在这里读到它:Minify HTML output from an ASP.Net MVC Application

+1

Meleze.web不会再压缩部分美景。 – hiddenUser 2013-04-09 09:08:52

+0

@ user2256464看起来像是开放的bug:https://github.com/meleze/Meleze.Web/issues/12 – webdeveloper 2013-04-09 10:06:40

+2

@webdeveloper在这些问题中,我总是看到这个回复“_enabling gzip is better solution_”。在同一时间缩小_and_ gzip会不会更好?甚至抛出js和css等客户端缓存? – snajahi 2014-04-15 06:40:29