1

How can I disable the output in the using-block (IDisposable HtmlHelper) of a razor page?

The following is a MCVE and not my exact scenario.

I have a litte helper for IDisposable:

public class DisposableHelper : IDisposable
{
    private readonly Action _endAction;

    public DisposableHelper(Action beginAction, Action endAction)
    {
        _endAction = endAction;
        beginAction();
    }

    public void Dispose()
    {
        _endAction();
    }
}

And this extension method:

public static IDisposable BeginSupress(this HtmlHelper htmlHelper)
{
    var originalWriter = htmlHelper.ViewContext.Writer;
    return new DisposableHelper(() => htmlHelper.ViewContext.Writer = TextWriter.Null, () => htmlHelper.ViewContext.Writer = originalWriter);
}

My Razor View Looks like this:

@using (Html.BeginSupress())
{
    <h1>This actually should have not been printed!</h1>
}

I expected that nothing is printed, but this string is printed:

<h1>This actually should have not been printed!</h1>
Community
  • 1
  • 1
Christian Gollhardt
  • 16,510
  • 17
  • 74
  • 111
  • why not use hidden field, what is the purpose of this ? – mybirthname Oct 30 '16 at 22:58
  • That is not possible for my usecase @mybirthname. I have a deep nested Html with a lot of Ajax stuff in it. I first tried to use `
    `, but all the logic is executed.
    – Christian Gollhardt Oct 30 '16 at 23:02
  • Some purpose could be a helper for Bootstrap Tabs. Based on the Model, I want to show a tabitem for example. I want the logic for it central, and not for every item `@if (Model.CanShowFoo)` @mybirthname – Christian Gollhardt Oct 30 '16 at 23:06
  • If this code did in fact work, you would have portions of code in a view that would _never render ever_. Would the method signature have a boolean in it? If so, what's the advantage over an `if`? – Will Ray Oct 31 '16 at 01:11
  • Yeah, that's because its a [MCVE](http://stackoverflow.com/help/mcve) @WillRay. I will give it a Model, and that model has a bollean in it. The Advantage is a cleaner view. If I already pass this information into the helper, I would double my code by checking it in the view everytime. Also there is more than one boolean check to decide if it will get rendered, and this helper is called ca. 10 times on one of multiple pages. – Christian Gollhardt Oct 31 '16 at 02:08
  • @ChristianGollhardt Either way you're checking it in the view. `@using (Html.BeginSuppress(boolean1, boolean2)` versus `@if (boolean1 && boolean2)`. Perhaps you want to use sections instead? – Will Ray Oct 31 '16 at 02:16
  • No it's more like `@using.BeginTab(Model.CustomerTabViewModel)`, where CustomerTabViewModel is a `TabViewModel`, which stores infos I need anyway in the helper. @Will Ray – Christian Gollhardt Oct 31 '16 at 02:22

1 Answers1

1

Inspired by this post under a different title, I got my answer.

It seems like we need to work with the underlying StringBuilder directly. Not sure why it is not possible to exchange it for a moment.

public static IDisposable BeginSupress(this HtmlHelper htmlHelper, bool suppress)
{
    StringBuilder stringBuilder = null;
    StringBuilder backupStringBuilder = null;
    return new DisposableHelper(
        () =>
        {
            if (suppress)
            {
                stringBuilder = ((StringWriter)htmlHelper.ViewContext.Writer).GetStringBuilder();
                backupStringBuilder = new StringBuilder(stringBuilder.Length).Append(stringBuilder);
            }
        },
        () =>
        {
            if (suppress)
            {
                stringBuilder.Length = 0;
                stringBuilder.Append(backupStringBuilder);
            }
        });
}
Community
  • 1
  • 1
Christian Gollhardt
  • 16,510
  • 17
  • 74
  • 111