可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
How can I put a span element inside ActionLink BUT NOT WITH URL.ACTION?
This:
<li><span>
@Ajax.ActionLink("LinkText", "ControllerName", new AjaxOptions
{
UpdateTargetId = "div",
InsertionMode = InsertionMode.Replace,
HttpMethod = "GET",
LoadingElementId = "progress"
})
</span></li>
generates this:
<li>
<span>
<a href="/Home/ControllerName" data-ajax-update="#scroll"
data-ajax-mode="replace" data-ajax-method="GET"
data-ajax-loading="#progress" data-ajax="true">LinkText</a>
</span>
</li>
But I need something else. How can I create a custom MVC3 ActionLink method that generates this output:
<li>
<a href="/Home/ControllerName" data-ajax-update="#scroll"
data-ajax-mode="replace" data-ajax-method="GET"
data-ajax-loading="#progress" data-ajax="true">
<span>LinkText</span> // this span generated inside <a>
</a>
</li>
回答1:
How to put span element inside ActionLink BUT NOT WITH URL.ACTION
Simple answer: you can't. The ActionLink method HTML encodes the link text and there's not much you could do about it (you could open a ticket at Microsoft so that they provide an overload that allows you to do this in ASP.NET MVC vNext).
At the moment you could write a custom html helper that won't encode:
public static class AjaxExtensions
{
public static IHtmlString MyActionLink(
this AjaxHelper ajaxHelper,
string linkText,
string actionName,
AjaxOptions ajaxOptions
)
{
var targetUrl = UrlHelper.GenerateUrl(null, actionName, null, null, ajaxHelper.RouteCollection, ajaxHelper.ViewContext.RequestContext, true);
return MvcHtmlString.Create(ajaxHelper.GenerateLink(linkText, targetUrl, ajaxOptions ?? new AjaxOptions(), null));
}
private static string GenerateLink(
this AjaxHelper ajaxHelper,
string linkText,
string targetUrl,
AjaxOptions ajaxOptions,
IDictionary<string, object> htmlAttributes
)
{
var a = new TagBuilder("a")
{
InnerHtml = linkText
};
a.MergeAttributes<string, object>(htmlAttributes);
a.MergeAttribute("href", targetUrl);
a.MergeAttributes<string, object>(ajaxOptions.ToUnobtrusiveHtmlAttributes());
return a.ToString(TagRenderMode.Normal);
}
}
and then:
@Ajax.MyActionLink(
"<span>LinkText</span>",
"ActionName",
new AjaxOptions {
UpdateTargetId = "div",
InsertionMode = InsertionMode.Replace,
HttpMethod = "GET",
LoadingElementId = "progress"
}
)
回答2:
I know this is old but I use this quick and dirty way for adding styled button links in my grids. You could add overloads to include route names/etc. as well. Hope this helps someone.
public static MvcHtmlString GridAnchor(this HtmlHelper html, string linkText, string actionName, string controllerName,
object routeValues, object htmlAttributes)
{
var result = new TagBuilder("a");
var url = UrlHelper.GenerateUrl(null, actionName, controllerName, new RouteValueDictionary(routeValues), html.RouteCollection,
html.ViewContext.RequestContext, true);
result.Attributes.Add("href", url);
result.MergeAttributes(new RouteValueDictionary(htmlAttributes));
result.InnerHtml = "<span>" + linkText + "</span>";
return MvcHtmlString.Create(result.ToString());
}
回答3:
I modified Darins answer just a bit to be able to accomodate RouteValues.
public static class AjaxExtensions
{
public static IHtmlString MyActionLink(
this AjaxHelper ajaxHelper,
string linkText,
string actionName,
AjaxOptions ajaxOptions
)
{
var targetUrl = UrlHelper.GenerateUrl(null, actionName, null, null, ajaxHelper.RouteCollection, ajaxHelper.ViewContext.RequestContext, true);
return MvcHtmlString.Create(ajaxHelper.GenerateLink(linkText, targetUrl, ajaxOptions ?? new AjaxOptions(), null));
}
public static IHtmlString MyActionLink(
this AjaxHelper ajaxHelper,
string linkText,
string actionName,
object routeValues,
AjaxOptions ajaxOptions
)
{
System.Web.Routing.RouteValueDictionary routeVals = new System.Web.Routing.RouteValueDictionary(routeValues);
var targetUrl = UrlHelper.GenerateUrl(null, actionName, null, routeVals, ajaxHelper.RouteCollection, ajaxHelper.ViewContext.RequestContext, true);
return MvcHtmlString.Create(ajaxHelper.GenerateLink(linkText, targetUrl, ajaxOptions ?? new AjaxOptions(), null));
}
private static string GenerateLink(
this AjaxHelper ajaxHelper,
string linkText,
string targetUrl,
AjaxOptions ajaxOptions,
IDictionary htmlAttributes
)
{
var a = new TagBuilder("a")
{
InnerHtml = linkText
};
a.MergeAttributes(htmlAttributes);
a.MergeAttribute("href", targetUrl);
a.MergeAttributes(ajaxOptions.ToUnobtrusiveHtmlAttributes());
return a.ToString(TagRenderMode.Normal);
}
}
回答4:
I know this is an old thread, but you can also do something inline along the lines of:
<li><span>
@{
var lnk = Ajax.ActionLink("LinkText", "ControllerName", new AjaxOptions {
UpdateTargetId = "div",
InsertionMode = InsertionMode.Replace,
HttpMethod = "GET",
LoadingElementId = "progress"
});
@Html.Raw(lnk.ToString().Replace(">LinkText<", "><span>LinkText</span><"));
// Remember to include the open and closing >< !
}
</span></li>
Its a hack I know, but you could easily write an extension along these lines
回答5:
How difficult is it to achieve this by using JQuery?
We can always use JQuery
and append the <span></span>
once the DOM is loaded.
May be not the perfect solution but for developers using jquery and dont want to write html helpers classes as above answer this might be the work around.
回答6:
I modified markdotnet's answer using Jetbrain's Annotation package to provide intellisense on the actionName parameter. I Also changed the linkText parameter to improve code visualizing; VS will treat it as HTML code, instead of just a simple string.
Example:
@Ajax.MyActionLink(
@<div>
<span>Click me</span>
</div>,
"MyAction",
new { Id = 1 },
new AjaxOptions
{
UpdateTargetId = "targed-id",
OnComplete = "oncomplete();"
})
Extension class:
using System;
using System.Collections.Generic;
using System.Web;
using System.Web.Mvc;
using System.Web.Mvc.Ajax;
using System.Web.WebPages;
using JetBrains.Annotations;
public static class AjaxExtensions
{
public static IHtmlString MyActionLink(
this AjaxHelper ajaxHelper,
Func<dynamic, HelperResult> linkHtml,
[AspMvcAction] string actionName,
AjaxOptions ajaxOptions
)
{
var targetUrl = UrlHelper.GenerateUrl(null, actionName, null, null, ajaxHelper.RouteCollection, ajaxHelper.ViewContext.RequestContext, true);
return MvcHtmlString.Create(ajaxHelper.GenerateLink(linkHtml, targetUrl, ajaxOptions ?? new AjaxOptions(), null));
}
public static IHtmlString MyActionLink(
this AjaxHelper ajaxHelper,
Func<dynamic, HelperResult> linkHtml,
[AspMvcAction] string actionName,
object routeValues,
AjaxOptions ajaxOptions
)
{
System.Web.Routing.RouteValueDictionary routeVals = new System.Web.Routing.RouteValueDictionary(routeValues);
var targetUrl = UrlHelper.GenerateUrl(null, actionName, null, routeVals, ajaxHelper.RouteCollection, ajaxHelper.ViewContext.RequestContext, true);
return MvcHtmlString.Create(ajaxHelper.GenerateLink(linkHtml, targetUrl, ajaxOptions ?? new AjaxOptions(), null));
}
private static string GenerateLink(
this AjaxHelper ajaxHelper,
Func<dynamic, HelperResult> linkHtml,
string targetUrl,
AjaxOptions ajaxOptions,
IDictionary<string, object> htmlAttributes
)
{
var a = new TagBuilder("a")
{
InnerHtml = linkHtml(null).ToString()
};
a.MergeAttributes(htmlAttributes);
a.MergeAttribute("href", targetUrl);
a.MergeAttributes(ajaxOptions.ToUnobtrusiveHtmlAttributes());
return a.ToString(TagRenderMode.Normal);
}
}