passing data by POST method between views in asp.net - asp.net

I have data in a particular view page(collected from the user) which I need to send to another view page which has a form needing this data. Now I can use:-
1. post method of javascript(jquery)
$().redirect('/Events/Create', {'arg1': 'value1', 'arg2': 'value2'});
or
A form:-
$('#inset_form').html(' < form action="/Events/Create"
method="post"style="display:none;">< input type="text" name="lat"
value="' + latitude + '" />< /form>');
document.forms['vote'].submit();
Now my question is, which method should be chosen?
Also, the '/Events/Create' page has form in the following way:-
#using (Html.BeginForm()) {
#Html.AntiForgeryToken()
#Html.ValidationSummary(true)
<div class="editor-label">
#Html.LabelFor(model => model.lat)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.lat)---------> THIS field accepts the POSTed data
#Html.ValidationMessageFor(model => model.lat)
</div>
<div>
....OTHER INPUT FIELDS.....
</div>
<p>
<input type="submit" value="Create" />
</p>
}
So, my next question is how do I make the text box 'lat' created by #Html.EditorFor in the form show the POSTed data as its default value. Then, the user can fill other fields and then submit the form.

As per HTTP standards, if a call is not changing the state of the website (i.e. data), you should use a GET request. This means you should provide the user with a link including the proper query string to populate the form on the /Events/Create page.
Also, keep in mind you never send data from view to view in MVC. Everything goes through a controller action so make sure your "Create" action on the "Events" controller accepts the proper arguments to populate the form for submission. If the Model.lat variable has a value in it when rendering the view, the text box will be prepopulated with that value.

Why do you want to POST the data to the second form? If you want to show the form and load it with default values, create a GET action method for it and pass the default values in the url. Although there's nothing stopping you having two POST methods for the same view, the normal approach would be to load the form using a GET, then POST back the data after editing.
[HttpGet]
public ActionResult Create(string lat)
{
MyView view = new MyView();
view.lat = lat;
View(view);
}
[HttpPost]
public ActionResult Create(MyView view)
{
//process posted data after editing
}
The view object here is a ViewModel class containing properties for the data that you will edit on the form. Make your View strongly typed to this ViewModel type.
To invoke the GET method from your jQuery (above):
window.location = "Events/Create?lat=myValue";

Related

Is using Viewbag for remembering past form inputs a bad idea?

I have a small asp.net core mvc application that basically consists of a form that a user can input some constraints into, and then get a filtered list of data depending on those constraints.
The controller action for filtering data basically looks like this:
[HttpPost]
public async Task<IActionResult> Query(QueryModel query)
{
var customers = await _context.Customers.AsQueryable().FilterCustomerList(query);
return View("Index", customers);
}
Now, my issue is that I would like the inputs in the fields to persist after entering them and being redirected to the view again. Right now they are currently just reset.
One way of doing this that I found was using viewBag. An example for a single query attribute is this:
public async Task<IActionResult> Query(QueryModel query)
{
var customers = await _context.Customers.AsQueryable().FilterCustomerList(query);
ViewBag.Name = query.Name;
return View("Index", customers);
}
and then the inpuit html elelment would look like:
<div class="col-md-4">
<input name="Name" type="text" placeholder="First name" value="#ViewBag.Name"class="form-control">
</div>
And this makes sure that if something has been entered into a field, it will now be entered into the field when after the query has been submitted.
But when I read up on ViewBag, I understand that a lot of .net developers have an aversion to it. It's not safe, the compiler can't catch errors in it easily etc.
Also, If I were to add all the input fields in my form to the viewbag, I would need a lot of lines of ViewBag.Attribute = query.SomeAttribute (20-30). Which seems like a code-smell too.
Is there any nicer way to do what I am trying to here?
You haven't included your QueryModel class and that class could be a key point to a cleaner approach.
You see, usually the user data, POSTed to your action is bound to the model, from there it's rendered on the form and is POSTed again. The model binding is where an input of a specific name is bound to a model member of the same name.
Thus, there's no need for viewbags.
More formally:
The Model
public class QueryModel
{
[your-validators-in-attributes, e.g. Required or MaxLength
there can be multiple validators]
public string Name { get; set; }
}
The controller:
[HttpPost]
async Task<IActionResult> Query(QueryModel query)
{
// query.Name is there, bound from the view
}
The View:
#model .....QueryModel
<div>
#Html.TextBoxFor( m => m.Name, new { placeholder = "a placeholder" } )
</div>
The html helper does two things
renders an input of the given name (Name in this case)
sets its value depending on the actual value from the model
In newer ASP.NETs you can achieve similar result by using tag helpers, where instead of Html.TextBoxFor(...) you write
<input asp-for="Name" />
These two approaches, using html helpers or using tag helpers are equivalent. In both cases there's no need for view bags.

How to get the user entered data from view to controller and then insert into database, in MVC?

I am a beginner and currently started a small project for my study purpose. A mini DB search portal. I created front end View. It has one search box and a button. Now what I need is, I have to fetch the data from DB, related to the user entered search term on clicking on the button.
How to proceed to get the user entered data from view to controller and process it for further operations.
General code:
view:
#using(Html.BeginForm("Search","Test"))
{
<input type="text" name="txtName"/>
<input type="submit" value="Generate report" />
}
Controller
[HTTPPost]
public ActionResult Seacrh(FormCollection form) // "Search" is action name specified in view for controller "TestController"
{
string text = form["txtName"]; // txtName is name of input in view.
}
However to take full advantage to MVC have a look at Model Binding in MVC
I recommend reading this article, it has an example different ways of adding search.
You can update the Index method in your Controller and View as follows:
1)Add a form to the view that will post to the view itself
View
#using (Html.BeginForm()){
<p> Title: #Html.TextBox("SearchString") <br />
<input type="submit" value="Filter" /></p>
}
2)Add a parameter to the Index method to filter the content based on the parameter passed. public ActionResult Index(string searchString)
Controller
var movies = from m in db.Movies
select m;
if (!String.IsNullOrEmpty(searchString))
{
movies = movies.Where(s => s.Title.Contains(searchString));
}
return View(movies);

How to make a search for item and show the result in seperated page [ASP MVC]

I just want to make a search for my site , and before I start work on that I just want to sort my work steps .
My site type is books site . and here is what I want to know :
I have a search box in my navbar .
when someone entered a book name to search I want to show the result of this
search in this page :
Localhost/Search?string=C++
How I can call the method that will process the search from the view
?
How should the controller method looks like , also the view page.
How to make a paging to the search page ?
I don't need a code , I just want from someone to help me with a list of steps I should do , to make the search as I requested and thanks a lot guys ....
You can keep your input box for search inside a form and keep the form's method value to be GET.
#using (Html.BeginForm("Search", "Students", FormMethod.Get, null))
{
<input type="text" name="searchTerm" />
<input type="submit" />
}
Now you should have an action method called Search inside your StudentsController which accepts a string value in a parameter named searchTerm.
public ActionResult Search(string searchTerm)
{
// use searchTerm variable to get data and pass to view
return View();
}
Now in your view (~/Views/Students/Search.cshtml), you can use the passed data to display the search results.
For paging, you may add another parameter to your action method which you will use to get a specific sub set of the data.
public ActionResult Search(string searchTerm,int page=1,size=10)
{
// use searchTerm variable to get data and pass to view
// page number is in page variable
// size is in size variable
return View();
}
Now you need to adjust your view to show all the page numbers and link to the same action method and pass the page number in url like
/Students/Search?searchTerm=Java&page=2&size=25

Post a file from View to Controller

I have following code in view :
<div>
<input type="file" name ="file" onchange="location.href='<%: Url.Action("ChangeImage", new{Id = Model.Id}) %>'" />
</div>
And in Controller I have the ChangeImage method :
public ActionResult ChangeImage(FormCollection collection, int Id,Products products)
{
var file = Request.Files["file"];
//Do something
}
But the selected file does not post to the controller. What is the problem? How can I send the file content to the controller to use it?
Because you are not posting the form data is probably the reason.
When creating an MVC form for submitting files you must specify the "enctype", with the helpers you can do this:
#using (Html.BeginForm("MyAction", "MyController", new { #Id = Model.Id }, FormMethod.Post, new { name = "Form", enctype = "multipart/form-data" }))
{
//all form fields code in here
}
Then you will want to change your javascript to post the form, something like:
document.forms[0].submit();//assuming you only have one form
Also, your action parameters don't seem to match anything. Specifically ShopID and products. You will probably get an error because you don't have default values for them. I am not 100% sure on that part though. Or maybe you have then in other parts of your form, so it might be ok

How to pass parent model from inside partial view

I am rendering a parital view which has a submit button with HttpPost action in controller. This action method needs parent model as its parameter. Is there any way to send parent model as first parameter from inside a partial view?
Main view -> aspx file which has model as ParentModel
Partial view -> ascx file which has model as ParentModel.ChildModel
Controller action -> MyActionName(ParentModel model, int direction, int user)
If I keep the method as HttpPost then by default Parent model gets passed but then I cannot send 2nd and 3rd parameter as their values are decided at run time and these are not childmodel properties. e.g. direction parameter which indicates if user has clicked next/prev button. In this case, next and prev buttons call same action method (MultipleAction submit)
Additional info: My parent model has a collection of child model. I am looping through this collection and calling RenderPartial for each item. So, I cannot pass this parent model directly to my partial view (which is default behavior).
Any suggestions please? Thanks..
You could wrap all those partials into a HTML <form> so that all values get submitted too the server when this form is posted:
<% using (Html.BeginForm()) { %>
<%= Html.TextBoxFor(x => x.SomePropertyOfParent) %>
<%= Html.TextBoxFor(x => x.SomeOtherPropertyOfParent) %>
<%= Html.EditorFor(x => x.Children) %>
<input type="submit" value="OK" />
<% } %>
I use an editor template instead of partials for the Children collection. The custom editor template will automatically be rendered for each element of this children collection and provide any input fields allowing to modify it.
Then when the form is finally submitted all the properties required by the model binder to reconstruct the ParentModel will be sent to the server. As far as the direction and user parameters are concerned I would make them part of the parent view model so that my POST controller action looks like this:
[HttpPost]
public ActionResult MyActionName(ParentViewModel model)
{
...
}

Resources