My mvc action can't update the model - asp.net-mvc

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

Related

How to use ModelState to clear my form after I post my form data,my view model is a viewmodel which has two models?

my view model is a viewmodel which has two models,
publish class ViewModel
{
public Student StudentModel{get;set;}
public Teacher TeacherModel {get;set;}
}
I has two forms called StudentForm and TeacherForm,Which binding StudentModel and TeacherModel respectively.Now I fill in some data in StudentForm and submit it. I use ModelState.Clear(); to clear my StudentForm data ,but It seems not only clear the data of the StudentForm but also the TeacherForm,How can I only clear the data of the StudentForm?
to shorten, you may just do
foreach (var key in ModelState.Keys.Where(m => m.StartsWith("StudentModel")).ToList())
ModelState.Remove(key);
In such case you will have to remove each property of StudentModel from your ModelState i.e.
Syntax:
ModelState.Remove("PropertyName");
Example:
ModelState.Remove("Id");
ModelState.Remove("Name");
ModelState.Remove("Marks");
Edit: For specific model property in among two
ModelState.Remove("StudentModel.Name");
ModelState.Remove("StudentForm"),Here is the MSDN link for this, http://msdn.microsoft.com/en-us/library/dd470162%28v=vs.108%29.aspx
While returning the model from action you can reinitialize the student object
For eg:
[HttpPost]
public ActionResult ActionName(ViewModel model)
{
model.StudentModel = new StudentModel();
return View(model);
}
Note: ModelState Key contains your ViewModel Name, like:
ModelState.Remove("YourViewModelName.YourPropertyName");

MVC sending data from View to Controller

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.

What is the purpose of passing a data model instance from within [HttpGet] Create to its View?

I notice there are 2 common practices to implement the Create form.
First Approach
From within [HttpGet] Create action method, we pass an instance of data model to the Create.cshtml as follows:
public ActionResult Create()
{
DataModel dm = new DataModel();
return View(dm);
}
Second Approach
From within [HttpGet] Create action method, we don't pass an instance of data model to the Create.cshtml as follows:
public ActionResult Create()
{
return View();
}
The [HttpPost] Create(DataModel dm) for both approaches is as follows:
[HttpPost]
public ActionResult Create(DataModel dm)
{
if (ModelState.IsValid)
{
db.Movies.Add(dm);
db.SaveChanges();
return RedirectToAction("Index");
}
else
return View(dm);
}
The question is: What is the purpose of passing a data model instance from within [HttpGet] Create to its View ?
Passing a data model to the view associated with the 'Create' is useful if you want the application logic to supply the initial values to be displayed on the form (whether because you don't want them hard-coded in the form defined in the view, or because they might differ depending on the context).
Default values for the bound controls, values in the viewmodel to be consumed by the view to generate dropdowns, etc... as mentioned by rsalmeidafl.
At the risk of sounding like a curmudgeon, this is really best practice. You shouldn't be calling the database to generate select lists and things from your views.
Finally, sending a default instance of the model to your view can also let you reuse edit/create views very easily, since you can bind values without fear of NullRef exceptions for your model. (if you strongly type your views)

Do I need to fill ViewData (MVC 2) more than once?

I am following a simple ADO.NET Entity/MVC 2 tutorial wherein my Views are created by right-clicking the action and selecting 'Add View'. The views get created based on my model and all is good. I can view the initial list of items from the DB but when I click Edit or Delete or Details I get 'Object reference not set to an instance of an object'. It acts like my data is not there at all so I'm thinking I may need to fill ViewData again?
Here is how I am getting the data:
CheckingEntities chk = new CheckingEntities();
//
// GET: /CheckingMVC/
[Authorize]
public ActionResult Index()
{
ViewData.Model = chk.tblCheckings.ToList();
return View();
}
And here is an example where I am getting the details:
// GET: /CheckingMVC/Details/5
[Authorize]
public ActionResult Details(int id)
{
return View();
}
I suspect I have filled the ViewData incorrectly or need to do it again but don't know where or how to do that. Still quite new to MVC.
The values passed to your Views must be populated on every request. Furthermore, values set inside your controller during a request cannot and will not be persisted between requests as every new requests creates a brand new set of controller instances from the controller factory.
In your Details() action you are accepting an id and then returning your View without any data being placed in the Model. Instead try something along these lines:
[Authorize]
public ActionResult Details(int id)
{
var item = Entities.SomeEntitySet.SingleOrDefault(e => e.Id == id);
return View("Details", item);
}

Example of an ASP.NET MVC post model?

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.

Resources