2010-12-12 5 views
3

Ich versuche, einen ActionFilter zu erstellen, um etwas Text in meinem HTML zu ersetzen. Grundsätzlich, wenn der Server SSL verwendet, möchte ich Referenzen zu meinem CDN (http://cdn.example.com) durch Referenzen direkt auf meinen Server (https://www.example.com) ersetzen. So ist die Struktur so etwas wie diese (Ich gehe davon aus OnResultExecuted ist, wo ich anfangen soll):Wie ersetze ich URLs in gerenderten HTML mit einem ASP.NET MVC ActionFilter

public class CdnSslAttribute : ActionFilterAttribute 
{ 
    public override void OnResultExecuted(ResultExecutedContext filterContext) 
    { 
     if(filterContext.HttpContext.Request.IsSecureConnection) 
     { 
      // when the connection is secure, 
      // somehow replace all instances of http://cdn.example.com 
      // with https://www.example.com 
     } 
    } 
} 

Diese in meinem sicheren Controller verwendet werden würde:

[CdnSsl] 
public class SecureController : Controller 
{ 
} 

Der Grund, warum ich dies tun will Ist mein CDN unterstützt nicht SSL. Und es gibt Verweise in den Masterseiten auf CDN-Ressourcen. Beispiel:

<link href="http://cdn.example.com/Content/base.css" rel="stylesheet" type="text/css" /> 

Antwort

5

I endete mit einer Variation auf diesem Blog-Post auf:

http://arranmaclean.wordpress.com/2010/08/10/minify-html-with-net-mvc-actionfilter/

mit meinem eigenen Filter:

public class CdnSslAttribute : ActionFilterAttribute 
{ 
    public override void OnResultExecuted(ResultExecutedContext filterContext) 
    { 
     if (filterContext.HttpContext.Request.IsSecureConnection) 
     { 
      var response = filterContext.HttpContext.Response; 
      response.Filter = new CdnSslFilter(response.Filter); 
     } 
    } 
} 

Dann wird der Filter wie folgt aussieht (einige Code der Kürze halber weggelassen):

public class CdnSslFilter : Stream 
{ 
    private Stream _shrink; 
    private Func<string, string> _filter; 

    public CdnSslFilter(Stream shrink) 
    { 
     _shrink = shrink; 
     _filter = s => Regex.Replace(s,@"http://cdn\.","https://www.", RegexOptions.IgnoreCase); 
    } 

    //overridden functions omitted for clarity. See above blog post. 

    public override void Write(byte[] buffer, int offset, int count) 
    { 
     // capture the data and convert to string 
     byte[] data = new byte[count]; 
     Buffer.BlockCopy(buffer, offset, data, 0, count); 
     string s = Encoding.Default.GetString(buffer); 

     // filter the string 
     s = _filter(s); 

     // write the data to stream 
     byte[] outdata = Encoding.Default.GetBytes(s); 
     _shrink.Write(outdata, 0, outdata.GetLength(0)); 
    } 
} 
0

Ich weiß nicht, aber die Antwort von @Haacked an diesen question helfen könnte.

0

Die Ersetzung der generierten Ausgabe innerhalb eines Aktionsfilters wäre etwas kompliziert.

Ein einfacherer Ansatz (wenn Sie Ihre Masterseiten bearbeiten können) wäre, eine neue HTML-Hilfsmethode zu schreiben (ähnlich dem Html.Content() Helfer), die die richtige URL bedingt ausgeben würde. Wenn Sie möchten, dass diese Ersetzung nur für bestimmte Controller erfolgt, dann könnten Sie immer noch einen Aktionsfilter haben, aber Sie würden nur ein Flag in Request.Items setzen und Ihr Helfer könnte dieses Flag überprüfen.

0

Mein Vorschlag ist, dem Ansatz von @ marcind zu folgen, eine Möglichkeit besteht darin, eine benutzerdefinierte Erweiterungsmethode zu verwenden, um die richtige URL abhängig vom aktuellen URL-Schema zu generieren.

public static MvcHtmlString CdnActionLink(this HtmlHelper helper, string linkText, string actionName, string controllerName) 
{ 
    if(helper.ViewContext.HttpContext.Request.IsSecureConnection) 
    { 
     return helper.ActionLink(linkText, actionName, controllerName, "https", "www.yourhost.com"...); 
    } 
    return helper.ActionLink(linkText, actionName, controllerName); 
} 

Ein Nachteil dieses Ansatzes ist, dass Sie in Ihren Ansichten alle aktuellen ActionLink Anrufungen zu ersetzen brauchen werden (oder zumindest die, die Sie benötigen) mit einem Aufruf zu dieser Erweiterung Methode.

+0

Es hängt alles davon ab, ob der Entwickler mit dem Quellcode arbeitet nicht "besitzen". Ich entwickle ein Plugin für ein System, in dem ich den Code nicht ändern darf. Das bedeutet, dass ich die Antwort ändern muss, um bestimmte Teile der Benutzeroberfläche zu ändern. –

Verwandte Themen