I have in my Model:
[Display(Name = "Check to enter <break> the Quantity of items")]
public bool IsLimitedQuantity { get; set; }
and I am using
#Html.LabelFor(shop => shop.IsLimitedQuantity)
in my view.
Please suggest how I can fix this, because the label is just showing <break> as it is, instead of breaking to a new line.
You could write a custom LabelFor helper which doesn't HTML encode the text as does the standard LabelFor helper:
public static class LabelExtensions
{
public static IHtmlString UnencodedLabelFor<TModel, TProperty>(this HtmlHelper<TModel> html, Expression<Func<TModel, TProperty>> expression)
{
var metadata = ModelMetadata.FromLambdaExpression(expression, html.ViewData);
var htmlFieldName = ExpressionHelper.GetExpressionText(expression);
var text = (metadata.DisplayName ?? (metadata.PropertyName ?? htmlFieldName.Split(new char[] { '.' }).Last<string>()));
if (string.IsNullOrEmpty(text))
{
return MvcHtmlString.Empty;
}
var tagBuilder = new TagBuilder("label");
tagBuilder.Attributes.Add("for", TagBuilder.CreateSanitizedId(html.ViewContext.ViewData.TemplateInfo.GetFullHtmlFieldName(htmlFieldName)));
tagBuilder.InnerHtml = text;
return new HtmlString(tagBuilder.ToString(TagRenderMode.Normal));
}
}
and then use this custom helper in the view:
#Html.UnencodedLabelFor(x => x.IsLimitedQuantity)
Now the HTML tags in the display name will be rendered without encoding:
[Display(Name = "Check to enter <br/> the Quantity of items")]
public bool IsLimitedQuantity { get; set; }
Using Html decode may help. MVC for security reasons encode all the values.
How to display HTML stored in a database from an ASP.NET MVC view?
Related
I have a model say
public class Contact
{
[Display(Name = "Phone Number", Description = "This is Phone number to contact")]
[Visibility(ShowForDisplay=false)]
public string Phone { get; set; }
[Display(Name = "Mail To Support", Description = "This is Mail for support")]
public string Email { get; set; }
}
Now in Mvc html I m doing at several places like
#Html.DisplayTextFor(x=>x.Phone)
Now I want a attribute based something like this which can manage at model level for turning of this display into the view . Like for eg the #html.DisplayTextFor(x=>x.Phone) should be there but when I do [Visibility(ShowForDisplay=false)] then all the visibility for the values or texts should not be rendered on the html .
How can be done through attribute like custom attribute [Visibility(ShowForDisplay=false)] ?
All Html Helper methods working with Model MetaData, and you can't change ModelMetada class so you should make your own Html helper, and ofcourse you need a custom attribute. Check this code:
First create a custom attribute:
public class VisibilityAttribute : ValidationAttribute
{
private bool _isVisible;
public VisibilityAttribute(bool visible = true)
{
_isVisible = visible;
}
public bool ShowForDisplay
{
get
{
return _isVisible;
}
set
{
_isVisible = value;
}
}
}
Then create a Html helper:
public static class MyHtmlExtensions
{
public static MvcHtmlString DisplayTextForCustom<TModel, TResult>(this HtmlHelper<TModel> html,
Expression<Func<TModel, TResult>> expression)
{
ExpressionType type = expression.Body.NodeType;
if (type == ExpressionType.MemberAccess)
{
MemberExpression memberExpression = (MemberExpression) expression.Body;
PropertyInfo pi = memberExpression.Member as PropertyInfo;
var attributes = pi.GetCustomAttributes();
foreach (var attribute in attributes)
{
if (attribute is VisibilityAttribute)
{
VisibilityAttribute vi = attribute as VisibilityAttribute;
if (vi.ShowForDisplay)
{
var metadata = ModelMetadata.FromLambdaExpression<TModel, TResult>(expression, html.ViewData);
return MvcHtmlString.Create(metadata.SimpleDisplayText);
}
}
}
}
return MvcHtmlString.Create("");
}
}
Then call it from your View like this:
#Html.DisplayTextForCustom(x=>x.Phone)
PS: To write this code I looked at Html.DisplayTextFor source code and I try to write a code as simple as possible.
I have some Create views and some Index views for my models, but I want different labels (generated from data annotations).
E.g.
I want #Html.DisplayNameFor(model => model.Url) to print something like "Page URL" because this is the heading for my tables on the index page...
And I want #Html.LabelFor(modelItem => item.Url) to print something like "Enter page Url" because it is for the Create views.
I've tried looking through the annotations but the only property I can find seems to set both:
[DisplayName("Page Url")]
public string Url { get; set; }
Is there a way (other than directly typing into my view) to do what I want?
Use the Display attribute instead of DisplayName, like this:
[Display(Name = "Page Url", Description = "Enter page Url")]
public string Url { get; set; }
And, then, create this HtmlHelper:
public static MvcHtmlString DescriptionFor<TModel, TValue>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TValue>> expression)
{
var metadata = ModelMetadata.FromLambdaExpression(expression, htmlHelper.ViewData);
var description = metadata.Description;
TagBuilder tagBuilder = new TagBuilder("span");
tagBuilder.SetInnerText(description);
return new MvcHtmlString(tagBuilder.ToString(TagRenderMode.Normal));
}
And, use it in your Views like this (For the Description):
#Html.DescriptionFor(model => model.Url)
And, for the Name:
#Html.LabelFor(model => model.Url)
I have the following classes:
public class Note
{
public string Text { get; set; }
public RowInfo RowInfo { get; set; }
}
public class RowInfo
{
[DisplayName("Created")]
public DateTime Created { get; set; }
[DisplayName("Modified")]
public DateTime Modified { get; set; }
}
In my view I have the following which creates HTML with the correct name and value:
Html.HiddenFor(model => model.Note.Created)
Now what I am trying to do is to create an extension method that will include the above and that I can call in each view. I have tried doing the following. I think I am on the right track but I don't know how to do the equivalent of "model => model.Note.Created" Can someone give me some advice on how I can do this and what I would need to replace the text inside the parenthesis with. I don't have a model but I can do this some other way so the hidden field will go look at my class to get the correct DisplayName just like it does above?
namespace ST.WebUx.Helpers.Html
{
using System.Web.Mvc;
using System.Web.Mvc.Html
using System.Linq;
public static class StatusExtensions
{
public static MvcHtmlString StatusBox(this HtmlHelper helper, RowInfo RowInfo )
{
return new MvcHtmlString(
"Some things here ... " +
System.Web.Mvc.Html.InputExtensions.Hidden( for created field ) +
System.Web.Mvc.Html.InputExtensions.Hidden( for modified field ) );
}
}
You could write a strongly typed helper taking a λ-expression:
public static class StatusExtensions
{
public static IHtmlString StatusBox<TModel, TProperty>(
this HtmlHelper<TModel> helper,
Expression<Func<TModel, TProperty>> ex
)
{
return new HtmlString(
"Some things here ... " +
helper.HiddenFor(ex));
}
}
and then:
#Html.StatusBox(model => model.RowInfo.Created)
UPDATE:
As requested in the comments section here's a revised version of the helper:
public static class StatusExtensions
{
public static IHtmlString StatusBox<TModel>(
this HtmlHelper<TModel> helper,
Expression<Func<TModel, RowInfo>> ex
)
{
var createdEx =
Expression.Lambda<Func<TModel, DateTime>>(
Expression.Property(ex.Body, "Created"),
ex.Parameters
);
var modifiedEx =
Expression.Lambda<Func<TModel, DateTime>>(
Expression.Property(ex.Body, "Modified"),
ex.Parameters
);
return new HtmlString(
"Some things here ..." +
helper.HiddenFor(createdEx) +
helper.HiddenFor(modifiedEx)
);
}
}
and then:
#Html.StatusBox(model => model.RowInfo)
Needless to say that custom HTML helpers should be used to generate small portions of HTML. Complexity could grow quickly and in this case I would recommend you using an editor template for the RowInfo type.
I am working with legacy models that wrap data and meta-data up in a single property. For the purpose of this question, suppose the interface is:
pubic interface ILegacyCheckbox
{
bool Value { get; set; }
bool Editable { get; set; }
}
I want to wrap the CheckBoxFor() extension method with my own,
public static MvcHtmlString LegacyCheckboxFor<TModel>(
this HtmlHelper<TModel> html,
Expression<Func<TModel, ILegacyCheckbox>> expression)
{
// wrap html.CheckBoxFor() method here by extracting the Value
// property and check if Editable is false, in which case add
// an htmlAttribute of "disabled=true"
}
Is there a way to do something like this? Where would I start?
Any help would be appreciated,
Thanks,
Alex
You could try something like this:
public static MvcHtmlString LegacyCheckboxFor<TModel>(
this HtmlHelper<TModel> html,
Expression<Func<TModel, ILegacyCheckbox>> expression)
{
var parameterName = ((MemberExpression)expression.Body).Member.Name;
var compiled = expression.Compile().Invoke(html.ViewData.Model);
if (editable)
return html.CheckBox(parameterName, compiled.Value);
else
return html.CheckBox(parameterName, compiled.Value, new {disabled = "disabled"});
}
You may also wish to cache the compiled expression.
My example uses Html.CheckBox(); I'm not sure how to go about utilising CheckBoxFor(). I haven't got time to investigate it either, but atleast this is somewhere to start.
public static MvcHtmlString LegacyCheckboxFor<TModel>(
this HtmlHelper<TModel> html,
Expression<Func<TModel, ILegacyCheckbox>> expression)
{
MemberExpression memberExpression = expression.Body as MemberExpression;
string parameterName = memberExpression.Member.Name;
var checkbox = expression.Compile().Invoke(html.ViewData.Model);
return new MvcHtmlString(
string.Format(
"<input type=\"checkbox\" name=\"{0}\" id=\"{0}\" value=\"{1}\" {2} />",
parameterName,
checkbox.Value,
checkbox.Editable ? "disabled=true" : string.Empty));
}
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.