ASP.NET MVC Ajax.ActionLink with Image
Asked Answered
G

21

73

is there anyway to have an image act as an ajax actionlink? I can only get it to work using text. Thanks for your help!

Goulder answered 4/12, 2008 at 18:40 Comment(1)
The answers to #211211 may help.Nursemaid
B
67

From Stephen Walthe, from his Contact manger project

 public static class ImageActionLinkHelper
{

    public static string ImageActionLink(this AjaxHelper helper, string imageUrl, string altText, string actionName, object routeValues, AjaxOptions ajaxOptions)
    {
        var builder = new TagBuilder("img");
        builder.MergeAttribute("src", imageUrl);
        builder.MergeAttribute("alt", altText);
        var link = helper.ActionLink("[replaceme]", actionName, routeValues, ajaxOptions);
        return link.Replace("[replaceme]", builder.ToString(TagRenderMode.SelfClosing));
    }

}

You can now type in your aspx file :

<%= Ajax.ImageActionLink("../../Content/Delete.png", "Delete", "Delete", new { id = item.Id }, new AjaxOptions { Confirm = "Delete contact?", HttpMethod = "Delete", UpdateTargetId = "divContactList" })%> 
Bubonocele answered 1/11, 2009 at 19:25 Comment(6)
Just an FYI, I added an additional parameter to the ImageActionLink method to accept the controller name as the MVC ActionLink method has and it works flawlessly! ThanksWillman
In addition to this, in the above code sample link will not have the method Replace as an available option on it. You'll need to first call ToString() or ToHtmlString() on it before being able to call Replace().Egoism
I feel a little silly, but, I can't work out how to implement this. I don't suppose you can explain a little where the class needs to go?Gottlieb
@Gottlieb this is a helper class (notice the keyword this). Just put it anywhere and reference it via @using, and you should be able to consume the new method.Extol
The custom helper ImageActionLink will render text and not markup until the return type is changed from string to IHtmlStringTobey
I used MvcHtmlString instead of string as a return type, it worked as a charm! Thanks All : )Calculus
D
35

Here's the easiest solution I've found:

<%= Ajax.ActionLink("[replacethis]", ...).Replace("[replacethis]", "<img src=\"/images/test.gif\" ... />" %>

The Replace() call is used to push the img tag into the action link. You just need to use the "[replaceme]" text (or any other safe text) as a temporary placeholder to create the link.

Deca answered 23/4, 2009 at 3:55 Comment(5)
I like this pragmatic solution!Algie
I tried to use the above code (with .ToHtmlString() before ".Replace") and it does not do the trick. It just throws the whole string in there. Has this changed in mvc3 or am I missing something?Plication
May I also suggest returning as return new MvcHtmlString(link); for MVC3Petrochemistry
@Plication You can wrap it all with Html.Raw(...) and Razor will not encode itSubjective
@FernandoNeira Thanks for your suggestions . I have given whole solutions from your suggestions here https://mcmap.net/q/272378/-asp-net-mvc-ajax-actionlink-with-imagePokeberry
L
33

This is a Razor/MVC 3 (and later) update to Black Horus' answer:

using System.Web;
using System.Web.Mvc;
using System.Web.Mvc.Ajax;

public static class ImageActionLinkHelper
{
    public static IHtmlString ImageActionLink(this AjaxHelper helper, string imageUrl, string altText, string actionName, object routeValues, AjaxOptions ajaxOptions, object htmlAttributes = null)
    {
        var builder = new TagBuilder("img");
        builder.MergeAttribute("src", imageUrl);
        builder.MergeAttribute("alt", altText);
        builder.MergeAttributes(new RouteValueDictionary(htmlAttributes));
        var link = helper.ActionLink("[replaceme]", actionName, routeValues, ajaxOptions).ToHtmlString();
        return MvcHtmlString.Create(link.Replace("[replaceme]", builder.ToString(TagRenderMode.SelfClosing)));
    }

}

You can now type in your .cshtml file :

@Ajax.ImageActionLink("../../Content/Delete.png", "Delete", "Delete", new { id = item.Id }, new AjaxOptions { Confirm = "Delete contact?", HttpMethod = "Delete", UpdateTargetId = "divContactList" })

Oct 31. 2013: Updated with an extra parameter to allow for setting additional HTML attributes to the image element. Usage:

@Ajax.ImageActionLink("../../Content/Delete.png", "Delete", "Delete", new { id = item.Id }, new AjaxOptions { Confirm = "Delete contact?", HttpMethod = "Delete", UpdateTargetId = "divContactList" }, new{ style="border: none;" })
Leake answered 1/6, 2011 at 12:34 Comment(6)
thanks for the update. It was quite helpful; however you appear to have 2 extra characters at the end of the .cshtml line.Torbart
Thanks, @snumpy! This was a typical copy-paste error... :) It's fixedLeake
I feel a little silly, but, I can't work out how to implement this. I don't suppose you can explain a little where the class needs to go?Gottlieb
You can put it anywhere. (At root level of your MVC application will do fine...) (You might need to put in a @using directive at the top of your razor files, pointing at the namespace of the class, if any)Leake
I would suggest you to add an attribute parameter to set attribute and style in the rendered image. (for example to clear the default image border). An usefull example can be found at this link kitsula.com/Article/Html.ImageActionLink-extensionImine
@GhiniAntonio: Thanks. Just updated the answer to include a parameter for html-attributes.Leake
L
6

Another solution is to create your own extension method:

ActionLink<TController>(this HtmlHelper helper, Expression<Action<TController>> action, string linkText, object htmlAttributes, LinkOptions options)

and as the last parameter is the enumeration LinkOptions

[Flags]
public enum LinkOptions
{
    PlainContent = 0,
    EncodeContent = 1,
}

and then you can use it as follows:

Html.ActionLink<Car>(
     c => c.Delete(item.ID), "<span class=\"redC\">X</span>",
     new { Class = "none left" }, 
     LinkOptions.PlainContent)

I'll post whole description of this solution on my blog: http://fknet.wordpress.com/

Lecithinase answered 16/1, 2009 at 16:50 Comment(0)
M
5

The short answer is that is not possible. Your options are to write your own extension method to have an ImageActionLink, not too hard to do. Or add an attribute to the actionLink and replace the innerhtml with the image tag.

Mobley answered 4/12, 2008 at 19:7 Comment(0)
P
5

See version 7 the Contact Manager Tutorial on http://asp.net/mvc. Stephen Walther has an example of creating an Ajax.ActionLink that is an image.

Paradigm answered 29/3, 2009 at 21:2 Comment(0)
P
4

MVC3, Html.ActionImageLink and Ajax.ActionImageLink

Thank you to all the other answers in helping me with these.

public static MvcHtmlString ActionImageLink(this HtmlHelper helper, string imageUrl, string altText, string actionName, string controller, object routeValues)
{
    var builder = new TagBuilder("img");
    builder.MergeAttribute("src", imageUrl);
    builder.MergeAttribute("alt", altText);
    var link = helper.ActionLink("[replaceme]", actionName, controller, routeValues);
    return new MvcHtmlString(link.ToHtmlString().Replace("[replaceme]", builder.ToString(TagRenderMode.SelfClosing)));
}
public static MvcHtmlString ActionImageLink(this AjaxHelper helper, string imageUrl, string altText, string actionName, string controller, object routeValues, AjaxOptions ajaxOptions)
{
    var builder = new TagBuilder("img");
    builder.MergeAttribute("src", imageUrl);
    builder.MergeAttribute("alt", altText);
    var link = helper.ActionLink("[replaceme]", actionName, controller, routeValues, ajaxOptions);
    return new MvcHtmlString(link.ToHtmlString().Replace("[replaceme]", builder.ToString(TagRenderMode.SelfClosing)));
}
Petrochemistry answered 14/7, 2011 at 1:58 Comment(1)
Note: You need the following in your code for this to compile (VS 2010 cannot resolve missing references for extension methods): using System.Web.Mvc.Ajax; using System.Web.Mvc.Html;Horripilate
N
4

General solution: include any Razor you want inside the action link

There's a much better solution using Razor template delegates, which allows to insert any Razor code inside the action link in a very natural way. So you can add an image, or any other code.

This is the extension method:

public static IHtmlString ActionLink<T>(this AjaxHelper ajaxHelper,
    T item, Func<T,HelperResult> template, string action,
    string controller, object routeValues, AjaxOptions options)
{
    string rawContent = template(item).ToHtmlString();
    MvcHtmlString a = ajaxHelper.ActionLink("$$$", action, 
        controller, routeValues, options);
    return MvcHtmlString.Create(a.ToString().Replace("$$$", rawContent));
}

An this is how it can be used:

@Ajax.ActionLink(car, 
    @<div>
        <h1>@car.Maker</h1>
        <p>@car.Description</p>
        <p>Price: @string.Format("{0:C}",car.Price)</p>
    </div>, ...

This allows to write Razor with intellisense, and use any object you want for the template (the ViewModel, or any other object, like the car in my sample). And you can use any helper inside the template to nest images or whatver element you want.

Note for Resharper Users

If you are using R# in your project, you can add R# annotations to improve Intellisense:

public static IHtmlString ActionLink<T>(this AjaxHelper ajaxHelper, T item,
    Func<T, HelperResult> template, 
    [AspMvcAction] string action, [AspMvcController] string controller, 
    object routeValues, AjaxOptions options)
Noh answered 17/6, 2013 at 15:49 Comment(4)
In my opinion this is the best solution. Compact and markup friendly!Blockhouse
The only drawback is R# doesn't understand it.Blockhouse
Where i can place this extension method ?Scowl
What do you mean by "where can I place this extension method?"? I don't understand what you mean. Is this answer what you expect: define the method in any static class and include a using in your Razor file to be able to use it?Noh
J
1

Every answer is good but I found the easiest one:

@Html.ActionLink( " ", "Index", "Countries", null, new
{
        style = "background: url('../../Content/Images/icon.png') no-repeat center right;display:block; height:24px; width:24px;margin-top:-2px;text-decoration:none;"
} )

Note that it is using a white space (" ") for the link text. It will not work with an empty text.

Jean answered 11/4, 2012 at 19:8 Comment(0)
L
0

The first solution is to use a helper static method DecodeLinkContent like the following:

DecodeLinkContent(Html.ActionLink<Home>(c => c.Delete(item.ID), "<span class=\"redC\">X</span>",new { Class = "none left"})) 

DecodeLinkContent has to find first '>' and last '<' and has to replace the content with HttpUtility.Decode(content).

This solution is little bit a hack but I think it's the most easy.

Lecithinase answered 16/1, 2009 at 16:43 Comment(0)
F
0

Update for MVC3 using Templated Razor Delegates relies on T4Mvc,but brings so much power.

Based on various other answers on this page.

        public static HelperResult WrapInActionLink(this AjaxHelper helper,ActionResult result, Func<object,HelperResult> template,AjaxOptions options)
    {
        var link=helper.ActionLink("[replaceme]",result,options);
        var asString=link.ToString();
        var replaced=asString.Replace("[replaceme]",template(null).ToString());

        return new HelperResult(writer =>
        {
            writer.Write(replaced);
        });
    }

Allows:

@Ajax.WrapInActionLink(MVC.Deal.Details(deal.ID.Value),@<img alt='Edit deal details' src='@Links.Content.Images.edit_16_gif'/>, new AjaxOptions() { UpdateTargetId="indexDetails" })
Fredrick answered 5/12, 2011 at 20:21 Comment(0)
S
0

.li_inbox { background: url(inbox.png) no-repeat; padding-left:40px; /image background wight 40px/ }


<li class="li_inbox" >
          @Ajax.ActionLink("Inbox", "inbox","Home", new {  },
            new AjaxOptions
        {
            UpdateTargetId = "MainContent",
            InsertionMode = InsertionMode.Replace,
            HttpMethod = "GET"
          })

Skirmish answered 5/8, 2013 at 16:14 Comment(0)
H
0

Try this

@Html.Raw(HttpUtility.HtmlDecode(Ajax.ActionLink( "<img src=\"/images/sjt.jpg\" title=\"上一月\" border=\"0\" alt=\"上一月\" />", "CalendarPartial", new { strThisDate = Model.dtCurrentDate.AddMonths(-1).ToString("yyyy-MM-dd") }, new AjaxOptions { @UpdateTargetId = "calendar" }).ToString()))
Hydrotaxis answered 23/8, 2013 at 6:33 Comment(1)
please edit your answer and format the code to make it readableBaltoslavic
K
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 (Ajax.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.

Kvass answered 10/10, 2013 at 17:32 Comment(0)
C
0

All are very Nice solutions, but if you dislike having a replace in your solution you can try this:

{
    var url = new UrlHelper(helper.ViewContext.RequestContext);

    // build the <img> tag
    var imgBuilder = new TagBuilder("img");
    imgBuilder.MergeAttribute("src", url.Content(imageUrl));
    imgBuilder.MergeAttribute("alt", altText);
    string imgHtml = imgBuilder.ToString(TagRenderMode.SelfClosing);

    //build the <a> tag
    var anchorBuilder = new TagBuilder("a");
    anchorBuilder.MergeAttribute("href", url.Action(actionName, controller, routeValues));
    anchorBuilder.InnerHtml = imgHtml; // include the <img> tag inside            
    anchorBuilder.MergeAttributes<string, object>(ajaxOptions.ToUnobtrusiveHtmlAttributes());
    string anchorHtml = anchorBuilder.ToString(TagRenderMode.Normal);

    return MvcHtmlString.Create(anchorHtml);
}

Furthermore, in my case, if I don't use url.Content(imageUrl), the image doesn't display.

Cryptogam answered 16/3, 2014 at 21:58 Comment(0)
W
0

I have found that far and away the best solution to this is to use the input tag with type="image"

@using (Ajax.BeginForm( "LoadTest","Home" , new System.Web.Mvc.Ajax.AjaxOptions { UpdateTargetId = "[insert your target tag's id here]" }))
                {
                    <input type="image" class="[css style class here]" src="[insert image link here]">
                }

It's easy and it's fast.

I've used it in combination with other controls libraries that interfere with AjaxOptions, so I tend to type out the whole System.Web.Mvc.Ajax.AjaxOptions just in case I end up trying a different set in the future.

NOTE: I have noticed that this does appear to have issues within MVC3 (something to do with type="image"), it does work for MVC 4 though

Westbound answered 14/5, 2014 at 13:36 Comment(0)
D
0

Use this Extension to generate ajax link with glifyphicon:

    /// <summary>
    /// Create an Ajax.ActionLink with an associated glyphicon
    /// </summary>
    /// <param name="ajaxHelper"></param>
    /// <param name="linkText"></param>
    /// <param name="actionName"></param>
    /// <param name="controllerName"></param>
    /// <param name="glyphicon"></param>
    /// <param name="ajaxOptions"></param>
    /// <param name="routeValues"></param>
    /// <param name="htmlAttributes"></param>
    /// <returns></returns>
    public static MvcHtmlString ImageActionLink(this AjaxHelper ajaxHelper, string linkText, string actionName, string controllerName, string glyphicon, AjaxOptions ajaxOptions, RouteValueDictionary routeValues = null, object htmlAttributes = null)
    {
        //Example of result:          
        //<a id="btnShow" href="/Customers/ShowArtworks?customerId=1" data-ajax-update="#pnlArtworks" data-ajax-success="jsSuccess"
        //data-ajax-mode="replace" data-ajax-method="POST" data-ajax-failure="jsFailure" data-ajax-confirm="confirm" data-ajax-complete="jsComplete"
        //data-ajax-begin="jsBegin" data-ajax="true">
        //  <i class="glyphicon glyphicon-pencil"></i>
        //  <span>Edit</span>
        //</a>

        var builderI = new TagBuilder("i");
        builderI.MergeAttribute("class", "glyphicon " + glyphicon);
        string iTag = builderI.ToString(TagRenderMode.Normal);

        string spanTag = "";
        if (!string.IsNullOrEmpty(linkText))
        {
            var builderSpan = new TagBuilder("span") { InnerHtml = " " + linkText };
            spanTag = builderSpan.ToString(TagRenderMode.Normal);
        }

        //Create the "a" tag that wraps
        var builderA = new TagBuilder("a");

        var requestContext = HttpContext.Current.Request.RequestContext;
        var uh = new UrlHelper(requestContext);

        builderA.MergeAttribute("href", uh.Action(actionName, controllerName, routeValues));

        builderA.MergeAttributes(HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes));
        builderA.MergeAttributes((ajaxOptions).ToUnobtrusiveHtmlAttributes());

        builderA.InnerHtml = iTag + spanTag;

        return new MvcHtmlString(builderA.ToString(TagRenderMode.Normal));
    }
David answered 9/11, 2014 at 20:48 Comment(0)
Q
0

Use Html data- attributes

<a data-ajax="true" data-ajax-begin="..." data-ajax-success="..." href="@Url.Action("Delete")">
<i class="halflings-icon remove"></i>
</a>
              

Replace the

<i class="halflings-icon remove"></i>

with your own image

Quaternion answered 8/2, 2015 at 14:44 Comment(0)
S
0

Others didn't work for me as the .ToHtmlString() spat out a string in MVC 4.

the below passes an id to the edit control and displays an edit image instead of the text spag:

@MvcHtmlString.Create(Ajax.ActionLink("Spag", "Edit", new { id = item.x0101EmployeeID }, new AjaxOptions() { UpdateTargetId = "selectDiv", InsertionMode = InsertionMode.Replace, HttpMethod = "GET" }).ToHtmlString().Replace("Spag", "<img src=\"" + Url.Content("../../Images/edit.png") + "\" />"))
Somniferous answered 19/10, 2017 at 8:14 Comment(0)
S
-1
actionName+"/"+routeValues Proje/ControlName/ActionName/Id




    using System.Web;
    using System.Web.Mvc;
    using System.Web.Mvc.Ajax;

    namespace MithatCanMvc.AjaxHelpers
{

    public static class ImageActionLinkHelper
    {
        public static IHtmlString ImageActionLink(this AjaxHelper helper, string imageUrl, string altText, string actionName, string routeValues, AjaxOptions ajaxOptions)
        {
            var builder = new TagBuilder("img");
            builder.MergeAttribute("src", imageUrl);
            builder.MergeAttribute("alt", altText);
            var link = helper.ActionLink("[replaceme]", actionName+"/"+routeValues, ajaxOptions).ToHtmlString();
            return MvcHtmlString.Create(link.Replace("[replaceme]", builder.ToString(TagRenderMode.SelfClosing)));

        }

    }

}
Striper answered 11/3, 2013 at 15:15 Comment(0)
P
-2

I don't know, this seems easier to me:

    <a href="@Url.Action("index", "home")">
        <img src="~/Images/rocket.png" width="25" height="25" title="Launcher" />
    </a>
Prevent answered 26/2, 2019 at 14:46 Comment(1)
Not an answer to the questionGoodden

© 2022 - 2024 — McMap. All rights reserved.