Question

I'm writing my first asp.net mvc application and I have a question about custom Html helpers:

For making a form, you can use:

<% using (Html.BeginForm()) {%>
   *stuff here*
<% } %>

I would like to do something similar with a custom HTML helper. In other words, I want to change:

Html.BeginTr();
Html.Td(day.Description);
Html.EndTr();

into:

using Html.BeginTr(){
    Html.Td(day.Description);
}

Is this possible?

Was it helpful?

Solution

Here is a possible reusable implementation in c# :

class DisposableHelper : IDisposable
{
    private Action end;

    // When the object is created, write "begin" function
    public DisposableHelper(Action begin, Action end)
    {
        this.end = end;
        begin();
    }

    // When the object is disposed (end of using block), write "end" function
    public void Dispose()
    {
        end();
    }
}

public static class DisposableExtensions
{
    public static IDisposable DisposableTr(this HtmlHelper htmlHelper)
    {
        return new DisposableHelper(
            () => htmlHelper.BeginTr(),
            () => htmlHelper.EndTr()
        );
    }
}

In this case, BeginTr and EndTr directly write in the response stream. If you use extension methods that return a string, you'll have to output them using :

htmlHelper.ViewContext.HttpContext.Response.Write(s)

OTHER TIPS

I tried following the advice given here in MVC3, but I ran into trouble using:

htmlHelper.ViewContext.HttpContext.Response.Write(...);

When I used this code, my helper was writing into the Response stream BEFORE my Layout was rendered. This didn't work well.

Instead I used this:

htmlHelper.ViewContext.Writer.Write(...);

If you look at the source for the ASP.NET MVC (available on Codeplex), you'll see the implementation of the BeginForm eventually calls down to the following code:

static MvcForm FormHelper(this HtmlHelper htmlHelper, string formAction, FormMethod method, IDictionary<string, object> htmlAttributes)
{
    TagBuilder builder = new TagBuilder("form");
    builder.MergeAttributes<string, object>(htmlAttributes);
    builder.MergeAttribute("action", formAction);
    builder.MergeAttribute("method", HtmlHelper.GetFormMethodString(method), true);
    htmlHelper.ViewContext.HttpContext.Response.Write(builder.ToString(TagRenderMode.StartTag));

    return new MvcForm(htmlHelper.ViewContext.HttpContext.Response);
}

The MvcForm class implements IDisposable, in it's dispose method is writes the </form> to the response.

So, what you'd need to do is write the tags you want out in the helper method and return an object that implements IDisposable...in it's dispose method close the tag off.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top