MVC3 ActionLink with images (but without MvcFutures)?

I was wondering if anyone knows if any of the out-of-the-box ASP.NET MVC3 helpers can be used to create the “link button” ... I am currently using the following:

<a class="button" title="My Action" href="@Url.Action("MyAction", "MyController", new { id = item.Id })">
    <img alt="My Action" src="@Url.Content("~/Content/Images/MyLinkImage.png")" />
</a>

I try to avoid using MvcFutures, but even if I could use them, I don’t think there is an extension method that it will do there. (I believe that the solution in this case would be a cast of a user helper as shown here )

Finally, this post also has a good opportunity to handle this through CSS, but this is not what I ask ...

+5
source share
3 answers

To generate action links, I use the following:

using System;
using System.Linq.Expressions;
using System.Text;
using System.Web.Mvc;
using System.Web.Mvc.Html;
using System.Web.Routing;
using Fasterflect;

namespace StackOverflow.Mvc.Extensions
{
    public static class HtmlExtensions
    {
        #region ActionImage
        // href image link
        public static string ActionImage( this HtmlHelper helper, string href, string linkText, object htmlAttributes,
                                          string alternateText, string imageSrc, object imageAttributes )
        {
            var sb = new StringBuilder();
            const string format = "<a href=\"{0}\"{1}>{2}</a>";
            string image = helper.Image( imageSrc, alternateText, imageAttributes ).ToString();
            string content = string.IsNullOrWhiteSpace( linkText ) ? image : image + linkText;
            sb.AppendFormat( format, href, GetAttributeString( htmlAttributes ), content );
            return sb.ToString();
        }

        // controller/action image link
        public static string ActionImage( this HtmlHelper helper, string controller, string action, string linkText, object htmlAttributes,
                                          string alternateText, string imageSrc, object imageAttributes )
        {
            bool isDefaultAction = string.IsNullOrEmpty( action ) || action == "Index";
            string href = "/" + (controller ?? "Home") + (isDefaultAction ? string.Empty : "/" + action);
            return ActionImage( helper, href, linkText, htmlAttributes, alternateText, imageSrc, imageAttributes );
        }

        // T4MVC ActionResult image link
        public static string ActionImage( this HtmlHelper helper, ActionResult actionResult, string linkText, object htmlAttributes,
                                          string alternateText, string imageSrc, object imageAttributes )
        {
            var controller = (string) actionResult.GetPropertyValue( "Controller" );
            var action = (string) actionResult.GetPropertyValue( "Action" );
            return ActionImage( helper, controller, action, linkText, htmlAttributes, alternateText, imageSrc, imageAttributes );
        }       
        #endregion

        #region Helpers
        private static string GetAttributeString( object htmlAttributes )
        {
            if( htmlAttributes == null )
            {
                return string.Empty;
            }
            const string format = " {0}=\"{1}\"";
            var sb = new StringBuilder();
            htmlAttributes.GetType().Properties().ForEach( p => sb.AppendFormat( format, p.Name, p.Get( htmlAttributes ) ) );
            return sb.ToString();
        }       
        #endregion
    }
}

Note that the GetAttributeString method relies on the Fasterflect library to facilitate the reflection task, but you can replace this with regular reflection if you prefer not to take an additional dependency.

The image helper extension was used as part of MvcContrib, but it seems to have been removed, most likely because the functionality is now built into MVC. Despite this, I have included it below for completeness:

public static class ImageExtensions {
    public static MvcHtmlString Image(this HtmlHelper helper, string imageRelativeUrl, string alt, object htmlAttributes) {
        return Image(helper, imageRelativeUrl, alt, new RouteValueDictionary(htmlAttributes));
    }

    public static MvcHtmlString Image(this HtmlHelper helper, string imageRelativeUrl, string alt, IDictionary<string, object> htmlAttributes) {
        if (String.IsNullOrEmpty(imageRelativeUrl)) {
            throw new ArgumentException(MvcResources.Common_NullOrEmpty, "imageRelativeUrl");
        }

        string imageUrl = UrlHelper.GenerateContentUrl(imageRelativeUrl, helper.ViewContext.HttpContext);
        return MvcHtmlString.Create(Image(imageUrl, alt, htmlAttributes).ToString(TagRenderMode.SelfClosing));
    }

    public static TagBuilder Image(string imageUrl, string alt, IDictionary<string, object> htmlAttributes) {
        if (String.IsNullOrEmpty(imageUrl)) {
            throw new ArgumentException(MvcResources.Common_NullOrEmpty, "imageUrl");
        }

        TagBuilder imageTag = new TagBuilder("img");

        if (!String.IsNullOrEmpty(imageUrl)) {
            imageTag.MergeAttribute("src", imageUrl);
        }

        if (!String.IsNullOrEmpty(alt)) {
            imageTag.MergeAttribute("alt", alt);
        }

        imageTag.MergeAttributes(htmlAttributes, true);

        if (imageTag.Attributes.ContainsKey("alt") && !imageTag.Attributes.ContainsKey("title")) {
            imageTag.MergeAttribute("title", (imageTag.Attributes["alt"] ?? "").ToString());
        }
        return imageTag;
    }
}
+6
source

Your snippet looks good. You should wrap it in a general purpose html helper and call it day. I am sure there are other more interesting aspects to your application than choosing nit for UI helpers :)

+1

Check out this blog post below for an example with Stephen Walther's HTML extension methods

0
source

All Articles