简体   繁体   中英

ASP MVC ActionLinks with HTML content

There are nice extension methods to generate ActionLinks/RouteLinks in ASP MVC. However it only lets you write plain text inside the generated tag. What if you want to generate anchor with image inside?

I wanted to create links using the icons from bootstrap:

// expected result
<a href="/Customer?page=1"><i class="glyphicon glyphicon-arrow-left"></i> Previous page</a>

When you want to generate simple link, you can use @Url.Action() like this:

<a href="@Url.Action("Index","Customer", new{ page = 1 })"><i class="glyphicon glyphicon-arrow-left"></i> Previous page</a>

But when you want to generate ajax links, it's not so simple. Because @Ajax.ActionLink generates anchor with javascript or 'data-*' atributes that are handled by jquery-unobtrusive-ajax-min.js library.

So I wrote for my purpose extension methods to generate ActionLinks/RouteLinks in way you use @Html.BeginForm/@Ajax.BeginForm (surrounded by using).

Usage:

// instead
@Html.ActionLink("Previous page", "Index", "Customer", new { page = 1 })

// you can write
@using(Html.BeginActionLink("Index", "Customer", new { page = 1 }) {
  <text><i class="glyphicon glyphicon-arrow-left"></i> Previous page</text>
}

// same with ajax links
@using(Ajax.BeginActionLink("Index", new { page = 1 }, new AjaxOptions { ... }) {
  <text><i class="glyphicon glyphicon-arrow-left"></i> Previous page</text>
}

Methods BeginActionLink return instance of class MvcLink which implements IDisposable. In constructor it writes start tag and when disposed it writes end tag. Between curly brackets there is place for your code

namespace System.Web.Mvc
{
  using System.Text.RegularExpressions;

  public class MvcLink : IDisposable
  {
    internal static readonly string InnerText = "___F7ED35E0097945398D5A969F8DE2C63C___";
    private static readonly Regex RegexPattern = new Regex(@"^\s*(?<startTag>.*)\s*" + InnerText + @"\s*(?<endTag>.*)\s*$", RegexOptions.Compiled | RegexOptions.Singleline);

    private readonly ViewContext _viewContext;
    private readonly string _endTag;

    internal MvcLink(ViewContext viewContext, IHtmlString actionLink) {
      _viewContext = viewContext;
      var match = RegexPattern.Match(actionLink.ToHtmlString());
      if (match.Success) {
        var startTag = match.Groups["startTag"].Value;
        _endTag = match.Groups["endTag"].Value;
        _viewContext.Writer.Write(startTag);
      }
    }

    public void Dispose() {
      _viewContext.Writer.Write(_endTag);
    }
  }
}

Then it's up to you to write extension methods for HtmlHelper and AjaxHelper. There are too many overloads for method ActionLink/RouteLink so I prepared just those that I realy use in my application.

But it's easy to write others. You can see that I create instance of MvcLink, it takes ViewContext as first parameter and the result of builtin ActionLink with predefined InnerText that will be replaced by your content.

namespace System.Web.Mvc
{
  using System.Web.Mvc.Ajax;
  using System.Web.Mvc.Html;

  public static class MvcHelperExtensions
  {
    public static MvcLink BeginActionLink(this AjaxHelper ajaxHelper, string actionName, object routeValues, AjaxOptions ajaxOptions, object htmlAttributes) {
      return new MvcLink(ajaxHelper.ViewContext, ajaxHelper.ActionLink(MvcLink.InnerText, actionName, routeValues, ajaxOptions, htmlAttributes));
    }

    public static MvcLink BeginActionLink(this HtmlHelper htmlHelper, string actionName, object routeValues, object htmlAttributes) {
      return new MvcLink(htmlHelper.ViewContext, htmlHelper.ActionLink(MvcLink.InnerText, actionName, routeValues, htmlAttributes));
    }
  }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM