I am quite new to MVC 3.
I know how to send a strongly typed object from a Controller to a View. What I have now, is a View which contains a table/form which consists of that data.
The user can change that data whilst they're are in that View (html page).
When they click on "Save", how do I send the data from the View back to the Controller so that I can update my database.
Do I overload the Controller method so that it accepts a parameter of the model type? Can you please provide some source code.
(Please do not show code of persisting data to a database, I know how to do that part).
Thank you very much for helping me.
I would also prefer using #Html.BeginForm()
I like creating an action method made for my post data. So let's say you have a UserViewModel:
public class UserViewModel
{
public int Id { get; set; }
public string Name { get; set; }
}
Then a UserController:
public class UserController
{
[HttpGet]
public ActionResult Edit(int id)
{
// Create your UserViewModel with the passed in Id. Get stuff from the db, etc...
var userViewModel = new UserViewModel();
// ...
return View(userViewModel);
}
[HttpPost]
public ActionResult Edit(UserViewModel userViewModel)
{
// This is the post method. MVC will bind the data from your
// view's form and put that data in the UserViewModel that is sent
// to this method.
// Validate the data and save to the database.
// Redirect to where the user needs to be.
}
}
I'm assuming you have a form in your view already. You'll want to make sure that the form posts the data to the correct action method. In my example, you'd create the form like so:
#model UserViewModel
#using (Html.BeginForm("Edit", "User", FormMethod.Post))
{
#Html.TextBoxFor(m => m.Name)
#Html.HiddenFor(m => m.Id)
}
The key to all this is the model binding that MVC does. Make use of the HTML helpers, like the Html.TextBoxFor I used. Also, you'll notice the top line of the view code I added. The #model tells the view you'll be sending it a UserViewModel. Let the engine do work for you.
Edit: Good call, did that all in Notepad, forgot a HiddenFor for the Id!
In MVC, the act of scraping out data from POST or GET HttpRequests is referred to as Model Binding - there are plenty of SO questions relating to this.
Out of the box, MVC will bind your Get and Post variables based on convention, e.g. a form field with the name 'FormName' will be bound back to a parameter on your controller with the same name.
Model binding also works for objects - MVC will instantiate an object for your controller, and set the properties with the same name as your form.
Related
I have to create a textbox from a viewbag property in MVC. I could do the mapping like #Html.TextBox("Comments", (string)ViewBag.Comments) but how do I read it back when the page is posted to the server. It is not filling the viewbag property back. I am very new to MVC so maybe don't understand the concept totally .
Thanks
Your ViewBag wont get updated from your view and that is not the way to get data from your form. Rather, you should either use strongly typed model binding to read your data from your Action Method or you can simply check for the key in your Forms data. I am showing you example for both:
Example 1: Strongly typed model binding.
[HttpPost]
public ActionResult MyAction(string comments)
{
// the Comment from the text box.
return View();
}
Example 2: Reading from Posted Data:
[HttpPost]
public ActionResult MyAction()
{
// the Comment from the text box.
string comments = Request.Form["comments"];
return View();
}
I hope, you will like to use the Example 1.
Anyway, the best practice would be to bind your View with a Model class and use HtmlHelper for generating the text box like :
Html.EditorFor(model => model.Comments)
Where your Model class contains a property named Comments.
And your action method should accept the same Model type as argument. Here is an example:
[HttpPost]
public ActionResult MyAction(MyModel model)
{
string comments = model.Comments;
}
And you should bind your View with the model of type MyModel.
I can understand that, as you are new to MVC, this may not make clear sense now, so, I would suggest you to check out some basic MVC tutorial. You can start from here : http://www.asp.net/mvc/tutorials
I am trying to update my model using MVC so i write this code to do that :
SemesterRepositor obj = new SemesterRepositor();
public ActionResult Edit(int id)
{
return View(obj.FindSemesterById(id));
}
[HttpPost]
public ActionResult Edit(int id,FormCollection collection)
{
var review = obj.FindSemesterById(id);
if (TryUpdateModel(review))
{
RedirectToAction("Index");
}
return View(review);
}
One of this method get the model and another one that is for post back updates the model .but it doesn't work .Why?
Best regards
there are many ways to send data from a view back to the controller. The easiest way is to tie your model items on the view to for helpers (except display) and then do a post back. your input on the post method would need to include the model
[HttpPost]
public ActionResult Edit(SemesterRepositor sr){
//save the data in sr to your database
RedirectToAction("Index");
}
you have form collection as an input to your post method which will have fields from your view but to save the values you would have to pass the individual fields to your database. In your code you have find semester by id but you don't ever set the form collection values to that object so it will always be empty
Update:
if your view has #model SemesterRepositor at the top and you use for helpers on your view your fields will be tied to the model
#model SemesterRepositor
#Html.TextBoxFor(x => x.Name)
something like this. Then on post back the field Name will have the value of the text box tied to it
Maybe this is very simple to do but I can't find the good words when I search on stackoverflow or on google.
I have a model and this model contains a "Country" property that is a integer. When I am in the Edit view, this property is used this way and it work well.
#Html.DropDownListFor(model => model.Country, new SelectList(ViewBag.Countries, "IDCountry", "Name"))
In the Details view, I only want to show the name of the country, but I don't know how! Right now, I'm doing this but it only show the ID and I can't find a way to give him the List so it use it as a datasource or something like that to show "Canada" instead of 42.
#Html.DisplayFor(model => model.Country)
How can this be achieved?
How can this be achieved?
By using a view model of course:
public class CountryViewModel
{
public int CountryId { get; set; }
public string CountryName { get; set; }
}
and then you would populate this view model in the controller action that is supposed to render your Display view:
public ActionResult Display(int id)
{
Country country = ... go and fetch from your db the corresponding country from the id
// Now build a view model:
var model = new CountryViewModel();
model.CountryId = country.Id;
model.CountryName = country.Name;
// and pass the view model to the view for displaying purposes
return View(model);
}
Now your view will be strongly typed to the view model of course:
#model CountryViewModel
#Html.DisplayFor(x => x.CountryName)
So as you can see in ASP.NET MVC you should always be working with view models. Think in terms of what information you need to work with in a given view and the first thing you should do is define a view model. Then it's the responsibility of the controller action that is serving the view to populate the view model. Where the values of this view model are coming from doesn't really matter. Think of the view model as a single point of aggregation of many data sources.
As far as the views are concerned, they should be as dumb as possible. Simply work with what's available in the view model.
I'm using MVC3 razor, and I'm trying to pass an object to a partial view, and it's not working.
This works fine without sending the object model to the partial view:
Html.RenderAction("Index", "ViewName");
Trying this doesn't sent the model object, i'm getting nulls instead (the object has data, and the view expects it):'
Html.RenderAction("Index", "ViewName", objectModel);
Is this even possible using RenderAction?
Thanks!
Edit: I found the error, there was an error with the controller's action that didn't pick up the sent object. Thanks for all your help!
You can actually pass an object to a controller method using Action. This can be done on any avaialble view, for instance I have one in a shared library that gets built to project bin folders that reference my shared project (properties - Copy if newer on the view file, in Visual Studio). It is done like so:
Controller:
public class GroovyController : Controller
{
public ActionResult MyTestView(MyModel m)
{
var viewPath = #"~\bin\CommonViews\MyTestView";
return View(viewPath, m);
}
}
MVC page (using Razor syntax):
#Html.Action("MyTestView", "Groovy", new { m = Model })
or using RenderAction method:
#{ Html.RenderAction("MyTestAction", "MyTestController", new { area = "area", m = Model }); }
Note: in the #Html.Action(), the Model object must be of type MyModel and that 3rd parameter must be set to the controller variable name, of which mine is MyModel m. The m is what you must assign to, so I do m = Model.
say you want to pass foo as model, make it first
public class Foo {
public string Name { get; set; }
public int Age { get; set; }
}
now make an ActionResult
public ActionResult FooBar(Foo _foo){
return PartialView(_foo);
}
call it
#Html.RenderAction("FooBar", "Controller", new { Name = "John", Age=20 });
Usually if I have a model already available it makes more sense to use Html.Partial than trying to render an action.
#Html.Partial("Foo", Model.FooModel)
Where Foo.cshtml is a view file (perhaps in your Shared folder) strongly typed with with #model FooProject.Models.FooModel or whatever your model is called. This can be as complex a model as you need it to be. Model is your page's main model into which you must set FooModel - or just omit this parameter if the Foo view uses the same model as the parent page.
RenderAction is generally better when you have just simple parameters, because you're just simulating a request to a regular action which has routing/query string parameters - and then dumping that response into your page. It works well if you need to put something in a Layout that isn't available in your page's model such as an element in a side bar.
I was watching the HaHaa presentation on ASP.NET MVC from MIX and they mentioned using a Post Model where I guess they were saying you could use a model that was ONLY for posting. I have tried looking for examples for this. Am I not understanding what they are saying? Does anyone have an example of how this might work in a strongly typed view where the view model and post model are not of the same type?
Below is ScottGu's example expanded a bit. As #SLaks explained, when the POST is received, MVC will try to create a new MyPostName object and match its properties with the from fields. It will also update the ModelState property with the results of the matching and validation.
When the action returns the view, it has to provide a model for it as well. However, the view doesn't have to use that same model. In fact, the view can be strongly typed with a different model, that contains the expanded data, for example it can have navigation properties bound to external keys in the DB table; and if that's the case, the logic to map from the POST model to the view model will be contained in the POST action.
public class MyGetModel
{
string FullName;
List<MyGetModel> SuggestedFriends;
}
public class MyPostModel
{
string FirstName;
string LastName;
}
//GET: /Customer/Create
public ActionResult Create()
{
MyGetModel myName = new MyGetModel();
myName.FullName = "John Doe"; // Or fetch it from the DB
myName.SuggestedFriends = new List<MyGetModel>; // For example - from people select name where name != myName.FullName
Model = myName;
return View();
}
//POST: /Customer/Create
[HttpPost]
public ActionResult Create(MyPostModel newName)
{
MyGetModel name = new MyGetModel();
name.FullName = newName.FirstName + "" + newName.LastName; // Or validate and update the DB
return View("Create", name);
}
The POST model would only be used to pass the data into your action method.
The model that the POST action sends to its view doesn't need to be related to the model that it received (and usually will not be).
Similarly, the model that the initial GET action (that shows the form in the first place) passes to its view (which submits to the POST action) doesn't need to be related to the model that the POST action takes (although it usually will be the same model)
As long as it has properties that match your input parameters, you can use any model you want for the parameter to the POST action.