I am using a Html.TextBoxFor helper in an MVC4 project. Our web designer used a custom property of "error-type" for his box that jquery/javascript looks at to determine how an error should be rendered for that textbox.
I tried doing something like:
#Html.TextBoxFor(m => m.SomeValue, new { error-type="blue" });
But C# doesn't like the property name of "error-type".
Is there a way to be able to use the custom property when rendering it through Razor?
Use an underscore; the helper will convert attribute names containing underscores to dashes. FYI, I believe this will only work with MVC-3 or later.
An alternate route is to use the overload that accepts an IDictionary<string, object> of HTML attributes. That will be both forwards and backwards compatible.
#Html.TextBoxFor(m => m.SomeValue, new Dictionary<string, object>{{"error-type", "blue"}})
Related
I'm learning ASP.NET MVC, and I have some problems, I would like to know what's the advantage of using Html.ActionLink() method instead of a normal Anchor tag, I don't see any obvious advantage yet, mostlyu because I have more problems using ASP's built-in method. Something else I would like to know, is how to add various attributes to Html.ActionLink(), I'm using this:
#Html.ActionLink("About", "About", "Home", new{ area="" }, new Dictionary<string, Object>{ { "class", "about-link" }, { "aria-role", "button" }, { "title", "About us..." } })
I found this in StackOverflow, but it just doesn't work, and I've been trying many things, but nothing.
This is the method signature of most likely interest to you:
public static MvcHtmlString ActionLink(
this HtmlHelper htmlHelper,
string linkText,
string actionName,
string controllerName,
object routeValues,
object htmlAttributes
)
For your instance, that would result in the following code:
#Html.ActionLink("About", "About", "Home", new { area = "" }, new { #class = "about-link", aria_role = "button", title = "About us..." })
A few things to note:
The first anonymous object is for route values, and the second anonymous object is for HTML attributes to apply to the anchor tag.
Since class is reserved keyword, you must prefix it with # inside anonymous objects. It will still be output as class on the anchor tag.
Similarly, aria-role is invalid C# syntax, so you have to use an underscore instead of a dash: aria_role. The built-in HtmlHelper extensions that accept htmlAttributes process the _ and turn it into a - when rendering the HTML.
Now, in terms of why you want to use this in the first place, #Christos points out correctly that by letting MVC construct the URL, your links continue to work even if your routing changes, while if you hardcoded the URL, it would fail. However, he misses the point that this doesn't require using Html.ActionLink. You can just as easily do something like the following:
<a href="#Url.Action("About", "Home", new { area = "" })" class="about-link" aria-role="button" title="About us...">
About
</a>
This is especially handy when you need something inside the link other than just straight text, like an icon, perhaps. If you find it easier to work directly with the HTML attributes, then you can do that. There's nothing wrong with this and you don't have to use Html.ActionLink. However, do still use Url.Action or one of its siblings, so that your URLs are constructed dynamically based on your route configuration.
The basic advantage of using #Html.ActionLink for creating a link instead of using an anchor element is the fact that the output is derived from the routing configuration. That means if you change something in the routes, automatically this change would be reflected to the links you have created using this helper.
Here you will find a detailed list with all the signatures of this method.
Most of the Html helpers available in ASP.Net MVC have overloads with object htmlAttributes. This is used to provide additional attribute values for the outputted tags. One common usage for these htmlAttributes is to output css class names.
So for example lets take the following example:
#Html.TextBox("Title", string.Empty, new { class="css-class-name" })
Here we are trying to create a textbox with class i.e. class="css-class-name".
Try the above code in your view and visual studio would show you an error saying "Expression Expected".
So the question is, how to provide htmlAttributes with their keys made up of c# reserved keywords like "class"?
Prefix your key name, madeup of reserved keyword, with an at-the-rate symbol # (like below example):
#Html.TextBox("Title", string.Empty, new { #class="css-class-name" })
Note: it is bad practice to use reserved keywords as variable or property names but sometimes you just have to use them (for e.g. the case of css "class" mentioned in the question)
I'm struggling with the following problem and I can't find an acceptable way to solve it.
My challenge: write out HTML comments just before the actual property value in a Razor view.
This is my (simplyfied) Viewmodel:
public class Article
{
public string Title {get;set;}
}
To write out this title I simply do this in my Razor view:
<h2>#Model.Title</h2>
Now I want to write out a html comment just before the actual title so the generated HTML looks like this (simplyfied):
<h2><!-- some parameters for a 3th party system --> This is my title</h2>
The HTML comment comes from an Attribute I applied to the 'Title' attribute. It's value is generated, so the attribute-value is added at runtime using the TypeDescriptor from the .NET framework.
Now I know I could achieve this by simply writing out all my properties using an HTML helper. Like this: #MyHelper.Write(m => m.Title)
But since potentially ALL my properties need this HTML comment I want to avoid the use of an HTML helper since it clutters the View and doesn't make the view look nice and (more) readable.
This is what I have tried:
Created a custom Razor base page (Inheriting from WebViewPage<TModel>). And overwriting it's 'Write' method.
This kind of works but the BIGGEST problem here is that I don't know which property is been written out at that moment. There is no way of getting the current property name in the 'Write' method. So now I dynamically search my Model to find a property with the value that's been written out and prepend the HTML comment from the attribute.
My question: is there another approach to accomplish what I want. As sais before: I want to avoid using an HTML helper to write out all my properties. (Think about loops, etc. It's just not nice).
Also, adding this HTML comment in my Controller is no option since:
it's not part of the actual value. Is a sort of metadata.
The HTML comment should be added to int's, double's and DateTime's. There is no way to adjust a double property to include a string. (Image a List<DateTime>. All date's need this HTML comment)
the HTML comment should be added based on a web.config setting. Yes or No. (The actual HTML comment is different for each value of a property)
I realize this question is rather long. Sorry for that. Any thoughts are appreciated.
You can use the existing #Html.Raw(Model.Title)
Alternatively you can use a display templates. Add a UIHintAttribute to the properties you wish to behave this way.
public class MyModel
{
[UIHint("Raw")]
public string MyString { get; set; }
}
Create a new display template called Raw.cshtml that accepts model of type string:
#model string
#Html.Raw(model)
Then in your view you can use:
#Html.DisplayFor(m => m.MyString)
This still requires that you use a helper (DisplayFor). This is a recommended practice that allows you to easily change the behavior of one or many fields with minimal code changes.
I am using an MVC3 WebGrid, and want to add custom attributes of the form "data-xxx" to the <table> element rendered by WebGrid.GetHtml().
I tried to do this as follows:
grid.GetHtml(...
htmlAttributes: new { data_xxx = "value" }
);
However this renders as:
<table ... data_xxx="value">
instead of the expected:
<table ... data-xxx="value">
I.e. unlike other MVC helpers, it doesn't replace the underscore in the property name with a hyphen.
After a bit of spelunking with Reflector it seems that:
WebGrid.GetHtml() calls System.Web.WebPages.Html.ObjectToDictionary to convert the anonymous attributes object to a dictionary. Unlike the method System.Web.Mvc.HtmlHelper.AnonymousObjectToHtmlAttributes used by other helpers, this doesn't replace "_" by "-".
Unlike most other MVC helpers, WebGrid.GetHtml() does not have an overload that takes an IDictionary<string, object>, so I can't work around the bug by specifying the attributes in this way.
This looks like a bug to me, and I've submitted it to Connect:
http://connect.microsoft.com/VisualStudio/feedback/details/767456/webgrid-gethtml-helper-does-not-allow-data-attributes-to-be-set
Any suggestions for a workaround? Or is it fixed in MVC4?
Thanks for reporting this issue:
This was fixed yesterday in CodePlex by resolving issues 610 & 575.
https://aspnetwebstack.codeplex.com/workitem/610
https://aspnetwebstack.codeplex.com/workitem/575
You can try out the nightly bits.
Just wondering how do I mimic the following using attributes...
<%= Html.EditorFor(x => x.SportProgramIdList, "FormMultiSelectDropDownList", "SportProgramIds")%>
I know I can specify the template by using [UIHint("FormMultiSelectDropDownList")] but I am left with the problem with how to set the name...
Cheers
Anthony
I Guess you'll have to create your own CustomAttribute UINameAttribute.
You could use the ModelMetadata to keep your attribute and then I'm not sure what would be the best way to get it, i guess you would have to overide the HtmlHelper.EditorFor Extension without the parameter and pass your attribute to the next.
I'm too lazy and to tired to try for a more complete answer.
look at :
Why You Don't Need ModelMetadata.Attributes
ASP.NET MVC 2 Templates, Part 2: ModelMetadata
Use the objectAttributes argument
<%= Html.EditorFor(x => x.SportProgramIdList, "FormMultiSelectDropDownList", new { id="SportProgramIds" }) %>>
you can use this to set any of the html input attributes