Convert ActionLink to T4MVC ActionLink - asp.net-mvc

Probably it should be very easy but I am not sure that I did it correctly, so I want to ask you how to convert the code below to T4MVC syntax:
#Html.ActionLink("Log in", "Login", "Account", routeValues: null, htmlAttributes: new {id = "loginLink"})
I tried to do this code and it works fine but I am not sure I did it 100% correct.
#Html.ActionLink("Log in", MVC.Account.Login(null, null), htmlAttributes: new { id = "loginLink" })
The Login method signature is:
public virtual async Task<ActionResult> Login(LoginViewModel model, string returnUrl)
Thanks in advance.

Based on this example:
#Html.ActionLink("Delete Dinner", "Delete", "Dinners", new { id = Model.DinnerID }, null)
being transformed into this:
#Html.ActionLink("Delete Dinner", MVC.Dinners.Delete(Model.DinnerID))
Your implementation of ActionLink using T4MVC seems correct.
You include your link text - Log in
You include your Controller - Account
You include your Action Name/Method with parameters - Login(null, null)
The only thing that I can't find is the correct way to implement htmlAttributes but I was able to find this example. You might not even need to put htmlAttributes: new { id = "loginLink" }.. instead just try new { id = "loginLink" } and take out the htmlAttributes.
I hope this helps!

Related

Wrong parameter in Query ActionLink MVC [duplicate]

I'm VERY confused as to why this code
Html.ActionLink("About", "About", "Home", new { hidefocus = "hidefocus" })
results in this link:
<a hidefocus="hidefocus" href="/Home/About?Length=4">About</a>
The hidefocus part is what I was aiming to achieve, but where does the ?Length=4 come from?
The Length=4 is coming from an attempt to serialize a string object. Your code is running this ActionLink method:
public static string ActionLink(this HtmlHelper htmlHelper, string linkText, string actionName, object routeValues, object htmlAttributes)
This takes a string object "Home" for routeValues, which the MVC plumbing searches for public properties turning them into route values. In the case of a string object, the only public property is Length, and since there will be no routes defined with a Length parameter it appends the property name and value as a query string parameter. You'll probably find if you run this from a page not on HomeController it will throw an error about a missing About action method. Try using the following:
Html.ActionLink("About", "About", new { controller = "Home" }, new { hidefocus = "hidefocus" })
The way I solved this is was adding a null to the fourth parameter before the anonymous declaration (new {}) so that it uses the following method overload: (linkText, actionName, controllerName, routeValues, htmlAttributes):
Html.ActionLink("About", "About", "Home", null, new { hidefocus = "hidefocus" })
You forgot to add the HTMLAttributes parm.
This will work without any changes:
Html.ActionLink("About", "About", "Home", new { hidefocus = "hidefocus" },null)
The parameters to ActionLink are not correct, it's attempting to use the "Home" value as a route value, instead of the anonymous type.
I believe you just need to add new { } or null as the last parameter.
EDIT: Just re-read the post and realized you'll likely want to specify null as the second last parameter, not the last.
Html.ActionLink("About", "About", "Home", new { hidefocus = "hidefocus" }, new { })
This will take the overload:
string linkText, string actionName, string controllerName, Object routeValues, Object htmlAttributes
Just remove "Home" (name of the controller) so that the code would be:
Html.ActionLink("About", "About", new { hidefocus = "hidefocus" })
Kindly use right overloaded method with five (5) parameters. Example:
#using (#Ajax.BeginForm("Register", "Account", null,
new AjaxOptions
{
HttpMethod = "POST",
OnSuccess = "OnSuccess",
OnFailure = "OnFailure",
OnBegin = "OnBegin",
OnComplete = "OnComplete"
}, new { #class = "form-login" }))
This worked fine
#Html.ActionLink("Informationen", "About", "Home", new { area = "" }, new { #class = "nav-link" })
added new { area = "" }.
As Jonathon Watney pointed out in a comment, this also goes for
Html.BeginForm()
methods. In my case, I was in a Create.cshtml targeting the post request of the corresponding controller + Create action and had
using (Html.BeginForm("Create")) {
#Html.AntiForgeryToken()
...
}
which was adding the querystring "?Length=6" to the form action when rendered. Hinted by roryf's approved answer and realizing the string length of "Create" is 6, I finally solved this by removing the explicit action specification:
using (Html.BeginForm()) {
#Html.AntiForgeryToken()
...
}
With attribute names:
#Html.ActionLink(linkText: "SomeText", actionName: "SomeAction", controllerName: "SomeControllerName", routeValues: new { parameterName = parameterValue}, htmlAttributes: null)
Perhaps others had the same issue and need to supply a class value via HTMLAttributes parm.
Here's my solution:
#Html.ActionLink("About", "About", new { controller = "Home", area = "" }, new { hidefocus = "hidefocus", #class = "nav-item nav-link" })
Search for an answer to my question landed me here, basically it's the selection of correct overload of #Html.ActionLink
which matters.
I was selecting an overload which didn't exist, (without the last null), and MVC had no such overload, resulting in a false URL something like the OP mentioned.
A personal note: you can use anonymous types doesn't mean you can use any of the overloads- which do not exist? - make certain: it has to be defined!
- Came here in times of MVC 5.2

Attribute routing number of parameters with 404 not found

I use AttributeRouting to set specific route for my ActionResult. I got an 404 page not found when I have this configuration:
[GET("Tender/SubmitBid/{id}/{bidId}")]
public ActionResult SubmitBid(string id, string bidId)
{
...
return View(model);
}
#using ("SubmitBid", "Tender", new { id = Model.TenderId, bidId = Model.BidId }, FormMethod.Post, new { enctype = "multipart/form-data" }))
{
...
<button type="submit">Save</button>
}
// 404 not found
[HttpPost]
public ActionResult SubmitBid(BidViewModel model)
{
...
}
I installed a url sniffer to see the url trigger the 404 page not found and I got this: http.../Tender/SubmitBid/1/0
It supposed to be working... but I have to remove the latest parameters to reach the ActionResult and I don't know why.
Thank you for your help,
Karine
Edit
If I remove the attribute [GET("Tender/SubmitBid/{id}/{bidId}")] the page is accessible for the POST request. But the url is like http...//Tender/SubmitBid/1?bidId=0
You should not need the query string parameters since they exist in the BidViewModel you post. The point of a POST request is that you don't have query string parameters.
I think you have to use this overload of the Html.BeginForm method:
#using (Html.BeginForm("SubmitBid", "Tender", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
#Html.HiddenFor(model => model.Id)
#Html.HiddenFor(model => model.BidId)
// Other properties..
<button type="submit">Save</button>
}
Now it will post to http:localhost/Tender/SubmitBid with the properties of BidViewModel as post values, which contain Id and BidId. The signature of the POST action can stay the same:
[HttpPost]
public ActionResult SubmitBid(BidViewModel model)
{
string id = model.Id;
string bidId = model.bidId;
// ...
}
It's also possible that AttributeRouting causes this issue. Can you try this with native ASP.NET MVC routing? You could use this specific route for submitting bids:
routes.MapRoute(
name: "SubmitBid",
url: "Tender/SubmitBid/{id}/{bidId}/",
defaults: new
{
controller = "Tender",
action = "SubmitBid",
id = UrlParameter.Optional,
bidId = UrlParameter.Optional
});

Passing multiple parameters to a controller

I have a situation where I need to pass two parameters to an action. I've been passing parameters to actions using the code below but I don't see how I pass multiple parameters. How do I do this?
#Html.ActionLink("Add Visit", "Create", "Visit", new { id = Model.Id }, null)
BTW - ASP.NET MVC 4 RC
You should separate the parameters with comma, like this:
#Html.ActionLink("Add Visit", "Create", "Visit",
new { id = Model.Id, secondParameter = Model.yourValue }, null)
Check the MSDN documentation for the ActionLink method.
Hope it helps!
I add from CodePlex called T4MVC.
This turns all your strings into a method call by using a combination of T4 templates and partial classes.
It will allow you to turn your ActionLink methods into a syntax checked method call.
#Html.ActionLink("Add Visit", "Create", "Visit", new { id = Model.Id }, null)
would be turned into
#Html.ActionLink("Add Visit", MVC.Visit.Create(Model.Id))
and
#Html.ActionLink("Add Visit", "Create", "Visit", new { id = Model.Id, Param2 = "Param2", Param3= "Param3Value" }, null)
#Html.ActionLink("Add Visit", MVC.Visit.Create(Model.Id, "Param2", "Param3Value"))
Its a life saver when you turn on compiled views.

Passing parameter to controller action from a Html.ActionLink

Is there anything wrong with this html? I want to have a link in the masterpage to navigate to "CreateParts" view. I have action 'CreateParts' which have a parameter parentPartId in the controller 'PartList'.
<li id="taskAdminPartCreate" runat="server">
<%= Html.ActionLink("Create New Part", "CreateParts", "PartList", new { parentPartId = 0 })%></li>
My controller action is like
public ActionResult CreateParts(int parentPartId)
{
HSPartList objHSPart = new HSPartList();
objHSPart.Id = parentPartId;
return View(objHSPart);
}
When I click on 'Create New Part' in the menu in SiteMaster, I get exception. Please help me out of this.
You are using incorrect overload. You should use this overload
public static MvcHtmlString ActionLink(
this HtmlHelper htmlHelper,
string linkText,
string actionName,
string controllerName,
Object routeValues,
Object htmlAttributes
)
And the correct code would be
<%= Html.ActionLink("Create New Part", "CreateParts", "PartList", new { parentPartId = 0 }, null)%>
Note that extra parameter at the end.
For the other overloads, visit LinkExtensions.ActionLink Method. As you can see there is no string, string, string, object overload that you are trying to use.
You are using the incorrect overload of ActionLink. Try this
<%= Html.ActionLink("Create New Part", "CreateParts", "PartList", new { parentPartId = 0 }, null)%>
Addition to the accepted answer:
if you are going to use
#Html.ActionLink("LinkName", "ActionName", "ControllerName", new { #id = idValue, #secondParam= = 2 },null)
this will create actionlink where you can't create new custom attribute or style for the link.
However, the 4th parameter in ActionLink extension will solve that problem. Use the 4th parameter for customization in your way.
#Html.ActionLink("LinkName", "ActionName", "ControllerName", new { #id = idValue, #secondParam= = 2 }, new { #class = "btn btn-info", #target = "_blank" })

Why does Html.ActionLink render "?Length=4"

I'm VERY confused as to why this code
Html.ActionLink("About", "About", "Home", new { hidefocus = "hidefocus" })
results in this link:
<a hidefocus="hidefocus" href="/Home/About?Length=4">About</a>
The hidefocus part is what I was aiming to achieve, but where does the ?Length=4 come from?
The Length=4 is coming from an attempt to serialize a string object. Your code is running this ActionLink method:
public static string ActionLink(this HtmlHelper htmlHelper, string linkText, string actionName, object routeValues, object htmlAttributes)
This takes a string object "Home" for routeValues, which the MVC plumbing searches for public properties turning them into route values. In the case of a string object, the only public property is Length, and since there will be no routes defined with a Length parameter it appends the property name and value as a query string parameter. You'll probably find if you run this from a page not on HomeController it will throw an error about a missing About action method. Try using the following:
Html.ActionLink("About", "About", new { controller = "Home" }, new { hidefocus = "hidefocus" })
The way I solved this is was adding a null to the fourth parameter before the anonymous declaration (new {}) so that it uses the following method overload: (linkText, actionName, controllerName, routeValues, htmlAttributes):
Html.ActionLink("About", "About", "Home", null, new { hidefocus = "hidefocus" })
You forgot to add the HTMLAttributes parm.
This will work without any changes:
Html.ActionLink("About", "About", "Home", new { hidefocus = "hidefocus" },null)
The parameters to ActionLink are not correct, it's attempting to use the "Home" value as a route value, instead of the anonymous type.
I believe you just need to add new { } or null as the last parameter.
EDIT: Just re-read the post and realized you'll likely want to specify null as the second last parameter, not the last.
Html.ActionLink("About", "About", "Home", new { hidefocus = "hidefocus" }, new { })
This will take the overload:
string linkText, string actionName, string controllerName, Object routeValues, Object htmlAttributes
Just remove "Home" (name of the controller) so that the code would be:
Html.ActionLink("About", "About", new { hidefocus = "hidefocus" })
Kindly use right overloaded method with five (5) parameters. Example:
#using (#Ajax.BeginForm("Register", "Account", null,
new AjaxOptions
{
HttpMethod = "POST",
OnSuccess = "OnSuccess",
OnFailure = "OnFailure",
OnBegin = "OnBegin",
OnComplete = "OnComplete"
}, new { #class = "form-login" }))
This worked fine
#Html.ActionLink("Informationen", "About", "Home", new { area = "" }, new { #class = "nav-link" })
added new { area = "" }.
As Jonathon Watney pointed out in a comment, this also goes for
Html.BeginForm()
methods. In my case, I was in a Create.cshtml targeting the post request of the corresponding controller + Create action and had
using (Html.BeginForm("Create")) {
#Html.AntiForgeryToken()
...
}
which was adding the querystring "?Length=6" to the form action when rendered. Hinted by roryf's approved answer and realizing the string length of "Create" is 6, I finally solved this by removing the explicit action specification:
using (Html.BeginForm()) {
#Html.AntiForgeryToken()
...
}
With attribute names:
#Html.ActionLink(linkText: "SomeText", actionName: "SomeAction", controllerName: "SomeControllerName", routeValues: new { parameterName = parameterValue}, htmlAttributes: null)
Perhaps others had the same issue and need to supply a class value via HTMLAttributes parm.
Here's my solution:
#Html.ActionLink("About", "About", new { controller = "Home", area = "" }, new { hidefocus = "hidefocus", #class = "nav-item nav-link" })
Search for an answer to my question landed me here, basically it's the selection of correct overload of #Html.ActionLink
which matters.
I was selecting an overload which didn't exist, (without the last null), and MVC had no such overload, resulting in a false URL something like the OP mentioned.
A personal note: you can use anonymous types doesn't mean you can use any of the overloads- which do not exist? - make certain: it has to be defined!
- Came here in times of MVC 5.2

Resources