ASP.NET MVC Ajax.ActionLink with Image - ajax

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!

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" })%>

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.

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;" })

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/

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.

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.

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)));
}

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)

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.

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.

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" })

.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"
})

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()))

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.

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.

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

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));
}

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

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") + "\" />"))

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)));
}
}
}

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>

Related

Extending MVC RadioButtonFor using HtmlHelper extensions

I'm trying to build an HtmlHelper to add functionality to an MVC RadioButtonFor control. I simply want to add a class and style attribute to the radio button given certain conditions. I can't seem to get my extension to include attributes. I've followed several examples I've found online, but no luck.
Here is my code:
public static MvcHtmlString GCSRadioButtonForHelper<TModel>(
this HtmlHelper<TModel> htmlHelper,
Expression<Func<TModel, bool?>> expression,
Object htmlAttributes,
object value )
{
bool isRequired = false;
bool isHidden = false;
object styleList;
object classList;
Dictionary<string, object> attributes = new Dictionary<string, object>();
attributes.TryGetValue("class", out classList);
attributes.TryGetValue("style", out styleList);
ModelMetadata metadata = ModelMetadata.FromLambdaExpression(expression, htmlHelper.ViewData);
var categoryName = string.Empty;
if (metadata.ContainerType != null)
categoryName = metadata.ContainerType.Name + "." + metadata.PropertyName;
isHidden = GetIsHidden(metadata);
isRequired = GetIsRequired(metadata);
if (isHidden)
classList = classList + " GCSHidden ";
if (isRequired)
{
classList = classList + " GCSRequired ";
}
attributes.Remove("class");
attributes.Remove("style");
attributes.Add("class", classList);
attributes.Add("style", styleList);
//Render HTML String
MvcHtmlString html = System.Web.Mvc.Html.InputExtensions.RadioButtonFor(htmlHelper, expression, attributes, value);
return html;
}
The problem is that the result of InputExtensions.RadioButtonFor() never includes the attributes class or style as I have specified. Any ideas?
TIA

Correctly making an ActionLink extension with htmlAttributes

I use a custom extension for my ActionLinks. I have added an attribute data_url which is meant to be translated to an attribute of data-url. This is, replacing the underscaore with a dash.
Here is link 1 using my custom extension:
#Ajax.ActionLink("Add", MyRoutes.GetAdd(), new AjaxOptions()
, new { data_url = Url.Action(...)})
Result: data_url
Here is link 2 using the framework ActionLink:
#Ajax.ActionLink("Add 2", "x", "x", null, new AjaxOptions()
, new { data_url = Url.Action(...) })
Result: data-url
Here is the extension, simple enough, except that the only way to pass the htmlAttributes through that I know of is by using the ToDictionaryR() extension. I suspect this is the problem, so I am wondering if I should be using something else. I have supplied that extension below too.
public static MvcHtmlString ActionLink(this AjaxHelper helper, string linkText
, RouteValueDictionary routeValues, AjaxOptions ajaxOptions
, object htmlAttributes = null)
{
return helper.ActionLink(linkText, routeValues["Action"].ToString()
, routeValues["Controller"].ToString(), routeValues, ajaxOptions
, (htmlAttributes == null ? null : htmlAttributes.ToDictionaryR()));
}
public static IDictionary<string, object> ToDictionaryR(this object obj)
{
return TurnObjectIntoDictionary(obj);
}
public static IDictionary<string, object> TurnObjectIntoDictionary(object data)
{
var attr = BindingFlags.Public | BindingFlags.Instance;
var dict = new Dictionary<string, object>();
foreach (var property in data.GetType().GetProperties(attr))
{
if (property.CanRead)
{
dict.Add(property.Name, property.GetValue(data, null));
}
}
return dict;
}
thank you
You could use the AnonymousObjectToHtmlAttributes method which does exactly what you want and you don't need any custom extension methods:
public static MvcHtmlString ActionLink(
this AjaxHelper helper,
string linkText,
RouteValueDictionary routeValues,
AjaxOptions ajaxOptions,
object htmlAttributes = null
)
{
return helper.ActionLink(
linkText,
routeValues["Action"].ToString(),
routeValues["Controller"].ToString(),
routeValues,
ajaxOptions,
htmlAttributes == null ? null : HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes)
);
}

ASP.NET MVC - Current Page highlighting in navigation

I'm wondering how is it possible to add a CSS Class to the current page in your navigation when using ASP.NET MVC 3? Here is my navigation in my _Layout.cshtml file:
<p>#Html.ActionLink("Product Search", "Index", new { controller = "Home" }, new { #class = "current" })
| #Html.ActionLink("Orders", "Index", new { controller = "Orders" })
| #Html.ActionLink("My Account", "MyAccount", new { controller = "Account" })
| #Html.ActionLink("Logout", "LogOff", new { controller = "Account" })</p>
As you can see I have 4 links in my navigation with the first one having the CSS class "current" applied to it, I'd like to be able to add/remove this class to the different links in my navigation depending on which page the user is at. Is this possible?
Cheers
You can do this
#{
var currentController = ViewContext.RouteData.Values["controller"] as string ?? "Home";
var currentAction = ViewContext.RouteData.Values["action"] as string ?? "Index";
var currentPage = (currentController + "-" + currentAction ).ToLower();
}
#Html.ActionLink("Product Search", "Index", "Home", null,
new { #class = currentPage == "home-index" ? "current" : "" })
#Html.ActionLink("MyAccount", "MyAccount", "Account", null,
new { #class = currentPage == "account-myaccount" ? "current" : "" })
I would recommend using an extension method for this. Something like:
public static HtmlString NavigationLink(
this HtmlHelper html,
string linkText,
string actionName,
string controllerName)
{
string contextAction = (string)html.ViewContext.RouteData.Values["action"];
string contextController = (string)html.ViewContext.RouteData.Values["controller"];
bool isCurrent =
string.Equals(contextAction, actionName, StringComparison.CurrentCultureIgnoreCase) &&
string.Equals(contextController, controllerName, StringComparison.CurrentCultureIgnoreCase);
return html.ActionLink(
linkText,
actionName,
controllerName,
routeValues: null,
htmlAttributes: isCurrent ? new { #class = "current" } : null);
}
Then you can use it in your View by including the namespace of your extension and just calling your method:
#using MyExtensionNamespace;
...
#Html.NavigationLink("Product Search", "Index", "Home")
| #Html.NavigationLink("Orders", "Index", "Orders")
| #Html.NavigationLink("My Account", "MyAccount", "Account")
| #Html.NavigationLink("Logout", "LogOff", "Account")
This has the benefit of keeping your razor a little cleaner and is easily reusable in other views.
#{
var controller = ViewContext.RouteData.Values["controller"].ToString();
var action = ViewContext.RouteData.Values["action"].ToString();
var isActiveController = new Func<string, string, string, string, string>((ctrl, act, activeStyle, inactiveStyle) => controller == ctrl && action == act ? activeStyle : inactiveStyle);
}
Then in your class attribute in your HTML you can do:
class="#isActiveController("controlername","action","activecssstyleclass","inactiveccsstyle")"
Just an other way of #dknaack his answer.. bit more generic and less functionality to repeat in your code.
In my case,assume I have a Home page and a menu.
Add a ViewBag.Active as a placeholder in Home page like this:
#{
ViewBag.Title = "Home";
ViewBag.Active = "Home";
}
Then place it to your li class as a condition to active it or not:
<li class="#(ViewBag.Active=="Home"? "active" : "")">
<span>#ViewBag.Title</span>
</li>
I used this tutorial to get this done, it's a lot simpler to understand and takes 2 minutes
Hightlight Active menu item
You can also override the AnchorTagHelper (the default <a> tag helper) to create your own tag helper. The advantage is that it already has all required information by providing the asp-controller and even allows for autocomplete etc. by your IDE.
This is my TagHelper:
public class NavAnchorTagHelper : AnchorTagHelper
{
public NavAnchorTagHelper(IHtmlGenerator generator) : base(generator)
{
}
public override void Process(TagHelperContext context, TagHelperOutput output)
{
base.Process(context, output);
var contextController = (string)ViewContext.RouteData.Values["controller"];
if (contextController?.Equals(this.Controller) == true)
{
output.AddClass("text-dark", HtmlEncoder.Default);
}
output.TagName = "a";
}
}
And I use it like that:
<nav-anchor class="nav-link" asp-controller="MyController" asp-action="Index">Test</nav-anchor>

Adding a class to Html.MenuItem's

I've got a HTML list of menu items generated by MVC 2.
<%= Html.MenuItem("Home", "Home", "Index")%>
<%= Html.MenuItem("Login", "Login", "Account")%>
Which generate in HTML:
<li>
Home
</li>
<li>
Login
</li>
How can I add a CSS class to the element in the list for each item in the list?
I am guessing this MenuItem is an extension method that you wrote or that you took from someone, I am also guessing that they are wrapping an ActionLink Method, As in:
public static string MenuItem(this HtmlHelper helper, string linkText, string actionName, string controllerName)
{
string currentControllerName = (string)helper.ViewContext.RouteData.Values["controller"];
string currentActionName = (string)helper.ViewContext.RouteData.Values["action"];
// Add selected class
if (currentControllerName.Equals(controllerName, StringComparison.CurrentCultureIgnoreCase) && currentActionName.Equals(actionName, StringComparison.CurrentCultureIgnoreCase))
return string.Concat("<li class=\"selected\">", helper.ActionLink(linkText, actionName, controllerName), "</li>");
// Add link
return string.Concat("<li>", helper.ActionLink(linkText, actionName, controllerName), "</li>");
}
if this is the case just make it take is a css class as a parameter and use the ActionLink that takes in htmlattributes, as in:
public static string MenuItem(this HtmlHelper helper, string linkText, string actionName, string controllerName, string cssClass = "menu-item")
{
string currentControllerName = (string)helper.ViewContext.RouteData.Values["controller"];
string currentActionName = (string)helper.ViewContext.RouteData.Values["action"];
// Add selected class
if (currentControllerName.Equals(controllerName, StringComparison.CurrentCultureIgnoreCase) && currentActionName.Equals(actionName, StringComparison.CurrentCultureIgnoreCase))
return string.Concat("<li class=\"selected\">", helper.ActionLink(linkText, actionName, controllerName), "</li>");
// Add link
return string.Concat("<li>", helper.ActionLink(linkText, actionName, controllerName, new {#class = cssClass} ), "</li>");
}
then you just call them like this:
<%= Html.MenuItem("Home", "Home", "Index", "index-tem")%>

Quick question about Ajax.ActionLink and span

I have a simple question.
I have the following html code
<a href="#" class="purchase">
<span>Purchase</span><em>#string.Format("{0:C0}", Model.thisItem.ItemSalePrice)</em>
</a>
But I want to use a Ajax.Actionlink to make it as a ajax post.
I have the following updated code
#Ajax.ActionLink("Purchase", "AddToCart", "Browse", new { ItemID = Model.thisItem.ItemID }, new AjaxOptions { UpdateTargetId = "content" }, new { #class = "purchase" })
The question is how I can put the tag into the actionlink?
Thank you everyone.
UPDATES
I also got an answer from ASP.NET's forum, and it is even easier.
http://forums.asp.net/p/1702210/4518688.aspx/1?p=True&t=634468566867949718
Just specify it in the action link text parameter:
#Ajax.ActionLink(String.Format("{0} {1}", "Purchase", String.Format("{0:C0}", Model.thisItem.ItemSalePrice)), "AddToCart", "Browse", new { ItemID = Model.thisItem.ItemID }, new AjaxOptions { UpdateTargetId = "content" }, new { #class = "purchase" })
EDIT 1:
Other overloads are not shown, but this should be enough to get you started.
If you need more details, you can take a look at the MVC3 source and see how they setup their helpers.
public static MvcHtmlString CustomActionLink(this HtmlHelper htmlHelper, string linkText, float salePrice, string actionName, string controllerName, object routeValues, object htmlAttributes)
{
return CustomActionLink(htmlHelper, linkText, salePrice, actionName, controllerName, new RouteValueDictionary(routeValues), HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes));
}
public static MvcHtmlString CustomActionLink(this HtmlHelper htmlHelper, string linkText, float salePrice, string actionName, string controllerName, RouteValueDictionary routeValues, IDictionary<string, object> htmlAttributes)
{
var url = new UrlHelper(htmlHelper.ViewContext.RequestContext);
// Build the <span> tag
var spanBuilder = new TagBuilder("span");
spanBuilder.SetInnerText(linkText);
string spanHtml = spanBuilder.ToString(TagRenderMode.Normal);
// Build the <em> tag
var emBuilder = new TagBuilder("em");
emBuilder.SetInnerText(String.Format("{0:C0}", salePrice));
string emHtml = emBuilder.ToString(TagRenderMode.Normal);
// Build the <a> tag
var anchorBuilder = new TagBuilder("a");
anchorBuilder.MergeAttribute("href", url.Action(actionName, controllerName, routeValues));
anchorBuilder.InnerHtml = spanHtml + emHtml;
string anchorHtml = anchorBuilder.ToString(TagRenderMode.Normal);
return MvcHtmlString.Create(anchorHtml);
}
Note: HtmlHelper.AnonymousObjectToHtmlAttributes is under the System.Web.Mvc namespace.

Resources