2013-01-02 24 views
8

Tôi có một cài đặt tùy chỉnh của một khối hoạt động giống như Html.BeginForm(). Việc thực hiện về cơ bản là như sau:Dao cạo: tùy chỉnh BeginForm() - như khối dùng một lần Razor không hoạt động trong một số trường hợp

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

Sau đó, theo quan điểm của tôi, tôi có thể làm:

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

Để nhận được:

BEGIN 
some content 
END 

này tất cả hoạt động tốt. Tuy nhiên, tôi gặp rắc rối khi sử dụng khối của tôi bên trong một "đoạn dao cạo", e. g. khi truyền một số nội dung dao cạo đến hàm có một đối số là Func<object, HelperResult>. Ví dụ, tôi có một chức năng HtmlHelper quy định như sau:

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 

Khi tôi làm những điều sau đây, tuy nhiên, nội dung bên trong làm cho không nội dung bên ngoài:

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

Tôi nghĩ vấn đề là " Html "vẫn đề cập đến HtmlHelper của bối cảnh bên ngoài, và do đó BEGIN và END được gửi đến một nhà văn khác với" một số nội dung 2 ", tuy nhiên, tôi không chắc chắn rằng đây là trường hợp.

Có ai biết (1) điều gì không ổn và (2) cách tôi có thể khắc phục sự cố?

Trả lời

2

Giải pháp một phần vấn đề của bạn là gọi phương thức WriteTo của HelperResult. Bạn có thể thay đổi phương thức nội dung lên một cái gì đó như thế này:

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

và sau đó sử dụng nó như vậy:

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

EDIT

Nếu bạn muốn trả lại giá trị như IHtmlString hoặc bất kỳ chuỗi khác mà bạn có thể làm điều này:

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

Mục tiêu của tôi là nắm bắt biến nội dung trong IHtmlString mà sau đó có thể được truyền đi ở một nơi khác. Nó không giống như thế này giải quyết vấn đề đó, phải không? – ChaseMedallion

0

Điều này đã gây phiền hà cho tôi một thời gian. Đó là một lỗi dao cạo do MyBlock và HtmlHelper sử dụng các Nhà văn khác nhau. Cách giải quyết hợp lý là chuyển __razor_template_writer của HtlmHelper vào MyBlock. (Hy vọng rằng điều này sẽ được khắc phục trong 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 
Các vấn đề liên quan