asp.net MVC 3/4相当于一个response.filter

时间:2012-05-14 22:00:59

标签: asp.net asp.net-mvc-3 response.filter

我需要拦截将发送到浏览器的所有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世界中是一个全新的人。

2 个答案:

答案 0 :(得分:9)

您仍然可以在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中的全局操作过滤器。

答案 1 :(得分: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);
})";
        }
    }