Related
I have created the following Html Helper Class for displaying a Image:
Class:
namespace MvcWebMobile.CustomHelpers
{
public static class CustomHelper
{
public static string Image(this HtmlHelper helper, string id, string url, string alternateText)
{
return Image(helper, id, url, alternateText, null);
}
public static string Image(this HtmlHelper helper, string id, string url, string alternateText, object htmlAttributes)
{
// Create tag builder
var builder = new TagBuilder("img");
// Create valid id
builder.GenerateId(id);
// Add attributes
builder.MergeAttribute("src", url);
builder.MergeAttribute("alt", alternateText);
builder.MergeAttributes(new RouteValueDictionary(htmlAttributes));
// Render tag
return builder.ToString(TagRenderMode.SelfClosing);
}
}
}
View:
#Html.Image("img1", "../../Content/images/icons-18-black.png", "logo")
Now when i use the custom helper in my view the Image is not displayed, instead of image following message is printed on web page
<img alt="logo" id="img1" src="../../Content/images/icons-18-black.png" /> <img alt="logo" border="4px" id="img1" src="../../Content/images/icons-18-black.png" />
Your helper should return a HtmlString instead of a string.
public static HtmlString Image(this HtmlHelper helper, string id, string url, string alternateText)
{
return Image(helper, id, url, alternateText, null);
}
public static HtmlString Image(this HtmlHelper helper, string id, string url, string alternateText, object htmlAttributes)
{
// ...
return new HtmlString(builder.ToString(TagRenderMode.SelfClosing));
}
Instead of returning string try returning MvcHtmlString,
public static MvcHtmlString Image(this HtmlHelper helper, string id, string url, string alternateText)
{
}
Use MvchtmlString:
public static MvcHtmlString Image(this HtmlHelper helper, string id, string url, string alternateText)
{
// ...
return new MvcHtmlString(builder.ToString(TagRenderMode.SelfClosing));
}
First of all I'm using MVC 3 RC1 with the Razor view engine. I've got an HTML helper extension which looks like this:
public static string TabbedMenuItem(this HtmlHelper htmlHelper, string text, string actionName, string controllerName) {
StringBuilder builder = new StringBuilder();
builder.Append("<li>");
builder.Append(text);
builder.Append("</li>");
return builder.ToString();
}
And on the view it's called like this:
#Html.TabbedMenuItem("Home", "Index", "Home")
The problem I've got is that MVC is automatically HTML encoding the result in the view so all I get is the encoded version of the string:
<li>Home</li>
Does anyone know how to disable the automatic encoding for your HTML helper extensions?
Thanks in advance
Andy
public static IHtmlString TabbedMenuItem(this HtmlHelper htmlHelper, string text, string actionName, string controllerName)
{
StringBuilder builder = new StringBuilder();
builder.Append("<li>");
builder.Append(text);
builder.Append("</li>");
return MvcHtmlString.Create(builder.ToString());
}
Use return value IHtmlString.
Hope this help.
Use TagBuilder
How do I create an ASP.Net MVC Helper for an Html.Label which takes in attributes?
Currently when I define an Html.TextBox I am able to pass in a list of attributes. Sort of like below:
new {disabled="disabled", #class="pcTextBoxWithoutPaddingDisabled"})%>
However, it does not look as though the Html.Label has this feature. As a result, I have to define my labels using the label tag. Sort of like below:
<label class="pcLabelBlackWithoutPadding">
I would like to be consistent I how my Html element get created.
So, how do I create an Html.Label that will take in a list of attributes?
Thanks for your help.
This is updated version for MVC3:
public static MvcHtmlString Label(this HtmlHelper helper, String htmlFieldName, String labelText, Object htmlAttributes)
{
ModelMetadata metadata = ModelMetadata.FromStringExpression(htmlFieldName, helper.ViewData);
String innerText = labelText ?? (metadata.DisplayName ?? (metadata.PropertyName ?? htmlFieldName.Split('.').Last()));
if (String.IsNullOrEmpty(innerText))
{
return MvcHtmlString.Empty;
}
TagBuilder tagBuilder = new TagBuilder("label");
tagBuilder.Attributes.Add("for", TagBuilder.CreateSanitizedId(helper.ViewContext.ViewData.TemplateInfo.GetFullHtmlFieldName(htmlFieldName)));
tagBuilder.MergeAttributes(new RouteValueDictionary(htmlAttributes));
tagBuilder.SetInnerText(innerText);
return new MvcHtmlString(tagBuilder.ToString(TagRenderMode.Normal));
}
I have modified Alexandr code a bit with lambda expression, in case anyone needed the lambda expression.
usage:
#Html.LabelFor(model => model.Property , new { #class = "bigFont" })
code:
public static MvcHtmlString LabelFor<TModel, TProperty>(
this HtmlHelper<TModel> htmlHelper,
Expression<Func<TModel, TProperty>> expression, Object htmlAttributes)
{
var metadata = ModelMetadata.FromLambdaExpression(expression, htmlHelper.ViewData);
var innerText = metadata.DisplayName ?? metadata.PropertyName;
if (String.IsNullOrEmpty(innerText))
{
return MvcHtmlString.Empty;
}
var tagBuilder = new TagBuilder("label");
tagBuilder.Attributes.Add("for", TagBuilder.CreateSanitizedId(htmlHelper.ViewContext.ViewData.TemplateInfo.GetFullHtmlFieldName(metadata.PropertyName)));
tagBuilder.MergeAttributes(new RouteValueDictionary(htmlAttributes));
tagBuilder.SetInnerText(innerText);
return new MvcHtmlString(tagBuilder.ToString(TagRenderMode.Normal));
}
I'd suggest creating your own HtmlHelper extension method and using a TagBuilder to create the label.
public static HtmlHelperExtensions
{
public static Label( this HtmlHelper helper, string labelText, object properties )
{
var builder = new TagBuilder("label");
builder.MergeAttributes( new RouteValueDictionary( properties ) );
builder.SetInnerText( labelText );
return builder.ToString( TagRenderMode.Normal );
}
}
See the MVC source code for ideas on how to create a strongly-typed label helper. Note that you'll need to add the namespace containing your extensions either to the page or the web.config to be able to use it.
The Html.RouteLink() HtmlHelper works great for text links. But what's the best way to link an image?
<img src="..." alt="..." />
Here is mine, it`s the core function make some overloads
public static string ImageLink(this HtmlHelper htmlHelper, string imgSrc, string alt, string actionName, string controllerName, object routeValues, object htmlAttributes, object imgHtmlAttributes)
{
UrlHelper urlHelper = ((Controller)htmlHelper.ViewContext.Controller).Url;
string imgtag = htmlHelper.Image(imgSrc, alt,imgHtmlAttributes);
string url = urlHelper.Action(actionName, controllerName, routeValues);
TagBuilder imglink = new TagBuilder("a");
imglink.MergeAttribute("href", url);
imglink.InnerHtml =imgtag;
imglink.MergeAttributes(new RouteValueDictionary(htmlAttributes), true);
return imglink.ToString();
}
This is an updated version that I have from MiniScalope answer above. I'm using VS2010 and ASP.Net MVC 2 Preview
public static string ImageLink(this HtmlHelper htmlHelper, string imgSrc, string alt, string actionName, string controllerName, object routeValues, object htmlAttributes, object imgHtmlAttributes)
{
UrlHelper urlHelper = ((Controller)htmlHelper.ViewContext.Controller).Url;
TagBuilder imgTag = new TagBuilder("img");
imgTag.MergeAttribute("src", imgSrc);
imgTag.MergeAttributes((IDictionary<string, string>) imgHtmlAttributes,true);
string url = urlHelper.Action(actionName, controllerName, routeValues);
TagBuilder imglink = new TagBuilder("a");
imglink.MergeAttribute("href", url);
imglink.InnerHtml = imgTag.ToString();
imglink.MergeAttributes((IDictionary<string, string>)htmlAttributes, true);
return imglink.ToString();
}
<%= Html.ActionLink(Html.Image(imageUrl, imageAlt), actionName, controllerName) %>
could work, the image extension is from the futures assembly.
Or make your own extention.
Create your own helper extension.
public static string Image(this HtmlHelper helper, string src, string alt)
{
TagBuilder tb = new TagBuilder("img");
tb.Attributes.Add("src", helper.Encode(src));
tb.Attributes.Add("alt", helper.Encode(alt));
return tb.ToString(TagRenderMode.SelfClosing);
}
I don't have enough SO swagger to add a comment, but this is a comment on
MiniScalope's comment above:
UrlHelper urlHelper = ((Controller)htmlHelper.ViewContext.Controller).Url;
I would suggest making this an HtmlHelper extension method in itself (and simplify it), for reuse:
private static UrlHelper Url(this HtmlHelper helper)
{
return new UrlHelper(helper.ViewContext.RequestContext);
}
<%= Html.RouteLink("PLACEHOLDER", ...).Replace("PLACEHOLDER", "<img src=""..."" alt=""..."" />")%>
this code has been tested on mvc4...
public static MvcHtmlString ImageLink(this HtmlHelper htmlHelper, string imgSrc, string alt, string actionName, string controllerName, object routeValues, object htmlAttributes, object imgHtmlAttributes)
{
UrlHelper urlHelper = ((Controller)htmlHelper.ViewContext.Controller).Url;
var imgTag = new TagBuilder("img");
imgTag.MergeAttribute("src", imgSrc);
imgTag.MergeAttributes((IDictionary<string, string>)imgHtmlAttributes, true);
string url = urlHelper.Action(actionName, controllerName, routeValues);
var imglink = new TagBuilder("a");
imglink.MergeAttribute("href", url);
imglink.InnerHtml = imgTag.ToString();
imglink.MergeAttributes((IDictionary<string, string>)htmlAttributes, true);
return MvcHtmlString.Create(imglink.ToString());
}
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 :-)
You can use the URL.Action method
<img src="../../Content/Images/add_48.png" />
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.
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.
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.
In MVC3, your link would look like this:
<img src="../../Content/Images/add_48.png" />
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;
}
You can use this control.It behaves like ActionLink.
http://agilefutures.com/index.php/2009/06/actionimage-aspnet-mvc
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)); %>" />
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.
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
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.
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("<", "<").Replace(">", ">")))
The problem for me is, that the ActionLink name is encoded so I have < instead of <.
I just removed this encoding and the result works for me.
(Is there a better way of doing this instead using replace?)
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.
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://stackoverflow.com/a/19302438/961139