Image equivalent of ActionLink in ASP.NET MVC
Asked Answered
L

14

47

In ASP.NET MVC is there an equivalent of the Html.ActionLink helper for Img tags?

I have a controller action that outputs a dynamically generated JPEG and I wanted to use the same Lambda expressions to link to it as I do HREFs using ActionLink.

Alternatively, a helper that just gives the URL to a route (again specified using Lambdas) would also be acceptable.

EDIT: I had originally specified that I was using Preview 5, however I see that a Beta has been released. So all-in-all the version number was an unneeded piece of info as I may be upgrading soon :-)

Lindner answered 17/10, 2008 at 0:5 Comment(0)
F
20

Url.Action() will get you the bare URL for most overloads of Html.ActionLink, but I think that the URL-from-lambda functionality is only available through Html.ActionLink so far. Hopefully they'll add a similar overload to Url.Action at some point.

Firstling answered 17/10, 2008 at 1:2 Comment(2)
The parse-the-lambda functionality is in a nice convenient method in MvcToolkit, it's just internal. You could add your own extension method that calls it through reflection (or recompile MvcToolkit with it made public), assuming that an official one will replace it shortly.Firstling
If you make a nice extensionmethod out of this (something like: Html.ActionImage()), it shouldn't clutter your views :)Chavez
L
47

You can use the URL.Action method

<a href="<%= Url.Action("Create")  %>"><img src="../../Content/Images/add_48.png" /></a>
Letter answered 23/7, 2009 at 15:33 Comment(3)
This worked great! Just passed in the action and the controller and it worked like a charm! Thank youOutdare
@RichardEverett so how to use the Razor @? would you mind provide a simple demo code?Harneen
Change <%= Url.Action("Create") %> to @Url.Action("Create")Exegete
D
39

This question is older, and I just started recently with ASP.NET MVC when the RC was already out, but for those who find this question later like me this might be interesting:

At least in the RC you can use Url.Action() also with anonymous types, the result looks much nicer than the suggestions above, I guess:

<a href="<%= Url.RouteUrl("MyRoute", new { param1 = "bla", param2 = 5 }) %>">
   put in <span>whatever</span> you want, also <img src="a.gif" alt="images" />.
</a>

There are many other overloads for RouteUrl as well, of course.

Downpipe answered 19/2, 2009 at 16:20 Comment(0)
F
20

Url.Action() will get you the bare URL for most overloads of Html.ActionLink, but I think that the URL-from-lambda functionality is only available through Html.ActionLink so far. Hopefully they'll add a similar overload to Url.Action at some point.

Firstling answered 17/10, 2008 at 1:2 Comment(2)
The parse-the-lambda functionality is in a nice convenient method in MvcToolkit, it's just internal. You could add your own extension method that calls it through reflection (or recompile MvcToolkit with it made public), assuming that an official one will replace it shortly.Firstling
If you make a nice extensionmethod out of this (something like: Html.ActionImage()), it shouldn't clutter your views :)Chavez
S
8

I used a workaround to place a marker instead of text for ActionLink and then replace it with my image code. Something like this:

<%= Html.ActionLink("__IMAGE_PLACEHOLDER__", "Products").Replace("__IMAGE_PLACEHOLDER__", "<img src=\"" + myImgUrl + "\" />")%>

Not the most elegant solution but it works.

Supplant answered 27/12, 2008 at 10:26 Comment(1)
This is what I'm doing, except I have an extension method for building the img tag. It'd be great to wrap this up in an extension method itself, and I just might do that.Nudism
C
5

In MVC3, your link would look like this:

<a href="@Url.Action("Create")"><img src="../../Content/Images/add_48.png" /></a>
Cogitate answered 25/4, 2011 at 20:44 Comment(1)
And of course, don't forget the alt attribute for the img element, if possible.Zayin
T
4

In ASP.NET MVC Beta, you can use the Html.BuildUrlFromExpression method in the Futures assembly (which is not included in the default ASP.NET MVC install, but is available from CodePlex) to create a link around an image--or any HTML--using the lambda-style ActionLink syntax, like this:

<a href="<%=Html.BuildUrlFromExpression<MyController>(c => c.MyAction())%>">
     <%=Html.Image("~/Content/MyImage.gif")%>
</a>

To keep your image links borderless, you'll need to add a CSS rule like this:

img
{
     border: none;
}
Transistorize answered 21/11, 2008 at 16:44 Comment(0)
R
3

You can use this control.It behaves like ActionLink.

http://agilefutures.com/index.php/2009/06/actionimage-aspnet-mvc

Remorse answered 12/6, 2009 at 13:17 Comment(0)
F
2

It's pretty simple to achieve in MVC 2. I have created my own very simple extension method to support Lambda expressions for the Url.Action helper. It requires that you reference MVC 2 Futures.
Here's the code:

using System;
using System.Linq.Expressions;
using System.Web.Mvc;
using System.Web.Routing;

using ExpressionHelperInternal=Microsoft.Web.Mvc.Internal.ExpressionHelper;

namespace Bnv.Bssi.Web.Infrastructure.Helpers
{
    public static class UrlExtensions
    {
        public static string Action<TController>(this UrlHelper helper, Expression<Action<TController>> action) where TController : Controller
        {
            RouteValueDictionary routeValuesFromExpression = ExpressionHelperInternal.GetRouteValuesFromExpression<TController>(action);

            return helper.Action(routeValuesFromExpression["action"].ToString(), routeValuesFromExpression);
        }
    }
}

This is how you use it:

<img src="<%= Url.Action<YourController>(c => c.YourActionMethod(param1, param2)); %>" />
Fear answered 6/5, 2010 at 5:33 Comment(0)
L
2

I know that my post is too late but i wanna share :)

I added new extension method something like this :

public static class ImageExtensions
{
    public static MvcHtmlString ImageLink(this HtmlHelper htmlHelper, string imgSrc, string additionalText = null, string actionName = null, string controllerName = null, object routeValues = null, object linkHtmlAttributes = null, object imgHtmlAttributes = null)
    {
        var urlHelper = ((Controller)htmlHelper.ViewContext.Controller).Url;
        var url = "#";
        if (!string.IsNullOrEmpty(actionName))
            url = urlHelper.Action(actionName, controllerName, routeValues);

        var imglink = new TagBuilder("a");
        imglink.MergeAttribute("href", url);
        imglink.InnerHtml = htmlHelper.Image(imgSrc, imgHtmlAttributes) + " " + additionalText;
        linkHtmlAttributes = new RouteValueDictionary(linkHtmlAttributes);
        imglink.MergeAttributes((IDictionary<string, object>)linkHtmlAttributes, true);

        return MvcHtmlString.Create(imglink.ToString());
    }

    public static MvcHtmlString Image(this HtmlHelper htmlHelper, string imgSrc, object imgHtmlAttributes = null)
    {
        var imgTag = new TagBuilder("img");
        imgTag.MergeAttribute("src", imgSrc);
        if (imgHtmlAttributes != null)
        {
            imgHtmlAttributes = new RouteValueDictionary(imgHtmlAttributes);
            imgTag.MergeAttributes((IDictionary<string, object>)imgHtmlAttributes, true);
        }
        return MvcHtmlString.Create(imgTag.ToString());
    }
}

Hope this helped.

Lidialidice answered 16/11, 2011 at 2:11 Comment(0)
B
1

Is Url.Content() what you're looking for?

Give it something like Url.Content("~/path/to/something.jpg") it will turn it into the appropriate path based on the application root.

-Josh

Blastoff answered 17/6, 2009 at 16:44 Comment(0)
O
1

I took the above answers and made a bit of a wrapper extension:

    public static MvcHtmlString ActionImageLink(this HtmlHelper helper, string src, string altText, UrlHelper url, string actionName, string controllerName)
        {
            return ActionImageLink(helper, src, altText, url, actionName, controllerName, null, null);
        }

        public static MvcHtmlString ActionImageLink(this HtmlHelper helper, string src, string altText, UrlHelper url, string actionName, string controllerName, Dictionary<string, string> linkAttributes, Dictionary<string, string> imageAttributes)
        {
            return ActionImageLink(helper, src, altText, url, actionName, controllerName, null, linkAttributes, imageAttributes);
        }

        public static MvcHtmlString ActionImageLink(this HtmlHelper helper, string src, string altText, UrlHelper url, string actionName, string controllerName, dynamic routeValues, Dictionary<string, string> linkAttributes, Dictionary<string, string> imageAttributes)
        {
            var linkBuilder = new TagBuilder("a");
            linkBuilder.MergeAttribute("href", routeValues == null ? url.Action(actionName, controllerName) : url.Action(actionName, controllerName, routeValues));

            var imageBuilder = new TagBuilder("img");
            imageBuilder.MergeAttribute("src", url.Content(src));
            imageBuilder.MergeAttribute("alt", altText);

            if (linkAttributes != null)
            {
                foreach (KeyValuePair<string, string> attribute in linkAttributes)
                {
                    if (!string.IsNullOrWhiteSpace(attribute.Key) && !string.IsNullOrWhiteSpace(attribute.Value))
                    {
                        linkBuilder.MergeAttribute(attribute.Key, attribute.Value);
                    }
                }
            }

            if (imageAttributes != null)
            {
                foreach (KeyValuePair<string, string> attribute in imageAttributes)
                {
                    if (!string.IsNullOrWhiteSpace(attribute.Key) && !string.IsNullOrWhiteSpace(attribute.Value))
                    {
                        imageBuilder.MergeAttribute(attribute.Key, attribute.Value);
                    }
                }
            }

            linkBuilder.InnerHtml = MvcHtmlString.Create(imageBuilder.ToString(TagRenderMode.SelfClosing)).ToString();
            return MvcHtmlString.Create(linkBuilder.ToString());
        }

has made it easier for me anyway, hope it helps someone else.

Omnibus answered 9/7, 2012 at 12:8 Comment(3)
I like this extension, however, the this HtmlHelper helper is extraneous. I changed it to this UrlHelper url and call it using Url.ActionImageLink(...)Compress
Or you can do something like var _url = new UrlHelper(htmlHelper.ViewContext.RequestContext).Action(_actionName, _mergedRouteValues); to get an UrlHelper. I shamelessly stole this from the link @Remorse provided.Compress
@JimGilmartin I see, good idea. The only reason I put on the htmlhelper was so I could use it in the same way as any other razor helper, saves me trying to remember where it is stored / accessed from.Omnibus
T
0

I tried to put the output of the Html.Image into my Html.ImageLink helper.

@(new HtmlString(Html.ActionLink(Html.Image("image.gif").ToString(), "myAction", "MyController").ToString().Replace("&lt;", "<").Replace("&gt;", ">")))

The problem for me is, that the ActionLink name is encoded so I have &lt instead of <.

I just removed this encoding and the result works for me. (Is there a better way of doing this instead using replace?)

Tansy answered 8/1, 2011 at 13:13 Comment(0)
K
0

Adding to the other posts: in my case (asp.net mvc 3) I wanted an image link to act as a language selector so I ended up with:

  public static MvcHtmlString ImageLink(this HtmlHelper htmlHelper, string imgSrc, string cultureName, object htmlAttributes, object imgHtmlAttributes, string languageRouteName = "lang", bool strictSelected = false)
        {
           UrlHelper urlHelper = ((Controller)htmlHelper.ViewContext.Controller).Url;
           TagBuilder imgTag = new TagBuilder("img");
           imgTag.MergeAttribute("src", imgSrc);
           imgTag.MergeAttributes((IDictionary<string, string>)imgHtmlAttributes, true);

           var language = htmlHelper.LanguageUrl(cultureName, languageRouteName, strictSelected);                      
           string url = language.Url;

           TagBuilder imglink = new TagBuilder("a");
           imglink.MergeAttribute("href", url);
           imglink.InnerHtml = imgTag.ToString();
           imglink.MergeAttributes((IDictionary<string, string>)htmlAttributes, true);

           //if the current page already contains the language parameter make sure the corresponding html element is marked
           string currentLanguage = htmlHelper.ViewContext.RouteData.GetRequiredString("lang");
           if (cultureName.Equals(currentLanguage, StringComparison.InvariantCultureIgnoreCase))
           {
              imglink.AddCssClass("selectedLanguage");
           }
           return new MvcHtmlString(imglink.ToString());
        }

The internalization support was done via a language route - original source here.

Karli answered 17/7, 2012 at 11:6 Comment(0)
A
0

Nice solutions here, but what if you want to have more then just an image in the actionlink? This is how I do it:

     @using (Html.BeginForm("Action", "Controler", ajaxOptions))
     { 
        <button type="submit">
           <img src="image.png" />            
        </button>
     }

The drawback is that I still have to do a bit of styling on the button-element, but you can put all the html you want in there.

And it works with the Ajax helper as well: https://mcmap.net/q/272378/-asp-net-mvc-ajax-actionlink-with-image

Arena answered 10/10, 2013 at 17:40 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.