Including All querystring parameters in Html.ActionLink - c#

In my page i have
#using (Html.BeginForm("list", "menu", FormMethod.Get))
{
<div>
Show categories:
#Html.DropDownList("groupName", (SelectList)ViewBag.groups)
<input id="Submit1" type="submit" value="Show" />
</div>
}
Regarding the option the user choose i generate a list and the Querystring in my address going to be like :
localhost/menu/list?groupName=controlpanel
My problem is when i use HtmlActionLink for example :
#Html.ActionLink("Title", "List", new { foo = item.foo})
What i got in result is result is :
localhost/menu/List?foo=123
instead of :
localhost/menu/List?foo=123&groupName=controlpanel
Am i missing something ??

It is not a built in solution, even though it seems to address exactly what you are looking for:
ASP.NET MVC Build Url Based on Current Url

To use ActionLink, you need to include all of the parameters you want to appear in the query string. The easiest thing I think would be is to add a GroupName property on your model (or in the ViewBag like your other sample). Then you can do this:
#Html.ActionLink("Title", "List", new { foo = item.foo, groupName = Model.GroupName })

Related

Form within a foreach loop not posting the model back to the controller

I've searched around and can't find an answer to my problem.
I've got a View that takes accepts Foo in like so:
#model IEnumerable<MyApplication.Models.Foo>
Inside of the view I've got a table. I populate the the table just doing a simple foreach loop through my Foo model. I have added a column where a user can add details to each row in a text area and save.
So the view looks like this:
#foreach (var item in Model)
{
<tr>
<th>
#using (Html.BeginForm("AddDetails", "MyController", FormMethod.Post))
{
#Html.AntiForgeryToken()
#Html.HiddenFor(u => item.Id)
#Html.TextAreaFor(u => item.Details, new { #class = "form-control" })
<input type="submit" value="Save" class="btn btn-sm btn-default" />
}
</th>
</tr>
}
My controller is setup like this:
[HttpPost]
public ActionResult AddDetails(Foo foo)
{
}
When I set a breakpoint on that controller foo always has null values for the Details property and the Id is always 0. When it's passed into the view it's got all of the properties set to right, so I'm not sure why it is not posting back properly?
I've tried this:
#using (Html.BeginForm("AddDetails", "MyController", FormMethod.Post, new { foo = Model }))
I have also tried removing the foreach loop and changing it to pass in just a single Model to the View and for the View to accept just the single model instead of an IEnumerable. When I do this it posts back just fine.
And that does not work either. I'm wondering if it has something to do with the fact that my form is within a foreach loop and perhaps I need to do a little more work like add a data-id attribute to the element and just capture the click event on the button and do an AJAX call to the controller and pass the right values along that way?
EDIT Sorry I completely forgot the view model. Here is what that looks like:
public class Foo
{
public int Id { get; set; }
public string Details { get; set; }
}
Generally speaking it's bad form to post to a different model than what your form view is composed from. It makes a lot of things difficult, not the least of which is recovering from validation errors.
What you're doing here is looping through a list of Foo and creating multiple forms that will each submit only a single Foo to an action that takes only a single Foo. While the post itself is fine, using the *For helpers on a model that is not the same as what you're posting to will likely not generate the proper input names necessary for the modelbinder to bind the posted values onto that other model. At the very least, if you need to return to this view because of a validation error, you will not be able to keep the user's posted data, forcing them to repeat their efforts entirely.
Ideally, you should either post the entire list of Foo and have just one form that wraps the iteration (in which case, you would need to use for rather than foreach). Or you should simply list the Foos with a link to edit a particular Foo, where you would have a form for just one Foo.
try to do this.possible problems
form should outside the table
single form for whole table
wrap your column editor inside tbody not thead
#using (Html.BeginForm("AddDetails", "MyController", FormMethod.Post))
{
//thead and tbody
}
Since no answer was reported for testing the for loop instead of foreach.
I was stuck all day yesterday using foreach loop and always got 0 items in the post method. I changed to for loop and was able to receive the updated items in the post method.
For reference I am using asp.net core 3.2
This is the foreach loop:
#{
foreach(var role in #Model.RolesList)
{
<div class="btn-check m-1">
<input type="hidden" asp-for="#role.RoleId" />
<input type="hidden" asp-for="#role.RoleName" />
<input asp-for="#role.IsSelected" class="form-check-input" />
<label class="form-check-label" asp-for="#role.IsSelected">#role.RoleName</label>
</div>
}
}
This is the for loop:
#for(int i = 0;i< Model.`enter code here`RolesList.Count();i++)
{
<div class="btn-check m-1">
<input type="hidden" asp-for="RolesList[i].RoleId" />
<input type="hidden" asp-for="RolesList[i].RoleName" />
<input asp-for="RolesList[i].IsSelected" class="form-check-input" />
<label class="form-check-label" asp-for="RolesList[i].IsSelected">#Model.RolesList[i].RoleName</label>
</div>
}

how to update the name attribute of a HTML helper

I am using MVC4, just wondering, is it possible to update the name attribute of a html helper. I am updating this as the action method is expecting a particular name. I know I can just write raw html, but just want to know if there is an overide in the html helper
I tried this
#Html.TextAreaFor(m => m.noteDetail.NotesDetails, new { #class = "k-textbox", #cols = 100, #rows = 5, id="NotesDetails", name= "NotesDetails" })
but when I look at the generated html
<textarea class="k-textbox" cols="100" data-val="true" data-val-required="The details are required" id="NotesDetails" name="noteDetail.NotesDetails" rows="5"></textarea>
Thanks
You just need a # symbol in front of your name property.
One technique I've found when a submodel is the model that your POST action accepts is to put the HTML that renders the submodel in a partial view that's included in the main view. Have this partial by strongly typed by the submodel and pass the value of the submodel into it. This way, the prefixes won't be generated on the submodel.
#Html.Partial("_NoteDetails", Model.noteDetail)
Then in _NoteDetails.cshtml
#model NoteDetail
#Html.TextAreaFor(m => m.NoteDetails,
new { #class = "k-textbox", cols = 100, rows = 5 });
Hi I think as you pass a viewModel as it contains maybe 2 models that is why you have this name. It does like this for the Binder to construct objects from your Post or Get.
If you change the name then you will maybe perform some custom codes for your binder if you want to pass it again to the controller.

Getting value from jquery datetimepicker in MVC

Im playing around with a booking-system in MVC.
I have a view where you select 3 diffrent values (treatment, hairdresser and date).
#using (Html.BeginForm("testing", "Home", FormMethod.Post)) {
<p id="frisor"> Frisör: #Html.DropDownList("Fris", "All")<a class="butt" onclick="showdiv()">Nästa steg</a></p>
<p id="behandling">Behandling: #Html.DropDownList("Cat", "All")<a class="butt" onclick="showdiv2()">Nästa steg</a></p>
<p>
Datum:
<input type="text" id="MyDate" /> <-------This is a jquery datetimepicker
</p
I would like to save the customers three choices in three properties i have created.
My post method looks like this:
[HttpPost]
public ActionResult Testing(string Fris, string Cat, DateTime MyDate)
{
kv.treatment = Cat
kv.Hairdresser = Fris;
kv.Datum = MyDate;
return View();
}
I get the two first (hairdresser,treatment) fine,
the problem is that i dont know how to get the value from the jquery datetimpicker.
Any help appreciated!
The input needs a name in order to be included in the form post:
<input type="text" id="MyDate" name="MyDate" />
Otherwise the browser won't include it in the posted data, so it will never reach the server for model binding. (And, of course, the name has to match the method argument name for the model binder to match them.)

how to strongly type an action from a view

I'm very new to using the MVC system and I would like to know how to "strongly-type" the controller as opposed to using a string in an action-link residing in a view. I put strongly typed in quotes because I am still a bit unsure as to its usage. Would be correct in saying that I have strongly typed the model at the top of the next code=line?
Here's my view:
#model HtmlEditModel
<title> Input Yout Html </title>
#Html.BeginForm(
#Html.TextAreaFor(m => m.HtmlInput))
<input type ="submit" />
#Html.ActionLink("Back to List page",
Here's my Action:
[HttpGet]
public virtual ActionResult HtmlEdit(
ActionMode mode,
int? id = null,
string returnUrl = null)
{
return base.DataGet<HtmlEditModel, Html>(mode, ID, db.Htmls, returnUrl);
}
#using(Html.BeginForm(action, controller)){ /*form fields go here*/}
I couldn't quite understand your comment, but after looking at your code I think you meant to say how to "remove" the ActionLink and bind the form to a specific action in a controller. Is this what you were asking for?

Binding value of form input to action link in ASP.NET MVC

I have the following snippet in my razor view.
#Html.ActionLink("US", "List", "Campaigns", new { country = "US", vertical = "Insurance" }, null)
<input id="verticals" />
How do I substitute vertical = "Insurance" with the value of <input id="verticals" />?
This depends on the source of the value that is in the input with id="verticals".
if the value is coming from the server, then you'd use that.
If you would like to apply value that is, for example typed in the input (in case the input type="text"), then you'd have to use some JQuery to update the link with the typed varaible.
Example in this case:
$('#verticals').change(function(){
$('#IdOfTheLinkTag').attr('vertical',$(this).val());
});
The code is not tested, but you get the idea.
I don't think this is possible. If you want that do it with JS and build the link yourself.
Click me!
<input type="text" id="verticals">
<script>
var vert = $('#verticals').val;
$.post() //bla bla
</script>
this is just some pseudo code but you get the idea.
i hope :)
*Note:
If verticals is an hidden field from the controller / model it easier of course
#Html.ActionLink("US", "List", "Campaigns", new { country = "US", vertical = Model.HiddenProperty}, null)

Categories

Resources