2012-04-04 15 views
8

Tôi đang cố viết một trình trợ giúp html kiểu BeginForm sử dụng IDisposable để bọc mã khác. Tôi muốn người trợ giúp chỉ hiển thị mã được bao bọc nếu một điều kiện nhất định được đáp ứng (ví dụ: người dùng có vai trò nhất định).Chụp nội dung được bao bọc trong bộ trợ giúp html dùng một lần theo phong cách BeginForm

Tôi nghĩ rằng tôi có thể chỉ cần chuyển ngữ cảnh.Writer trong phương thức Begin và chuyển nó trở lại trong phương thức Dispose. Mã bên dưới biên dịch và chạy nhưng nội dung được bao bọc được hiển thị trong mọi trường hợp. Nếu tôi bước qua nó, nội dung được bao bọc không được ghi vào StringWriter mới và do đó không nằm trong tầm kiểm soát của tôi.

public static IDisposable BeginSecure(this HtmlHelper html, ...) 
    { 
     return new SecureSection(html.ViewContext, ...); 
    } 

    private class SecureSection : IDisposable 
    { 
     private readonly ViewContext _context; 
     private readonly TextWriter _writer; 

     public SecureSection(ViewContext context, ...) 
     { 
      _context = context; 
      _writer = context.Writer; 
      context.Writer = new StringWriter(); 
     } 

     public void Dispose() 
     { 
      if (condition here) 
      { 
       _writer.Write(_context.Writer); 
      } 

      _context.Writer = _writer; 
     } 
    } 

Tôi đang cố gắng làm gì với người trợ giúp html?

Tôi biết rằng trình trợ giúp html khai báo trong dao cạo có thể hoạt động nhưng sẽ thích cách tiếp cận trợ giúp html chuẩn nếu có thể, với giới hạn app_code của trình trợ giúp dao cạo trong MVC3.

Trả lời

6

Bạn không thể điều kiện hiển thị nội dung cơ thể của phương thức trợ giúp trả về IDisposable. Nó sẽ luôn hiển thị. Bạn có thể sử dụng kiểu trợ giúp này khi bạn muốn bọc phần thân của khối using với một số đánh dấu tùy chỉnh chẳng hạn như trình trợ giúp BeginForm làm với phần tử <form>.

Bạn có thể sử dụng một templated Razor delegate thay vì:

public static class HtmlExtensions 
{ 
    public static HelperResult Secure(this HtmlHelper html, Func<object, HelperResult> template) 
    { 
     return new HelperResult(writer => 
     { 
      if (condition here) 
      { 
       template(null).WriteTo(writer); 
      } 
     }); 
    } 
} 

và sau đó:

@Html.Secure(
    @<div> 
     You will see this text only if some condition is met 
    </div> 
) 
9

Trên thực tế bạn có thể có điều kiện ẩn nội dung với một cấu trúc BeginForm-như thế nào. Nó chỉ liên quan đến việc can thiệp vào StringBuilder nội bộ một chút:

public class Restricted: IDisposable 
{ 
    public bool Allow { get; set; } 

    private StringBuilder _stringBuilderBackup; 
    private StringBuilder _stringBuilder; 
    private readonly HtmlHelper _htmlHelper; 

    /// <summary> 
    /// Initializes a new instance of the <see cref="Restricted"/> class. 
    /// </summary> 
    public Restricted(HtmlHelper htmlHelper, bool allow) 
    { 
     Allow = allow; 
     _htmlHelper = htmlHelper; 
     if(!allow) BackupCurrentContent(); 
    } 

    private void BackupCurrentContent() 
    { 
     // make backup of current buffered content 
     _stringBuilder = ((StringWriter)_htmlHelper.ViewContext.Writer).GetStringBuilder(); 
     _stringBuilderBackup = new StringBuilder().Append(_stringBuilder); 
    } 

    private void DenyContent() 
    { 
     // restore buffered content backup (destroying any buffered content since Restricted object initialization) 
     _stringBuilder.Length = 0; 
     _stringBuilder.Append(_stringBuilderBackup); 
    } 

    /// <summary> 
    /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. 
    /// </summary> 
    public void Dispose() 
    { 
     if(!Allow) 
      DenyContent(); 
    } 
} 

Sau đó, bạn chỉ cần thực hiện một HtmlHelper mà làm cho một thể hiện của đối tượng trên

public static class RestrictedHelper 
{ 
    public static Restricted RestrictedContent(this HtmlHelper htmlHelper, bool allow) 
    { 
     return new Restricted(htmlHelper, allow); 
    } 
} 

Cách sử dụng như sau:

@using (var restricted = Html.Restricted(true)) 
{ 
    <p>This will show up</p> 
} 
@using (var restricted = Html.Restricted(false)) 
{ 
    <p>This won't</p> 
} 

Ưu điểm:

  • Viết logic tùy chỉnh để hiển thị/ẩn nội dung của bạn và chuyển nó tới nhà xây dựng bị hạn chế.
  • thuộc tính công khai trong đối tượng Hạn chế của bạn có thể truy cập được trong khối mã trong chế độ xem của bạn, do đó bạn có thể sử dụng lại các giá trị được tính toán ở đó.

Tested với ASP.Net MVC 4

+0

Bạn nên bình luận-out "allowcontent" mã, chỉ cần làm gì ở đó. Nếu không, tôi sẽ nhận được nội dung lồng nhau. Ngoài ra, việc sao lưu chỉ cần thiết khi Được phép là 'false' – Alex

+0

Cảm ơn @jitbit, tôi đã cập nhật bài đăng của mình. Chỉ cần một suy nghĩ bằng cách này: lớp bảo đảm này thêm rất ít giá trị so với các câu lệnh if built-in đơn giản ... Tôi sẽ chỉ thực hiện tuyến này nếu bạn cần thao tác HTML và đã thử tất cả các tùy chọn khác. Tôi đã làm việc với Razor rất nhiều kể từ khi tôi thực hiện bài đăng này, và tìm cú pháp "sử dụng" trong Razor xem lạm dụng ngôn ngữ chứ không phải là đường cú pháp. – Moeri

Các vấn đề liên quan