Using Html.BeginForm with querystring - asp.net-mvc

My url looks like this:
customer/login?ReturnUrl=home
In the login view, I have used this pattern of code which works fine.
#using(Html.BeginForm())
{
...
}
This magically generates following html
<form action="customer/login?ReturnUrl=home" method="post">
But now, I need to add an attribute (e.g., data-id="something") in the form. How can I do that? If I don't have any query string, I know I can do something like this:
#using(Html.BeginForm(action, controller, FormMethod.Post,
new { data_id="something" }))
But don't know how to add querystring which should be in html:
<form action="customer/login?ReturnUrl=home" method="post" data-id="something">
I thought about using <form> directly but don't know how to specify querystring which is variable. And I have no idea how to achieve it with Html.BeginForm. Any tip would be appreciated.
RESOLUTION:
For now, I used <form> with following hint How to get current url value in View. The resulting view looks like
<form action="#Request.Url.PathAndQuery" data-id="something" method="POST">
But it would be nice to have an overloaded method of BeginForm for this.

Here's The way that worked for me
Html.BeginForm("Profile", "Partner", routeValues: new {id=Partner.partner_id},method:FormMethod.Post)
It was almost like there was a problem with overloading the method, but by specifying what things are, it seems to work fine...

To create a RouteValueDictionary from the querystring:
RouteValueDictionary queryStringDictionary = new RouteValueDictionary(Request.QueryString.AllKeys.ToDictionary(key => key, key => (object)Request.QueryString[key]));
Then you can use it with Html.BeginForm:
Html.BeginForm(null, null, queryStringDictionary, FormMethod.Post, new Dictionary<string, object> { { "autocomplete", "off" } })

I guess this doesn't directly answer the question, but why not just use a plain old form tag?
<form action='customer/login?ReturnUrl=#Request.QueryString["ReturnUrl"]' method="post" data-id="something">
Alternatively, you can create a custom HtmlHelperExtension that renders a form with path and querystring. In this HtmlHelperExtension you can iterate through your querystring values and populate the routeValueDictionary which you then pass to a Html.BeginForm constructor.
If you don't want something so extensible you can just use the overloaded constructor of Html.BeginForm using
#Html.BeginForm("login", "customer", new {ReturnUrl = #Request.QueryString["ReturnUrl"]},FormMethod.Post, new {data-id="something"});

using Reflector to look at the code,
BeginForm() will pass directly the rawUrl over to the final Form.
Any other overloads on BeginForm will go through a helper utility which will strip the query string.

This works for me :
#using (Html.BeginForm("index", "Photos", routeValues: new { user = pUser, album = pAlbum, }, method: FormMethod.Get))
Explicit route values and method is what is required...

Just incase you wanted to add other attributes as well. use below code
#using (Html.BeginForm("actionName", "controllerName", routeValues: new { lang = "en" }, method:FormMethod.Post, htmlAttributes: new { #class= "my-form", enctype = "multipart/form-data" }))

Try #using(Html.BeginForm(null, null, FormMethod.Post, new { data_id="something" }))
It should use the default logic to construct the url, just as if you used BeginForm()
(never tried that though in such case, but I believe it should work)

Related

Html.BeginForm with overload causes form action to be '/cgi-bin?action=Index&controller=Home' and so the HomeController is bypassed

Because I wanted to assign an id to a form element my code was #using (Html.BeginForm(null, null, FormMethod.Post, new { id = "indexform"}))
This resulted in markup <form action="/cgi-bin?action=Index&controller=Home" id="indexform" method="post" style="position: relative;">
My HomeController ActionResult Index was completely bypassed.
Notice the '/cgi-bin'. This might be the problem and I think the culprit may be parameter 'FormMethod.Post' but I could not enter null there.
(BTW I worked around the id requirement by using jQuery var form = $("#btnShowProperty").closest("form");)
I did quite a bit of Googling on this with no luck.
The problem is you're passing null for the action and controller in the first two arguments. Instead, pass the name of your action and controller and it will work.
Example, if your action is "Index" and your controller is "Home", then use:
#using (Html.BeginForm("Index", "Home", FormMethod.Post, new { id = "indexform"})) {
...
}
The problem is mixing web pages and mvc especially using MapPageRoute AND MapRoute in Route.config. See full answer #Url.Action(“Action”, “Controller”) returns “/cgi-bin?action=Action&controller=Controller”

Html.BeginForm inside partial changes attributes

In my ASP.NET MVC (5.2) project, I have a page called register.cshtml. It doesn't include any forms or anything, just plain divs.
Inside one of the divs, I'm rendering a partial:
#Html.Partial("~/Views/Users/_x.cshtml").
Inside _x.cshtml I have a form:
#using (Html.BeginForm("/users/x"))
{
...
}
When I go to my register page, I expect my form to be rendered as:
<form action="/users/x" method="post"> ... </form>
But instead, I'm getting this:
<form action="/users/register?Length=23" method="post" novalidate="novalidate"> ... </form>
What is length=23, why is there a novalidate attribute added, and why is it posting to an incorrect path?
Why is my form not rendering properly?
If your wanting to post to a method named x in usersController, then it needs to be
#using (Html.BeginForm("x", "users"))
{
....
}
Note that your currently using the overload that accepts object routeValues and because its a string, the method generated a route value for Length because that's the only property of string (the /users/register is because that the method that generated the main view)
From your code
Html.BeginForm("/users/x")
i understand that users your controller and x is a method. So you can do in this way-
#using (Html.BeginForm("x", "users", FormMethod.Post, new { id = "YourFormID"}))
{
}
#using (Html.BeginForm("action", "controller",new { QueryString = 1}, FormMethod.Post, null))
{
}
Note : its due to passing wrong parameter in beginform constructor .
and in ur VIEW
#Html.Partial("~/Views/Shared/_x.cshtml")

ASP.NET MVC: Html Helper Form Seems to be Incorrect

all, I could use your help again. I'm currently attempting to use an HTML helper to create a from that will pass my model into the Operations controller's method, TaskEdit, seen below:
[HttpPost]
public ActionResult TaskEdit(TaskViewModel viewModel, bool? embedded)
{
// code
}
In the view, I am using the following Razor code to attempt to produce the form:
#using (Html.BeginForm("TaskEdit", "Operations", new { embedded = true, viewModel = Model }, FormMethod.Post, new { #class = "form-horizontal" }))
{
// form code
}
This didn't actually give me my instance of the model - it only passed the class back as if it were a static class. So I tried the following instead:
#using (Html.BeginForm("TaskEdit", "Operations", new { embedded = true, id = Model.TaskId }, FormMethod.Post, new { #class = "form-horizontal" }))
{
// form code
}
And the following form was produced (which confused me):
<form action="/<sitename>/Operations/TaskEdit/0?embedded=True" class="form-horizontal" method="post"> <!-- Form code --> </form>
Not only was I assuming that the form action would be more along the lines of "/<sitename>/Operations/TaskEdit?id=0&embedded=True", but when I try to submit the form, I get a server error about "No parameterless constructor defined for this object." Help?
A transcription from the comments:
The reason the URL results in /TaskEdit/0 is because of the way your routing is setup. You'll notice the route also defines an id which causes it to format it different than expected.
The best solution here is to use a strongly typed view:
1) Put your model on top of the view (#model TaskViewModel)
2) Remove the model parameter from your form
3) Use the built-in extensions to create form fields (Html.EditorFor(x => x.SomeField)) or use the field names if you're doing it manually: <input type="text" name="SomeField />
4) The model parameter in your controller's actionresult will now contain the form data

How can I name a form with Html.BeginForm()?

How do I give a name to a form in ASP.NET MVC using Html.BeginForm()? I want only the name, not the action or controller name because I want to post it through Javascript. I think it should be something like Html.BeginForm(id = "frm").
I tried the following:
Html.BeginForm(null,null,new{id="frm",name="frm})
Html.BeginForm(new{#id="frm",#name="frm})
But the above code produces output like this:
<form action="/Main/Index/Id?name=Id" method="post">
Html.BeginForm(null, null, FormMethod.Get, new { name = "frm", id = "frm" })
You'll need to catch the form submit with your JavaScript
Using MVC2, this is what worked for me:
<% using (Html.BeginForm("Index", "Home", null, FormMethod.Post, new {#id = "myForm", #name = "myForm"})) {%>
#HTML.BeginForm("Target-ViewName where you want to post the page","Controller Name",new {#name="Name of the Form", id="ID of the Form"})
{ //form here
}
Taken from this answer: How to pass in ID with Html.BeginForm()?
Can you not just do:
Html.BeginForm(new {#id="Id", #name="Id"});
It can pay to search SO for answers as I've found many things I want to ask have already been encountered.

asp.net mvc Html.ActionLink() keeping route value I don't want

I have the following ActionLink in my view
<%= Html.ActionLink("LinkText", "Action", "Controller"); %>
and it creates the following URL http://mywebsite.com/Controller/Action
Say I add an ID at the end like so: http://mywebsite.com/Controller/Action/53 and navigate to the page. On this page I have the markup I specified above. Now when I look at the URL it creates it looks like this:
http://mywebsite.com/Controller/Action/53 (notice the addition of the ID)
But I want it to remove the ID and look like it did originally, like this http://mywebsite.com/Controller/Action (notice no ID here)
Any ideas how I can fix this? I don't want to use hard coded URLs since my controller/actions may change.
The solution is to specify my own route values (the third parameter below)
<%= Html.ActionLink("LinkText", "Action", "Controller",
new { id=string.Empty }, null) %>
It sounds like you need to register a second "Action Only" route and use Html.RouteLink(). First register a route like this in you application start up:
routes.MapRoute("ActionOnly", "{controller}/{action}",
new { controller = "Home", action = "Index" } );
Then instead of ActionLink to create those links use:
Html.RouteLink("About","ActionOnly")
The problem is the built in methods take input from the URL you are currently on as well as what you supply. You could try this:
<%= Html.ActionLink("LinkText", "Action", "Controller", new { id = ""}) %>
That should manually wipe the id parameter.
Don't know why, but it didn't work for me (maybe because of Mvc2 RC). Created urlhelper method =>
public static string
WithoutRouteValues(this UrlHelper helper, ActionResult action,params string[] routeValues)
{
var rv = helper.RequestContext.RouteData.Values;
var ignoredValues = rv.Where(x=>routeValues.Any(z => z == x.Key)).ToList();
foreach (var ignoredValue in ignoredValues)
rv.Remove(ignoredValue.Key);
var res = helper.Action(action);
foreach (var ignoredValue in ignoredValues)
rv.Add(ignoredValue.Key, ignoredValue.Value);
return res;
}
If you either don't know what values need to be explicitly overridden or you just want to avoid the extra list of parameters you can use an extension method like the below.
View
The implementation details are in this blog post
I explicitly set the action name as "Action/". Seems a little like a hack but it's a quick fix.
#Html.ActionLink("Link Name", "Action/", "Controller")
Another way is to use ActionLink(HtmlHelper, String, String, RouteValueDictionary) overload, then there are no need to put null in the last parameter
<%= Html.ActionLink("Details", "Details", "Product", new RouteValueDictionary(new { id=item.ID })) %>
The overloads of Html.ActionLink are changed on the later versions of MVC. On MVC 5 and above. This is how to do this:
#Html.ActionLink("LinkText", "Action", "Controller", new { id = "" }, null)
Note I passed "" for id parameter and null for HTMLATTRIBUTES.
I needed my menu links to be dynamic. Rather than implement a lot of extra code and routing for every single page I simple dispensed with the HTML helper.
#item.MenuItemName

Resources