How to specify a property with - in the name - c#

I am using ASP.NET MVC along with JQueryMobile in a web app. I want to generate a link:
Previous
I have a helper extension method that lets me do:
<%= Html.ActionLink<WhateverController>(c => c.Previous(),
"Previous",
new { data-role = "button", data-icon="arrow-l" } ) %>
Except data-role and data-icon are not valid as property names in C#. Using #data-role doesn't work either.
Is there any syntax to work around this? Or am I stuck with creating a more specialized helper that knows the correct attribute names.

You should be able to use IDictionary<string, object> instead of the anonymous object:
Html.ActionLink<WhateverController>(c => c.Previous(),
"Previous",
new Dictionary<string, object>
{
{ "data-role", "button" },
{ "data-icon", "arrow-l"}
})

In addition to svick's response, we made a neat change in ASP.NET MVC 3 where properties that have an underscore in them will automatically have the underscores converted to dashes.
So, if you have code like this:
<%= Html.ActionLink<WhateverController>(c => c.Previous(),
"Previous",
new { data_role = "button", data_icon="arrow-l") %>
It will render the markup with dashes:
Previous

Because that character is also the subtraction/unary minus operator you can't use it in an identifier. I think the custom helper method is probably your best bet.

Related

How to pass routeValues that contains hyphen via actionlink in asp.net mvc 5

I have an actionlink in view, I need it to pass parameter containing hyphen (-). Changing the name convention is not possible. How do I do this?
<li>#Html.ActionLink("abc", "abc", "abc", new { area = "",sap-ie="Edge" }, new { id = nav_abc"})</li>
This one gives me an error "Invalid Anonymous Type Declarator" since it contains hyphen. Basically I need the actionlink to generate html like below.
<a href=".../abc?sap-ie=Edge" id="nav_abc" >abc</a>
If you are sure the url won't change much from the structure you've specified you could use an anchor tag and build the url from Url.Action.
<a href='#Url.Action("abc", "abc")?sap-ie=Edge'>abc</a>
The whole point of htmlhelpers are to help generate html anyway .. so if its getting in the way, you can drop down to html proper and just get it done.
Just wanted to point out that it's not that the underscore trick only works with data attributes, it's that it only works with passing HTML attributes in general. This is because it makes sense to change underscores to hyphens in the context of HTML, as underscores aren't use in HTML attributes. However, it's perfectly valid for you to have a route param with an underscore, so the framework can make no assumptions about your intent.
If you need to pass route values with hyphens, you have to use a RouteValueDictionary. This is simply a limitation of anonymous objects that can't be overcome.
<li>#Html.ActionLink("abc", "abc", "abc", new RouteValueDictionary { { "area", "" }, "sap-ie", "Edge" } }, new RouteValueDictionary { { "id", "nav_abc" } })</li>
Unfortunately, there's no ActionLink overload that accepts both a RouteValueDictionary for routeValues and an anonymous object for htmlAttributes, so switching one means switching both. You can technically use any IDictionary implementation for the htmlAttributes param, so you may prefer to use just new Dictionary { { "id", "nav_abc" } }. It's up to you.
Have you tried using this overload of the ActionLink method?
#{
var routeValues = new RouteValueDictionary();
routeValues.Add("sap-ie", "Edge");
routeValues.Add("area", "");
var attributes = new Dictionary<string, object>();
attributes.Add("Id", "nav_abc");
}
#Html.ActionLink("Go to contact page", "Contact", routeValues, attributes)

Pass model property to Html.ActionLink

Edit: I found the answer, but it meant abandoning the use of HtmlActionlink in favor of doing this (the "blah" parameters from my original post now being subbed in for what I actually needed):
<a href="#Url.Action("LinkedDetails",
new
{
controller = "LGDetails",
findByString = item.AccounNumber
})">#item.LastName</a>
This does exactly what I want. Trying to accomplish the same thing with HtmlActionLink results in one error or another no matter what I tried:
#Html.ActionLink(item.LastName,
"../LGDetails/LinkedDetails",
new
{
controller = "LinkedDetails",
findByString = item.AccounNumber
})
result: Value cannot be null or empty.
Parameter name: linkText
Trying like this:
#Html.ActionLink(Model.LastName .....
Result:
System.Collections.Generic.IEnumerable' does not contain a definition for 'LastName' and no extension method 'LastName' accepting a first argument of type 'System.Collections.Generic.IEnumerable' could be found (are you missing a using directive or an assembly reference?)
etc etc. Always one of those errors regardless.
And yes, I tried every single thing suggested here, and an equal number of other things found elsewhere (which is how I found the answer I did use, it was posted by another person having the same problem).
Despite a lot of searching, I can't seem to figure out how to do what seems like it should be basic.
This works fine:
#Html.DisplayFor(modelItem => item.LastName)
But I want to display the LastName field as the linked text inside an Html.ActionLink like this:
#Html.ActionLink(item.LastName, "blah", "blah")
But nothing works. Doing it like the above gives me a compilation error:
The type arguments for method
'System.Web.Mvc.Html.DisplayExtensions.DisplayFor(System.Web.Mvc.HtmlHelper,
System.Linq.Expressions.Expression>)'
cannot be inferred from the usage. Try specifying the type arguments
explicitly
I've tried it like this:
#Html.ActionLink(#Html.DisplayFor(modelItem => item.LastName), "blah", "blah")
and other variations thereof where it is nested. That doesn't work either (won't compile) with the error "no overload method for actionlink.."
I feel like this should be simple. Yes, I'm very new to C# and MVC.
you need to use this overload of Html.ActionLink:
#Html.ActionLink(string LinkText,string ActionName,string ControllerName)
do like this:
#Html.ActionLink(Model.LastName, "ActionName","ControllerName")
Updated:
then do like this, as your Model is IEnumerable:
#foreach(var item in Model)
{
#Html.ActionLink(item.LastName, "ActionName","ControllerName")
}
If Model is Single like this:
#model MyCompany.LGCustData
then it should be lke this:
#Html.ActionLink(Model.LastName, "ActionName","ControllerName")
#Html.ActionLink(#Model.AccounNumber....) works in case someone ends up here just like me.
this is a breaf description of how you should use an actionlink
Html.ActionLink("link title",
"ActionMethod",
"ControllerName",
null, // <-- Route arguments.
null // <-- htmlArguments
)
try something like this:
#Html.DisplayFor(Model.LastName, "actionMethod","controllerName",new{Model.LastName});
*if the case you want to add some parameters to your route, following the standard convention:
/controller/action/parameter
otherwise
#Html.DisplayFor(Model.LastName, "actionMethod","controllerName");
For me I simply convert the "dynamic text" before in a string with String.Format() function like this
<ul>
#foreach (var user in ViewBag.users )
{
string complete_name = String.Format("{0} {1}", user.Firstname, user.Lastname);
<li>#Html.ActionLink(complete_name, "Details", new { Id = user.Id })</li>
}
</ul>
On my computer it works very fine.
Just use
#Html.ActionLink(Html.DisplayNameFor(model => model.LastName).ToHtmlString(), "blah", "blah")

Need help to understand this piece of code in MVCContrib Grid

I'm a bit new to the concept of "Action" in C# and delegate in general.
I'm trying to study how to build a custom html component in MVC, and I chose the grid component of MVCContrib to start.
To add columns, typically we do
<%= Html.Grid(Model).Columns(column =>
{
column.For(model => model.Date).Format("{0:d}");
column.For(model => model.DayAmount);
column.For(model => model.LeaveType);
})
%>
and I see the source of Columns like the following
public IGridWithOptions<T> Columns(Action<ColumnBuilder<T>> columnBuilder)
{
var builder = new ColumnBuilder<T>();
columnBuilder(builder);
foreach (var column in builder)
{
if (column.Position == null)
{
_gridModel.Columns.Add(column);
}
else
{
_gridModel.Columns.Insert(column.Position.Value, column);
}
}
return this;
}
What I'm confused of is the Action parameter In this instance, Type is CustomBuilder, so when did the "CustomBuilder" object got instantiated?
I suppose, i can rewrite the calling statement above as
Html.Grid(Model).Columns(delegate(CustomBuilder<T> column)
{
});
or a bit more explicit as
Html.Grid(Model).Columns(new Action<CustomBuilder<T>>(delegate(CustomBuilder<T> column)
{
});
);
So are we saying, when the Action was instantiated with the "new" keyword above, the param "CustomBuilder" was instantiated as well?
Lastly, in the
"public IGridWithOptions<T> Columns(Action<ColumnBuilder<T>> columnBuilder)"
function,
the first two lines are
var builder = new ColumnBuilder<T>();
columnBuilder(builder);
What do they do? Looks like it's instantiating ColumBuilder object and pass it as a parameter to Action method columBuilder. Is this where you instantiate the parameter?
Thank you all.
It's nothing to do with action concept.
The delegates is present in .net from the beginning so you should start with the first step. Should build the wall before the roof.
Delegates
Lambda Expressions
Expression trees
But you should know about generic classes and methods, extension methods...
Got it after read this excellent article.
http://www.codeproject.com/Articles/47887/C-Delegates-Anonymous-Methods-and-Lambda-Expressio
while it's talking about Func, the concept applies to Action, which does not return any results.
Looks like the magic happens here
var builder = new ColumnBuilder();
columnBuilder(builder);
I obviously didn't understand the fact that delegate, is just a pointer to a function (anonymous or not). You still need to supply the parameter when calling it. (Duh!).
All cleared up now.
Thank you.

Html.ActionLink with non-C# friendly htmlAttribute names

Disqus wants me to add an attribute called data-disqus-identifier to my links, but for obvious reasons, new { #data-disqus-identifier = "article" } gives me a syntax error.
Any idea what to do in these situations?
Thanks,
Rei
You can pass a Dictionary<string, object> with arbitrary string keys.
The syntax will be more verbose: new Dictionary<string, object> { { "data-disqus-identifier", "article" } }.
You may want to create an extension method or a static method on a static class with a short name that takes a smaller parameter set and returns the dictionary.
In MVC 3, if you use underscore _ instead of hyphens - in your property names then MVC will automatically convert them to hyphens in the resulting HTML. So, something like this should work for you:
new { data_disqus_identifier = "article" }

MVC - Changing or adding a class for either 'Html.ValidationMessage' or 'Html.TextBox'

How do I change the class that is assigned to the control which is rendered by an MVC view by either the Html.TextBox or Html.ValidationMessage methods?
You would do something like this (not that you have to escape "class" with # because it's a reserved C# keyword):
Html.TextBox("Text", "Value", new { #class = "YourClassName" })
or if you don't like anonymous types:
Html.TextBox("Text", "Value", new Dictionary() { { "class", "YourClassName" } } )
It doesn't look like you can. It's defined as readonly in HtmlHelpers.cs. You could, of course, change the css. Or, make your own helper that names it what you want.

Categories

Resources