I have a page that displays a list of people. It can be sorted on first and last name. To search for people, I have the following Razor form:
#using (Html.BeginForm("Index", "Persons", new { sort = ViewBag.Sort }, FormMethod.Get))
{
<p>
Search: #Html.TextBox("search", ViewBag.Search as string)
<input type="submit" value="Search" />
</p>
}
ViewBag.Search and ViewBag.Sort contains the last used search and sort routeValues. When I sort the list of people on first name, the form gets rendered in HTML like this:
<form action="/persons?sort=firstname" method="get">
<p>
Search: <input id="search" name="search" type="text" value="" />
<input type="submit" value="Search" />
</p>
</form>
As intended, ?sort=firstname is included in the action. However, when I press the submit button (Search), the sort parameter is lost. The new url only has ?search=.... How can I fix this?
When you look at the output html you would get something like this :
<form action="/persons/index?sort=asc" method="get">
<p>
<input type="text" name="search" />
<input type="submit" value="Search" />
</p>
</form>
This seems completely legit, you would expect a behaviour like appending the query of post inputs. However this is limited by HTTP specification. The query string of a form post action wont be appended. That is why your query parameters wont work at your server side. However i what would expect from the Asp.net to get the parameters for the form to the hidden fields automatically which it doesnt right now.
As a proper solution you have to put the input , in the form , so you can use hidden field to do this like :
#using (Html.BeginForm("Index", "Persons", FormMethod.Get))
{
#Html.Hidden("sort",ViewBag.Sort)
<p>
Search: #Html.TextBox("search", ViewBag.Search as string)
<input type="submit" value="Search" />
</p>
}
You need to store the value of sort somewhere in the form, in order for it to be included as part of the submit. You could try a hidden input:
#using (Html.BeginForm("Index", "Persons"))
{
<input type="hidden" id="sort" value="firstname" />
<p>
Search: #Html.TextBox("search", ViewBag.Search as string)
<input type="submit" value="Search" />
</p>
}
You may need to tweak how the value of sort is retrieved from, I put firstname as an example, but when you submit the form, sort will be included in the payload e.g.
[HttpPost]
public ActionResult Index(string sort, string search)
{
}
Related
here was my code from view
#{ var companies = (IEnumerable<Company>)ViewData["companylist"]; }
#foreach (var item in companies)
{
//post the form to upload actions, index2 for testing
<form id="submitfinal" method="post" asp-action="Upload" asp-controller="report" enctype="multipart/form-data">
<input type="hidden" name="companyid" value="#item.Id" />
#item.Name (#item.Status)
<input type="file" name="files" />
<input name="submit" type="submit" value="upload final report" />
</form>
}
Question here was how can i take the data from input tag attribute to controller?
let say the #item.Id is 1234, how i get that in controller?
you can use
#Html.HiddenFor(m => m.yourPropertyname)
or using jquery ajax you can send the value to controller.
Maybe it's too late, but I would use asp-route-Id like:
<form id="submitfinal" method="post" asp-route-Id="#item.Id" asp-action="Upload" asp-controller="report" enctype="multipart/form-data">
I've a form that points to itself on POST operation to process data. This part is good. Now in the form I've a textbox and a button (X) that is used for another purpose as well. When this button X is clicked it should take the input value from the text box and point to another ASP page, process data and return the value...and this is the part I'm unable to figure out... Let me explain this in a bit more clearly..
form name=frmAccounts method=Post action="self.asp"
...
...
name ---> Textbox
function ---> textbox :: search button(X) <--> sales.asp
Description --->textbox
...
...
Form Submit ---> button
Form ends
Now..suppose I enter function as "Sales" in the textbox, then when I click on the search button it would look at another ASP page like sales.asp that will query for relevant description and populate the description box...Then the form submit will call the self.asp to do its function.
Question: How can I pass value from function textbox, via search button, to sales.asp for processing and return back the value.
Things I've tried so far with no luck
1) Functions using #include method
2) Button onClick method by passing Request.Form data
3) href option by passing the URL by adding the form data - URL does not take the value
some other methods after Googling through many forums but with no joy.
Any help please?
Like Lankymart says, do something like this:
Self.asp
<form action="self.asp" name="myform" id="myform">
<input type="text" name="name" id="name" />
<br /><input type="text" name="functionbox" id="functionbox" />
<br /><input type="button" name="search" value="search" id="search" />
<br /><input type="text" name="Description" id="Description" />
<br /><input type="submit" value="submit" />
</form>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js"></script>
<script type="text/javascript">
$(function() {
$("#search").click(function() {
$.ajax({
data: {'functionbox': $("#functionbox").val()},
url: '/sales.asp',
success: function(data) {
if (data) {
$("#Description").val(data);
}
}
});
});
});
</script>
sales.asp
<%# LANGUAGE = JScript %>
var functionbox = Request.Form("functionbox").Item;
var answer = getAnswer(functionbox); // your code here
%><%= answer %>
Here is a simplified example. My first form :
#using (Html.BeginForm("Action1", "MyController", FormMethod.Post))
{
<input id="cb" type="checkbox" value="true" name="MyCheckBox" />
<label for="cb">Check this out</label>
}
And late in the same view, another form :
#using (Html.BeginForm("Action2", "MyController", FormMethod.Post))
{
<input type="submit" value="Submit" id="submit" />
}
How to efficiently get the value (checked or not) of this checkbox, in the action Action2 in MyController ?
Browser don't send values from another form in requests.
The only way to do it is to handle onsubmit event with js/jquery, add value to form and submit it with js.
I am trying to bind a dynamic array of elements to a view model where there might be missing indexes in the html
e.g. with the view model
class FooViewModel
{
public List<BarViewModel> Bars { get; set; }
}
class BarViewModel
{
public string Something { get; set; }
}
and the html
<input type="text" name="Bars[1].Something" value="a" />
<input type="text" name="Bars[3].Something" value="b" />
<input type="text" name="Bars[6].Something" value="c" />
at the moment, bars will just be null. how could I get the model binder to ignore any missing elements? i.e. the above would bind to:
FooViewModel
{
Bars
{
BarViewModel { Something = "a" },
BarViewModel { Something = "b" },
BarViewModel { Something = "c" }
}
}
Add the .Index as your first hidden input to deal with out of sequence elements as explained in this Phil Haacked blog post:
<input type="text" name="Bars.Index" value="" />
<input type="text" name="Bars[1].Something" value="a" />
<input type="text" name="Bars[3].Something" value="b" />
<input type="text" name="Bars[6].Something" value="c" />
A possible workaround could be to instantiate the ViewModel and the collection to the correct size (assuming it's known), then update it with TryUpdateModel... something like:
[HttpPost]
public ActionResult SomePostBack(FormCollection form)
{
// you could either look in the formcollection to get this, or retrieve it from the users' settings etc.
int collectionSize = 6;
FooViewModel bars = new FooViewModel();
bars.Bars = new List<BarViewModel>(collectionSize);
TryUpdateModel(bars, form.ToValueProvider());
return View(bars);
}H
MVC is able to populate list itself.
public ActionResult Index(FooViewModel model)
{
...
So no matter if anything is missing mvc will create new List<BarViewModel> and
for each found index - [1],[3],[6] it will create new BarViewModel and add it to List. So you will get FooViewModel with populated Bars.
i didnt know even that worked!
bearing that in mind, id have done something like:
<input type="text" name="Bars.Something" value="a" />
<input type="hidden" name="Bars.Something" value="" />
<input type="text" name="Bars.Something" value="b" />
<input type="hidden" name="Bars.Something" value="" />
<input type="hidden" name="Bars.Something" value="" />
<input type="text" name="Bars.Something" value="c" />
which would hopefully post
a,,b,,,c
but I suspect that will bind in the same way as you describe
Youre probably going to have write a custom model binder that looks for the max index, makes a list of that size then puts the elements in the correct place.
Saying all that, wait for someone else to post a really simple attribute you can put on your property that makes it just work ;D
I have a route defined as:
routes.MapRoute("AllUsers",
"Users/Search/{Search}", new {
Controller = "Users", action=
"Index"});
and the form as:
<% using (Html.BeginForm("Index", "Users/Search/", new { RouteValue = "AllUsers" }, FormMethod.Get, new { id = "searchForm" })){%>
<input id="searchBox" name="search" type="text" />
<input type="submit" id="submit" value="Search" /><%} %>
Currently as expected this creates a url of
../Users/Search/?search=searchTerm
but what I would like is:
../Users/Search/searchTerm
How is this possible? I thought of using javascript, but this seems a little dirty. Is there a more streamlined way of accomplishing this?
You cannot do that with an HTML form. Though you can mimic the behavior with JavaScript.
How about a server-side redirect?
You could do:
<input type="submit" id="submit" value="Search"
onclick="$('form').attr('action', $('form').attr('action') + $('#searchBox').val());" />
Which seems a little ugly. You could also not use a form and have this:
<input type="button" id="submit" value="Search"
onclick="window.location.href = 'search/' + $('#searchBox').val();" />
Outside of this, you could allow the original submit to go to the weird url, but use RedirectToAction in your controller.
Using jQuery you could something like this:
<script type="text/javascript">
$(function(){
$("#submit").click(function(){
document.location.href = $("form").attr("action") + $("#searchBox").val();
return false;
});
});
</script>
Try to change like this:
routes.MapRoute("AllUsers",
"Users/Search/{id}", new { Controller = "Users", action= "Index"});
and the form as:
<% using (Html.BeginForm("Index", "Users/Search/",
new { RouteValue = "AllUsers" }, FormMethod.Get, new { id = "searchForm" })){%>
<input id="searchBox" name="id" type="text" />
<input type="submit" id="submit" value="Search" /><%} %>
Not tested, but "id" is default route value which are not creating "?name=value".