5

我需要拦截将发送到浏览器的所有 html 并替换那里的一些标签。这需要在全球范围内针对每个视图进行。使用 C# 在 ASP.NET MVC 3 或 4 中执行此操作的最佳方法是什么?过去,我使用 Global.asax (vb) 中的“response.filter”在 ASP.net Webforms 中完成了此操作

Private Sub Global_PreRequestHandlerExecute(ByVal sender As Object, ByVal e As System.EventArgs) Handles MyBase.PreRequestHandlerExecute
    Response.Filter = New ReplaceTags(Response.Filter)
End Sub

这调用了我创建的一个类,它继承自 system.io.stream 并遍历 html 以替换所有标签。我不知道如何使用 C# 在 ASP.NET MVC 4 中执行此操作。正如您可能已经注意到的那样,我是 MVC 世界的新手。

4

2 回答 2

10

您仍然可以在 ASP.NET MVC 中使用响应过滤器:

public class ReplaceTagsFilter : MemoryStream
{
    private readonly Stream _response;
    public ReplaceTagsFilter(Stream response)
    {
        _response = response;
    }

    public override void Write(byte[] buffer, int offset, int count)
    {
        var html = Encoding.UTF8.GetString(buffer);
        html = ReplaceTags(html);
        buffer = Encoding.UTF8.GetBytes(html);
        _response.Write(buffer, offset, buffer.Length);
    }

    private string ReplaceTags(string html)
    {
        // TODO: go ahead and implement the filtering logic
        throw new NotImplementedException();
    }
}

然后编写一个自定义操作过滤器,它将注册响应过滤器:

public class ReplaceTagsAttribute : ActionFilterAttribute
{
    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        var response = filterContext.HttpContext.Response;
        response.Filter = new ReplaceTagsFilter(response.Filter);
    }
}

现在剩下的就是装饰您想要应用此过滤器的控制器/操作:

[ReplaceTags]
public ActionResult Index()
{
    return View();
}

如果要应用于所有操作,或者将其注册为 Global.asax 中的全局操作过滤器。

于 2012-05-15T07:44:45.190 回答
5

答案是正确的但是。使用了一段时间后,我遇到了一个案例,响应被分成许多部分,因此 html 不正确

Part 1: 
<html>.....<labe

Part 2: 
l/>...</html>

部分渲染也可能会产生意想不到的情况。他们的 html 也不在主流之外。所以我的解决方案是在所有流式传输完成后在 Flush 方法中执行此操作。

    /// <summary>
    /// Insert messages and script to display on client when a partial view is returned
    /// </summary>
    private class ResponseFilter : MemoryStream
    {
        private readonly Stream _response;
        private readonly IList<object> _detachMessages;

        public override void Flush()
        {

            // add messages and remove
            // filter is called for a number of methods on one page (BeginForm, RenderPartial...)
            // so that we don't need to add it more than once

            var html = MessageAndScript(_detachMessages);
            var buffer = Encoding.UTF8.GetBytes(html);
            _detachMessages.Clear();
            _response.Write(buffer, 0, buffer.Length);

            base.Flush();
        }

        public ResponseFilter(Stream response, IList<object> detachMessages)
        {
            _response = response;
            _detachMessages = detachMessages;
        }

        public override void Write(byte[] buffer, int offset, int count)
        {
            _response.Write(buffer, offset, buffer.Length);    
        }

        private static string MessageAndScript(IList<object> detachMessages)
        {

            if (detachMessages.Count == 0)
                return null;

            var javascript = CustomJavaScriptSerializer.Instance.Serialize(detachMessages);

            return "$(function(){var messages = " + javascript + @";
// display messages
base.ajaxHelper.displayMessages(messages);
})";
        }
    }
于 2014-01-19T20:37:53.117 回答