Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
445 views
in Technique[技术] by (71.8m points)

asp.net mvc 3 - Capture wrapped content in BeginForm style disposable html helper

I am trying to write a BeginForm style html helper that uses IDisposable to wrap other code. I want the helper to only render the wrapped code if a certain condition is met (e.g. user is in a certain role).

I thought that I could simply switch the context.Writer in the Begin method and switch it back in the Dispose method. The code below compiles and runs but the wrapped content gets rendered in all cases. If I step through it, the wrapped content is not written to the new StringWriter and therefore not within my control.

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

Is what I am trying to do possible with html helpers?

I know that declarative html helpers in razor would probably work but would prefer standard html helper approach if possible, given the app_code limitation of razor helpers in MVC3.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Actually you can conditionally hide content with a BeginForm-like structure. It only involves messing with the internal StringBuilder a bit:

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

Then you just need to make an HtmlHelper that makes an instance of the above object

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

Usage is as follows:

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

Advantages:

  • Write custom logic to show/hide your content and pass it to the Restricted constructor.
  • public properties in your Restricted object are accessible in the block of code in your view, so you can reuse calculated values there.

Tested with ASP.Net MVC 4


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...