asp.netasp.net-mvc-3razorhtmlextensions

MVC 3 htmlhelper extension method to wrap around content


I searched but could not find any quick solutions for an MVC 3 htmlhelper to create a wrapper method. What I'm looking for is something like:

@html.createLink("caption", "url")
{
    <html> content in tags </html>
}

the result should have

<a href="url" title="Caption">
  <html> content in tags </html>
</a>

Any help with this.


Solution

  • The way that this is done with BeginForm is that the return type MvcForm impliments IDisposable so that when used within a using statement, the Dispose method of MvcForm writes out the closing </form> tag.

    You can write an extension method that does exactly the same thing.

    Here's one I just wrote to demonstrate.

    First off, the extension method:

    public static class ExtensionTest
    {
        public static MvcAnchor BeginLink(this HtmlHelper htmlHelper)
        {
            var tagBuilder = new TagBuilder("a");
            htmlHelper.ViewContext.Writer
                            .Write(tagBuilder.ToString(
                                                 TagRenderMode.StartTag));
            return new MvcAnchor(htmlHelper.ViewContext);
        }
    }
    

    And here's our new type, MvcAnchor:

    public class MvcAnchor : IDisposable
    {
        private readonly TextWriter _writer;
        public MvcAnchor(ViewContext viewContext)
        {
            _writer = viewContext.Writer;
        }
    
        public void Dispose()
        {
            this._writer.Write("</a>");
        }
    }
    

    In your views you can now do:

    @{
        using (Html.BeginLink())
        { 
            @Html.Raw("Hello World")
        }
    }
    

    Which yields the result:

    <a>Hello World</a>
    

    Expanding this slightly to deal with your exact requirement:

    public static MvcAnchor BeginLink(this HtmlHelper htmlHelper, 
                                       string href, 
                                       string title)
    {
        var tagBuilder = new TagBuilder("a");
        tagBuilder.Attributes.Add("href",href);
        tagBuilder.Attributes.Add("title", title);
        htmlHelper.ViewContext.Writer.Write(tagBuilder
                                        .ToString(TagRenderMode.StartTag));
        return new MvcAnchor(htmlHelper.ViewContext);
    }
    

    and our view:

    @{
      using (Html.BeginLink("http://stackoverflow.com", "The Worlds Best Q&A site"))
      { 
          @Html.Raw("StackOverflow - Because we really do care")
      }
    }
    

    which yields the result:

    <a href="http://stackoverflow.com" title="The Worlds Best Q&amp;A site">
       StackOverflow - Because we really do care</a>