自定义HttpResponse的Filter修改Http Entity Body

HttpResponse的Filter属性允许开发人员定义一个派生于Stream的类型,修改Http Entity Body。比如原来的Web应用程序并没有添加兼容性标记,许多页面也并没有使用Master,各处修改增加了许多工作量。编写一个HttpModule,在Init函数中订阅HttpApplication的ReleaseRequestState事件。

1 // <summary>
2 /// 初始化
3 /// </summary>
4 /// <param name=”context”>上下文</param>
5 public void Init(HttpApplication context)
6 {
7   context.ReleaseRequestState += new EventHandler(OnReleaseRequestState);
8 }

新建一个派生于Stream的类型HeadRequestFilter,并在ReleaseRequestState事件触发后为HttpResponse的Filter属性赋值:

 1 /// <summary>
 2 /// 释放请求状态
 3 /// </summary>
 4 /// <param name=”sender”>发送方</param>
 5 /// <param name=”e”>事件参数</param>
 6 private void OnReleaseRequestState(Object sender, EventArgs e)
 7 {
 8   HttpResponse response = HttpContext.Current.Response;
 9 
10   response.Filter = new HeadRequestFilter(response.Filter);
11 }

由于我们只需要为head标签内添加meta标签,所以HttpResponse原来的HttpResponseStreamFilterSink依然可以被使用。需要修改的是Stream定义的Write和Flush函数。在执行Flush函数前需要通过StringBuilder保存旧有输出的HTML:

m_buffer.Append(HttpContext.Current.Response.ContentEncoding.GetString(buffer, offset, count));

在调用Flush函数内部插入meta标签,最后调用HttpResponse输出修改后的Http Entity Body。下面是一个实现插入meta标签的HeadResponseFilter示例:

  1 public sealed class HeadResponseFilter : Stream
  2 {
  3   private const String TAG_HEAD_BEGIN = “<head”;
  4   private const String TAG_HEAD_END = “</head>”;
  5 
  6   private StringBuilder m_buffer;
  7   private Stream m_stream;
  8 
  9   /// <summary>
 10   /// 构造函数
 11   /// </summary>
 12   /// <param name=”stream”></param>
 13   public HeadResponseFilter(Stream stream)
 14   {
 15     m_stream = stream;
 16     m_buffer = new StringBuilder();
 17   }
 18 
 19   /// <summary>
 20   /// 请求
 21   /// </summary>
 22   public HttpRequest Request
 23   {
 24     get
 25     {
 26       return HttpContext.Current.Request;
 27     }
 28   }
 29 
 30   /// <summary>
 31   /// 响应
 32   /// </summary>
 33   public HttpResponse Response
 34   {
 35     get
 36     {
 37       return HttpContext.Current.Response;
 38     }
 39   }
 40 
 41   /// <summary>
 42   /// 可读
 43   /// </summary>
 44   public override Boolean CanRead
 45   {
 46     get { return true; }
 47   }
 48 
 49   /// <summary>
 50   /// 可查询
 51   /// </summary>
 52   public override Boolean CanSeek
 53   {
 54     get { return true; }
 55   }
 56 
 57   /// <summary>
 58   /// 可写
 59   /// </summary>
 60   public override Boolean CanWrite
 61   {
 62     get { return true; }
 63   }
 64 
 65   /// <summary>
 66   /// 长度
 67   /// </summary>
 68   public override Int64 Length
 69   {
 70     get { return 0; }
 71   }
 72 
 73   /// <summary>
 74   /// 位置
 75   /// </summary>
 76   public override Int64 Position { get; set; }
 77 
 78   /// <summary>
 79   /// 刷新
 80   /// </summary>
 81   public override void Flush()
 82   {
 83     String rawHtml = m_buffer.ToString();
 84     Int32 headIndex = rawHtml.IndexOf(TAG_HEAD_BEGIN, StringComparison.CurrentCultureIgnoreCase);
 85     Int32 headIndex2 = rawHtml.IndexOf(TAG_HEAD_END, StringComparison.CurrentCultureIgnoreCase);
 86 
 87     if ((headIndex > 0) && (headIndex2 > 0) && (headIndex < headIndex2))
 88     {
 89       String rawHead = rawHtml.Substring(headIndex, headIndex2 – headIndex + TAG_HEAD_END.Length);
 90       XElement headElement = XElement.Parse(rawHead);
 91       IEnumerable<XElement> metaElement = headElement.Descendants(“meta”).Where(p => p.Attribute(“http-equiv”) != null);
 92 
 93       if (metaElement.Count() == 0)
 94         headElement.Add(new XElement(“meta”, new XAttribute(“http-equiv”, “x-ua-compatible”), new XAttribute(“content”, “IE=7″)));
 95 
 96       rawHtml = String.Concat(rawHtml.Substring(0, headIndex), headElement.ToString(), rawHtml.Substring(headIndex + rawHead.Length));
 97     }
 98 
 99     this.Response.Write(rawHtml);
100     this.Response.Flush();
101   }
102 
103   /// <summary>
104   /// 读取
105   /// </summary>
106   /// <param name=”buffer”>缓冲区</param>
107   /// <param name=”offset”>偏移量</param>
108   /// <param name=”count”>数量</param>
109   /// <returns>读取数量</returns>
110   public override Int32 Read(Byte[] buffer, Int32 offset, Int32 count)
111   {
112     return m_stream.Read(buffer, offset, count);
113   }
114 
115   /// <summary>
116   /// 查找
117   /// </summary>
118   /// <param name=”offset”>偏移量</param>
119   /// <param name=”origin”>参考点</param>
120   /// <returns>位置</returns>
121   public override Int64 Seek(Int64 offset, SeekOrigin origin)
122   {
123     return m_stream.Seek(offset, origin);
124   }
125 
126   /// <summary>
127   /// 设置长度
128   /// </summary>
129   /// <param name=”value”></param>
130   public override void SetLength(Int64 value)
131   {
132     m_stream.SetLength(value);
133   }
134 
135   /// <summary>
136   /// 写入
137   /// </summary>
138   /// <param name=”buffer”>缓冲区</param>
139   /// <param name=”offset”>偏移量</param>
140   /// <param name=”count”>数量</param>
141   public override void Write(Byte[] buffer, Int32 offset, Int32 count)
142   {
143     m_buffer.Append(HttpContext.Current.Response.ContentEncoding.GetString(buffer, offset, count));
144   }
145 }
原文地址:https://www.cnblogs.com/junchu25/p/2633463.html