Action Image MVC3 Navaja

¿Cuál es la mejor manera de reemplazar enlaces con imágenes usando Razor en MVC3? Simplemente hago esto en este momento:

Edit 

¿Hay una mejor manera?

Puede crear un método de extensión para HtmlHelper para simplificar el código en su archivo CSHTML. Puede reemplazar sus tags con un método como este:

 // Sample usage in CSHTML @Html.ActionImage("Edit", new { id = MyId }, "~/Content/Images/Image.bmp", "Edit") 

Aquí hay un método de muestra de extensión para el código anterior:

 // Extension method public static MvcHtmlString ActionImage(this HtmlHelper html, string action, object routeValues, string imagePath, string alt) { var url = new UrlHelper(html.ViewContext.RequestContext); // build the  tag var imgBuilder = new TagBuilder("img"); imgBuilder.MergeAttribute("src", url.Content(imagePath)); imgBuilder.MergeAttribute("alt", alt); string imgHtml = imgBuilder.ToString(TagRenderMode.SelfClosing); // build the  tag var anchorBuilder = new TagBuilder("a"); anchorBuilder.MergeAttribute("href", url.Action(action, routeValues)); anchorBuilder.InnerHtml = imgHtml; // include the  tag inside string anchorHtml = anchorBuilder.ToString(TagRenderMode.Normal); return MvcHtmlString.Create(anchorHtml); } 

Puede usar Url.Content que funciona para todos los enlaces a medida que traduce la tilde ~ al uri raíz.

  Edit  

Sobre la base de la respuesta de Lucas anterior, esta es una sobrecarga que toma un nombre de controlador como parámetro, similar a ActionLink. Use esta sobrecarga cuando su imagen se vincule a una Acción en un controlador diferente.

 // Extension method public static MvcHtmlString ActionImage(this HtmlHelper html, string action, string controllerName, object routeValues, string imagePath, string alt) { var url = new UrlHelper(html.ViewContext.RequestContext); // build the  tag var imgBuilder = new TagBuilder("img"); imgBuilder.MergeAttribute("src", url.Content(imagePath)); imgBuilder.MergeAttribute("alt", alt); string imgHtml = imgBuilder.ToString(TagRenderMode.SelfClosing); // build the  tag var anchorBuilder = new TagBuilder("a"); anchorBuilder.MergeAttribute("href", url.Action(action, controllerName, routeValues)); anchorBuilder.InnerHtml = imgHtml; // include the  tag inside string anchorHtml = anchorBuilder.ToString(TagRenderMode.Normal); return MvcHtmlString.Create(anchorHtml); } 

Bueno, podrías usar la solución @Lucas, pero también hay otra manera.

  @Html.ActionLink("Update", "Update", *Your object value*, new { @class = "imgLink"}) 

Ahora, agregue esta clase en un archivo CSS o en su página:

 .imgLink { background: url(YourImage.png) no-repeat; } 

Con esa clase, cualquier enlace tendrá su imagen deseada.

Esto resultó ser un hilo muy útil.

Para aquellos que son alérgicos a las llaves, aquí está la versión VB.NET de las respuestas de Lucas y Crake:

 Public Module ActionImage  Function ActionImage(html As HtmlHelper, Action As String, RouteValues As Object, ImagePath As String, AltText As String) As MvcHtmlString Dim url = New UrlHelper(html.ViewContext.RequestContext) Dim imgHtml As String 'Build the  tag Dim imgBuilder = New TagBuilder("img") With imgBuilder .MergeAttribute("src", url.Content(ImagePath)) .MergeAttribute("alt", AltText) imgHtml = .ToString(TagRenderMode.Normal) End With Dim aHtml As String 'Build the  tag Dim aBuilder = New TagBuilder("a") With aBuilder .MergeAttribute("href", url.Action(Action, RouteValues)) .InnerHtml = imgHtml 'Include the  tag inside aHtml = aBuilder.ToString(TagRenderMode.Normal) End With Return MvcHtmlString.Create(aHtml) End Function  Function ActionImage(html As HtmlHelper, Action As String, Controller As String, RouteValues As Object, ImagePath As String, AltText As String) As MvcHtmlString Dim url = New UrlHelper(html.ViewContext.RequestContext) Dim imgHtml As String 'Build the  tag Dim imgBuilder = New TagBuilder("img") With imgBuilder .MergeAttribute("src", url.Content(ImagePath)) .MergeAttribute("alt", AltText) imgHtml = .ToString(TagRenderMode.Normal) End With Dim aHtml As String 'Build the  tag Dim aBuilder = New TagBuilder("a") With aBuilder .MergeAttribute("href", url.Action(Action, Controller, RouteValues)) .InnerHtml = imgHtml 'Include the  tag inside aHtml = aBuilder.ToString(TagRenderMode.Normal) End With Return MvcHtmlString.Create(aHtml) End Function End Module 

Este método de extensión también funciona (para ser colocado en una clase pública estática):

  public static MvcHtmlString 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 new MvcHtmlString( link.ToHtmlString().Replace("[replaceme]", builder.ToString(TagRenderMode.SelfClosing)) ); } 

Para agregar a todo el increíble trabajo iniciado por Luke, estoy publicando uno más que toma un valor de clase css y trata a clase y alt como parámetros opcionales (válido en ASP.NET 3.5+). Esto permitirá una mayor funcionalidad pero reducirá el número de métodos sobrecargados necesarios.

 // Extension method public static MvcHtmlString ActionImage(this HtmlHelper html, string action, string controllerName, object routeValues, string imagePath, string alt = null, string cssClass = null) { var url = new UrlHelper(html.ViewContext.RequestContext); // build the  tag var imgBuilder = new TagBuilder("img"); imgBuilder.MergeAttribute("src", url.Content(imagePath)); if(alt != null) imgBuilder.MergeAttribute("alt", alt); if (cssClass != null) imgBuilder.MergeAttribute("class", cssClass); string imgHtml = imgBuilder.ToString(TagRenderMode.SelfClosing); // build the  tag var anchorBuilder = new TagBuilder("a"); anchorBuilder.MergeAttribute("href", url.Action(action, controllerName, routeValues)); anchorBuilder.InnerHtml = imgHtml; // include the  tag inside string anchorHtml = anchorBuilder.ToString(TagRenderMode.Normal); return MvcHtmlString.Create(anchorHtml); } 

la modificación de diapositiva cambió Helper

  public static IHtmlString ActionImageLink(this HtmlHelper html, string action, object routeValues, string styleClass, string alt) { var url = new UrlHelper(html.ViewContext.RequestContext); var anchorBuilder = new TagBuilder("a"); anchorBuilder.MergeAttribute("href", url.Action(action, routeValues)); anchorBuilder.AddCssClass(styleClass); string anchorHtml = anchorBuilder.ToString(TagRenderMode.Normal); return new HtmlString(anchorHtml); } 

Clase de CSS

 .Edit { background: url('../images/edit.png') no-repeat right; display: inline-block; height: 16px; width: 16px; } 

Crea el enlace solo pasa el nombre de la clase

  @Html.ActionImageLink("Edit", new { id = item.ID }, "Edit" , "Edit") 

Me he unido a la respuesta de Lucas y ” ASP.NET MVC Helpers, fusionando dos objetos htmlAttributes juntos ” y más controllerName al siguiente código:

// Uso de muestra en CSHTML

  @Html.ActionImage("Edit", "EditController" new { id = MyId }, "~/Content/Images/Image.bmp", new { width=108, height=129, alt="Edit" }) 

Y la clase de extensión para el código de arriba:

 using System.Collections.Generic; using System.Reflection; using System.Web.Mvc; namespace MVC.Extensions { public static class MvcHtmlStringExt { // Extension method public static MvcHtmlString ActionImage( this HtmlHelper html, string action, string controllerName, object routeValues, string imagePath, object htmlAttributes) { //https://stackoverflow.com/questions/4896439/action-image-mvc3-razor var url = new UrlHelper(html.ViewContext.RequestContext); // build the  tag var imgBuilder = new TagBuilder("img"); imgBuilder.MergeAttribute("src", url.Content(imagePath)); var dictAttributes = htmlAttributes.ToDictionary(); if (dictAttributes != null) { foreach (var attribute in dictAttributes) { imgBuilder.MergeAttribute(attribute.Key, attribute.Value.ToString(), true); } } string imgHtml = imgBuilder.ToString(TagRenderMode.SelfClosing); // build the  tag var anchorBuilder = new TagBuilder("a"); anchorBuilder.MergeAttribute("href", url.Action(action, controllerName, routeValues)); anchorBuilder.InnerHtml = imgHtml; // include the  tag inside string anchorHtml = anchorBuilder.ToString(TagRenderMode.Normal); return MvcHtmlString.Create(anchorHtml); } public static IDictionary ToDictionary(this object data) { //https://stackoverflow.com/questions/6038255/asp-net-mvc-helpers-merging-two-object-htmlattributes-together if (data == null) return null; // Or throw an ArgumentNullException if you want BindingFlags publicAttributes = BindingFlags.Public | BindingFlags.Instance; Dictionary dictionary = new Dictionary(); foreach (PropertyInfo property in data.GetType().GetProperties(publicAttributes)) { if (property.CanRead) { dictionary.Add(property.Name, property.GetValue(data, null)); } } return dictionary; } } } 

Esto sería trabajo muy bien

 ">Edit