2013-01-02 13 views
8

Mam niestandardową implementację bloku, który działa podobnie do Html.BeginForm(). Realizacja jest w zasadzie w sposób następujący:Brzytwa: niestandardowy BeginForm() - jak jednorazowy blok Razor nie działa w niektórych przypadkach

public class MyBlock : IDisposable { 
    private readonly HtmlHelper _html; 

    public MyBlock(HtmlHelper hml) { 
     this._html.ViewContext.Writer.WriteLine("BEGIN"); 
    } 

    public void Dispose() { 
     this._html.ViewContext.Writer.WriteLine("END"); 
    } 
} 

Wtedy moim zdaniem można zrobić:

@using (new MyBlock(Html)) { 
    @: some content 
} 

Aby uzyskać:

BEGIN 
some content 
END 

to wszystko działa dobrze. Jednak napotkam problemy, gdy używam mojego bloku wewnątrz "fragmentu maszynki do golenia", np. sol. przy przekazywaniu zawartości brzytwy do funkcji, która przyjmuje argument Func<object, HelperResult>. Na przykład, mam inna funkcja HtmlHelper zdefiniowane następująco:

public static IHtmlString Content(this HtmlHelper @this, Func<object, HelperResult> razor) { 
    return razor(null); 
} 

@* use in a view as: *@ 
@{ 
    var razorContent = Html.Content(@<div>Some razor content</div>); 
} 
@razorContent 

Kiedy wykonać następujące czynności, choć wewnętrzna treść świadczy bez zewnętrznej treści:

@{ 
    var content =Html.Content(
     @<text> 
      @using (new MyBlock(Html)) { 
       @: some content 2 
      } 
     <text> 
    ); 
} 
@content 

Myślę, że problemem jest to, że " Html "nadal odnosi się do HtmlHelper z zewnętrznego kontekstu, a zatem BEGIN i END są wysyłane do różnych pisarzy niż" niektóre treści 2 ", jednak nie jestem pewien, czy tak jest.

Czy ktoś wie (1), co dzieje się nie tak i (2) jak mogę to naprawić?

Odpowiedz

2

Częściowym rozwiązaniem twojego problemu jest wywołanie metody WriteTo HelperResult. Można zmienić sposób zawartość do czegoś takiego:

public static void Content(this HtmlHelper @this, Func<object, HelperResult> razor) 
{ 
    razor(null).WriteTo(@this.ViewContext.Writer); 
} 

a następnie używać go w ten sposób:

@{ Html.Content(
     @<text> 
      @using (new MyBlock(Html)) { 
       @: some content 2 
      } 
     </text> 
    ); 
} 

EDIT

Jeśli chcesz powrócić wartość jako IHtmlString lub jakikolwiek inny ciąg może to zrobić:

public static IHtmlString Content(this HtmlHelper @this, Func<object, HelperResult> razor) 
{ 
    using (MemoryStream ms = new MemoryStream()) 
    using (TextWriter tw = new StreamWriter(ms)) 
    { 
     Delegate @delegate = (Delegate)razor; 
     WebViewPage target = (WebViewPage)@delegate.Target; 
     TextWriter tmp = target.Html.ViewContext.Writer; 
     try 
     { 
      target.Html.ViewContext.Writer = tw; 
      razor(null).WriteTo(tw); 
      tw.Flush(); 
      ms.Seek(0, SeekOrigin.Begin); 
      TextReader tr = new StreamReader(ms); 

      return MvcHtmlString.Create(tr.ReadToEnd()); 
     } 
     finally 
     { 
      target.Html.ViewContext.Writer = tmp; 
     } 
    } 
} 
+0

Moim celem jest uchwycenie zmiennej treści w IHtmlString, która może zostać przekazana gdzie indziej. To nie wygląda na to, że rozwiązuje ten problem, prawda? – ChaseMedallion

0

To też mnie niepokoi przez jakiś czas. To brzytwa z powodu MyBlock i HtmlHelper przy użyciu różnych pisarzy. Rozsądnym rozwiązaniem jest przekazanie __razor_template_writer HtlmHelpera do MyBlock. (Mam nadzieję, że zostanie to naprawione w vnext)

public class MyBlock : IDisposable { 
    private readonly TextWriter _writer; 

    public MyBlock(TextWriter writer) { 
     _writer = writer; 
     _writer.WriteLine("BEGIN"); 
    } 

    public void Dispose() { 
     _writer.WriteLine("END"); 
    } 
} 

@{ 
    var content =Html.Content(
     @<text> 
      @using (new MyBlock(__razor_template_writer)) { 
       @: some content 2 
      } 
     <text> 
    ); 
} 
@content 
Powiązane problemy