2012-05-14 5 views
4

Мне нужно перехватить весь html, который будет отправлен в браузер, и заменить некоторые теги, которые есть. это нужно делать во всем мире и для каждого взгляда. Каков наилучший способ сделать это в ASP.NET MVC 3 или 4 с помощью C#? В прошлом я сделал это в ASP.NET WebForms с использованием «Response.Filter» в Global.asax (Vb)asp.net MVC 3/4 эквивалент response.filter

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, чтобы заменить все теги. Я понятия не имею, как это сделать в ASP.NET MVC 4 с использованием C#. Как вы могли заметить, я полностью новичок в мире MVC.

+0

Проверить эту ссылку: http://msdn.microsoft.com/en-us/library/gg416513(v=vs.98).aspx – Chandu

+0

Этот ответ показывает, как использовать фильтр ответа переписать итоговый HTML. http://stackoverflow.com/a/8382617/64750 – HackedByChinese

ответ

8

Вы все еще можете использовать фильтр ответа в 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, если вы хотите применить ко всем действиям.

+0

Фильтр появляется только тогда, когда код выходит из функции OnActionExecuting. Как я могу получить доступ к буфере потока до того, как ответ действительно будет выписан? – River

+1

Весь смысл фильтра Response - изменить поток ответов. Но для того, чтобы изменить его, этот поток должен быть сначала написан. –

+5

Это не похоже на работу с Razor. Я получаю «Фильтрация не допускается» HttpException при попытке добавить фильтр в ответ. –

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); 
})"; 
     } 
    } 
+0

Я испытал это, когда поток раскололся, я в конечном итоге с большим количеством странных "??" символы в исходном коде, что делает страницу странной. Вы столкнулись с этим? – Maritim

Смежные вопросы