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" rel="nofollow noreferrer noopener" title="Caption">
  <html> content in tags </html>
</a>

Any help with this.

Answers:

Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.

Method 1

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" rel="nofollow noreferrer noopener" title="The Worlds Best Q&amp;A site">
   StackOverflow - Because we really do care</a>

Method 2

There’s also another way, without disposable trick. It’s less work, great for small helpers. I answered similar question, and don’t want to copy everything, but here’s a short example:

@helper Paragraph(string cssClass, Func<object, object> markup) {
    <p class="@cssClass">@markup.DynamicInvoke(this.ViewContext)</p>
}

Usage of this helper looks like this:

@Paragraph("highlited", 
    @<text>
        Look, a @Html.ActionLink("link", "index")
    </text>
)

My full answer to the other similar question here.

Method 3

At its simplest level something like this would do it

public static MvcHtmlString SomeLink(this HtmlHelper htmlHelper, string href, string     title,  string content )
    {
        var urlHelper = ((Controller)htmlHelper.ViewContext.Controller).Url;
        //var url = urlHelper.Action(actionName, controllerName, routeValues);

        var someLink = new TagBuilder("a");
        someLink.MergeAttribute("href", href);
        someLink.InnerHtml = content;

        return new MvcHtmlString(someLink.ToString());
    }


All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

0 0 votes
Article Rating
Subscribe
Notify of
guest

0 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x
()
x