这个有可能。对于部分视图,它更简单,因为您可以Html.Partial
直接捕获输出,在将响应写入输出流之前对其进行修改。
为此,您将创建一个扩展方法,它可能看起来像这样:
public static class HtmlExtensions
{
public static HtmlString PartialIE9TableFix(this HtmlHelper helper,
string view, object model = null)
{
var partialOutput = helper.Partial(view, model).ToString();
partialOutput = Regex.Replace(partialOutput, @"/td>\s+<td",
"/td><td", RegexOptions.IgnoreCase);
return MvcHtmlString.Create(partialOutput);
}
}
如您所见,它Html.Partial
直接捕获 的输出,然后对其执行替换。您可以像这样在视图中使用它:
@Html.PartialIE9TableFix("YourPartial")
但是,要为实际视图执行此操作需要更多的工作,并且在使用它时当然要更加小心。为了做到这一点,我们实际上需要在将响应流发送到客户端之前对其进行捕获和修改。
下面IE9TableFixFilter
的代码非常基于Minify HTML with .NET MVC ActionFilter的代码。
using System;
using System.IO;
using System.Text;
public class IE9TableFixFilter : Stream
{
public IE9TableFixFilter(Stream response, Func<string, string> filter)
{
this.response = response;
this.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() { response.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 response.Read(buffer, offset, count);
}
public override long Seek(long offset, SeekOrigin origin)
{
return response.Seek(offset, origin);
}
public override void SetLength(long value)
{
response.SetLength(value);
}
public override void Close()
{
response.Close();
}
public override void Write(byte[] buffer, int offset, int count)
{
//byte[] data = new byte[count];
//Buffer.BlockCopy(buffer, offset, data, 0, count);
string s = Encoding.Default.GetString(buffer);
s = filter(s);
byte[] outData = Encoding.Default.GetBytes(s);
response.Write(outData, 0, outData.GetLength(0));
}
private Stream response;
private Func<string, string> filter;
}
这里的大部分代码都是abstract
为Stream
. 重要的部分是Write
方法中发生了什么。
文章中的版本Write
首先复制流的字节而不实际使用它们。如果这是出于某种特定原因,则没有提及,但这对我来说似乎没用,所以我将这些行注释掉了。
接下来,我们需要创建一个简单ActionFilter
的应用响应过滤器:
using System.Text.RegularExpressions;
using System.Web.Mvc;
public class IE9TableFixFilterAttribute : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
var response = filterContext.HttpContext.Response;
response.Filter = new IE9TableFixFilter(response.Filter,
s => Regex.Replace(s, @"/td>\s+<td", "/td><td", RegexOptions.IgnoreCase));
}
}
现在一切都完成了,我强烈建议您不要全局应用此过滤器,而是选择在需要使用它的操作上装饰它。这样做的原因是因为它自然会导致一些性能损失,所以最好明确说明何时真正需要它。使用它时,您将不需要部分扩展方法。因此,只需装饰您的操作即可使用它:
[IE9TableFixFilterAttribute]
public ActionResult Index()
{
return View();
}
更新
为了使过滤器属性更有效,您实际上可以将其应用于包含用户代理字符串的浏览器MSIE 9.0
:
public class IE9TableFixFilterAttribute : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
var request = filterContext.HttpContext.Request;
var response = filterContext.HttpContext.Response;
if (request.UserAgent.Contains("MSIE 9.0"))
{
response.Filter = new IE9TableFixFilter(response.Filter,
s => Regex.Replace(s, @"/td>\s+<td", "/td><td", RegexOptions.IgnoreCase));
}
}
}