2009-03-24 18 views
37

ich meine erste asp.net MVC-Anwendung Ich schreibe, und ich habe eine Frage zu benutzerdefinierte HTML-Helfer:benutzerdefinierte HTML-Helfer: Erstellen Helfer mit „using“ Anweisung Unterstützung

Für ein Formular erstellen, können Sie verwenden:

<% using (Html.BeginForm()) {%> 
    *stuff here* 
<% } %> 

Ich möchte etwas ähnliches mit einem benutzerdefinierten HTML-Helfer tun. Mit anderen Worten, ich möchte ändern:

Html.BeginTr(); 
Html.Td(day.Description); 
Html.EndTr(); 

in:

using Html.BeginTr(){ 
    Html.Td(day.Description); 
} 

Ist das möglich?

Antwort

47

Hier eine mögliche wiederverwendbare Implementierung in C# ist:

class DisposableHelper : IDisposable 
{ 
    private Action end; 

    // When the object is created, write "begin" function 
    public DisposableHelper(Action begin, Action end) 
    { 
     this.end = end; 
     begin(); 
    } 

    // When the object is disposed (end of using block), write "end" function 
    public void Dispose() 
    { 
     end(); 
    } 
} 

public static class DisposableExtensions 
{ 
    public static IDisposable DisposableTr(this HtmlHelper htmlHelper) 
    { 
     return new DisposableHelper(
      () => htmlHelper.BeginTr(), 
      () => htmlHelper.EndTr() 
     ); 
    } 
} 

In diesem Fall BeginTr und EndTr direkt in dem Antwortstream schreiben. Wenn Sie Erweiterungsmethoden verwenden, die einen String zurückgeben, werden Sie zur Ausgabe von ihnen haben mit:

htmlHelper.ViewContext.HttpContext.Response.Write(s) 
+0

pweh .. und ich dachte, das für Ihre Mühe leicht .. Dank sein würde. –

+0

Es war nur eine schnelle und schmutzige Implementierung. Der "Begin" -Delegat kann direkt in Ihrer Erweiterungsmethode aufgerufen werden, und die DisposableHelper-Klasse ist für andere Erweiterungen wiederverwendbar. – ybo

+0

Ok, danke, ich werde später genauer darauf eingehen. –

18

Wenn Sie an der Quelle für die ASP.NET MVC (auf Codeplex) anschauen, werden Sie die Implementierung der Begin sehen schließlich auf den folgenden Code ruft nach unten:

static MvcForm FormHelper(this HtmlHelper htmlHelper, string formAction, FormMethod method, IDictionary<string, object> htmlAttributes) 
{ 
    TagBuilder builder = new TagBuilder("form"); 
    builder.MergeAttributes<string, object>(htmlAttributes); 
    builder.MergeAttribute("action", formAction); 
    builder.MergeAttribute("method", HtmlHelper.GetFormMethodString(method), true); 
    htmlHelper.ViewContext.HttpContext.Response.Write(builder.ToString(TagRenderMode.StartTag)); 

    return new MvcForm(htmlHelper.ViewContext.HttpContext.Response); 
} 

Die MvcForm Klasse implementiert IDisposable schreibt in seiner Dispose-Methode </form > in die Antwort.

Also, was Sie tun müssten, ist schreiben Sie die Tags, die Sie wollen in der Hilfsmethode und geben Sie ein Objekt zurück, das IDisposable implementiert ... in seiner Dispose-Methode schließen Sie das Tag aus.

31

Ich habe versucht, im Anschluss an die Ratschläge hier in MVC3, aber ich lief in Schwierigkeiten mit:

htmlHelper.ViewContext.HttpContext.Response.Write(...); 

Als ich diesen Code verwendete, schrieb mein Helfer in den Antwortstream, bevor mein Layout gerendert wurde. Das hat nicht gut funktioniert.

Stattdessen benutzte ich diese:

htmlHelper.ViewContext.Writer.Write(...); 
+2

Vielen Dank. Sparte mir viel Zeit. –

+2

Arbeitete für mich in MVC 3 mit dem ursprünglichen Code war das Schreiben der HTML-Helfer Inhalt direkt unter dem HTML-Körper. Das hat es behoben. –

Verwandte Themen