2013-12-24 10 views
5

VERSION 2Der beste Ort Text in asp.net Mvc pipline

ich den ursprünglichen Code unter Berücksichtigung der Tatsache, aktualisiert zu ersetzen, dass die Schreibmethode den HTML von der Seite in Blöcken übertragen.

Wie bereits erwähnt, da Sie nicht garantiert haben, dass "THE_PLACEHOLDER" in einem zusammenhängenden Byteblock geschrieben wird. Sie können "THE_PLACEH" am Ende eines Anrufs erhalten, um zu schreiben, und "OLDER" am Anfang des nächsten.

Ich habe das behoben, indem ich den kompletten Inhalt des Streams in einen StringBuilder einfüge und alle Aktualisierungen mache, die für die Close-Methode erforderlich sind.

Nachdem dies erledigt ich wieder unter der gleichen Frage mich frage ....


Ich arbeite an einem CMS, die einfach einen Platzhalter mit dem CMS Text ersetzt.

Ich habe Folgendes, das funktioniert, wie es sollte.

Ich habe die IHttpModule außer Kraft gesetzt

public class CmsFilterHttpModule : IHttpModule { 

    // In the Init method, register HttpApplication events by adding event handlers. 
    public void Init(HttpApplication httpApplication) { 

    httpApplication.ReleaseRequestState += new EventHandler(this.HttpApplication_OnReleaseRequestState); 

    } 

    /// <summary> 
    /// HttpApplication_OnReleaseRequestState event handler. 
    /// 
    /// Occurs after ASP.NET finishes executing all request event handlers. 
    /// This event causes state modules to save the current state data. 
    /// </summary> 
    private void HttpApplication_OnReleaseRequestState(Object sender, EventArgs e) { 

    HttpResponse httpResponse = HttpContext.Current.Response; 

    if (httpResponse.ContentType == "text/html") { 

     httpResponse.Filter = new CmsFilterStream(httpResponse.Filter); 

    } 

    } 

    public void Dispose() { 

    //Empty 

    } 

} 

und die Memory

public class CmsFilterStream : MemoryStream { 

    private Stream  _responseStream; 
    private StringBuilder _responseHtml; 

    public CmsFilterStream(Stream inputStream) { 

    _responseStream = inputStream; 
    _responseHtml = new StringBuilder(); 

    } 

    /// <summary> 
    /// Writes a block of bytes to the current stream using data read from a buffer. 
    /// </summary> 
    /// <param name="buffer">The buffer to write data from.</param> 
    /// <param name="offset">The zero-based byte offset in buffer at which to begin copying bytes to the current stream.</param> 
    /// <param name="count">The maximum number of bytes to write.</param> 
    public override void Write(Byte[] buffer, Int32 offset, Int32 count) { 

    if (buffer == null) { throw new ArgumentNullException("buffer", "ArgumentNull_Buffer"); } 
    if (offset < 0) { throw new ArgumentOutOfRangeException("offset", "ArgumentOutOfRange_NeedNonNegNum"); } 
    if (count < 0) { throw new ArgumentOutOfRangeException("count", "ArgumentOutOfRange_NeedNonNegNum"); } 
    if (buffer.Length - offset < count) { throw new ArgumentException("Argument_InvalidOffLen"); } 

    String bufferContent = UTF8Encoding.UTF8.GetString(buffer, offset, count); 

    _responseHtml.Append(bufferContent); 

    } 

    public override void Close() { 

    _responseHtml.Replace("THE_PLACEHOLDER", "SOME_HTML"); 

    _responseStream.Write(UTF8Encoding.UTF8.GetBytes(_responseHtml.ToString()), 0, UTF8Encoding.UTF8.GetByteCount(_responseHtml.ToString())); 

    _responseStream.Dispose(); 

    base.Close(); 

    } 

} 

und die folgenden in der Web.config

<system.webServer> 
    <modules> 
    <remove name="CmsFilterHttpModule" /> 
    <add name="CmsFilterHttpModule" type="{MY_NAMESPACE}.CmsFilterHttpModule" /> 
    </modules> 
</system.webServer> 

Dies funktioniert wie ich brauche.

Meine Frage ist wirklich die beste Stelle in der Pipeline, um dies zu tun, bevor ich anfange, rückwärts zu arbeiten.

Diese Methode ersetzt den Text der abgeschlossenen Ausgabe.

Ich bin auf der Suche nach dem schnellsten Weg, um diesen Text aus der Pipeline Perspektive zu ersetzen.

Für den Moment ignoriert die Geschwindigkeit von String.Replace/Stringbuilder und die verschiedenen anderen Methoden. Ich sehe diese Optimierung etwas weiter.

Ich habe noch nicht durch die gesamte Pipeline debugged, aber obwohl ich vermute, dass die Seite aus verschiedenen Teilen gebaut werden muss, d. H. Layouts, Ansichten teilweise etc. etc. ist es vielleicht schneller, den Text in diesen Teilen zu ersetzen.

Auch dazu wird es Probleme sein mit

String bufferContent = UTF8Encoding.UTF8.GetString(buffer); 

, wenn andere Sprachen Japanisch verwenden, Chinesisch usw.

Ich muss auch hinzufügen, dass ich versuche, das als eine separate zu tun hinzugefügt Stück Code, der den MVC-Code des Benutzers so wenig wie möglich berührt.

+2

Haben Sie sich den Aktionsfilter "OnActionExecuted" angesehen? – xandercoded

+0

Ich habe noch nicht tief in andere hineingeschaut. Darum geht es in meiner Frage. Andere Menschen Erfahrungen, Meinungen, verschiedene Möglichkeiten Menschen haben sich an diese etc. –

+0

Ich muss auch hinzufügen, dass ich versuche, dies als separate hinzugefügt am Stück Code, der den ursprünglichen MVC-Code so wenig wie möglich berührt. Damit wird wirklich ein Action-Filter ausgeschlossen. –

Antwort

1

Um die vollständige Reaktion ohne den Flaum des Habens zu behandeln Zustand zwischen den Anrufen zu behandeln Ihre Implementierung schreiben nicht die Write Methode außer Kraft setzen müssen, nur die Close Methode ist erforderlich, da müssen Sie zuerst alle Bytes erfassen, bevor die Umwandlung .Dies ist eine Implementierung, die funktioniert:

public class CmsFilterStream : MemoryStream { 

    private Stream  _responseStream; 

    public CmsFilterStream(Stream inputStream) { 
     _responseStream = inputStream; 
    } 

    public override void Close() { 
     var allHtml = UTF8Encoding.UTF8.GetString(this.ToArray()); // get ALL bytes!! 
     allHtml = allHtml.Replace("THE_PLACEHOLDER", "SOME_HTML"); 

     var buf =UTF8Encoding.UTF8.GetBytes(allHtml); 
     _responseStream.Write(buf,0, buf.Length); 

     _responseStream.Flush(); // I assume the caller will close the _responseStream 

     base.Close(); 
    } 
} 

Dies ist eine naive Implementierung. Sie können den Ersetzungscode und das Schreiben in den Stream optimieren, aber ich würde dies nur optimieren, wenn Ihre Leistungsmessungen anzeigen, dass sich diese Codefrequenz auf dem heißen Pfad befindet.

Verwandte Themen