What is more correct: using UpdateModel () or getting the model as a parameter?

I have seen numerous examples of creating actions in articles, books, and examples. There seem to be two common styles.

[AcceptVerbs(HttpVerbs.Post)] public ActionResult Create(FormCollection collection) { try { var contact = Contact.Create(); UpdateModel<Contact>(contact); contact.Save(); return RedirectToAction("Index"); } catch (InvalidOperationException ex) { return View(); } } 

BUT...

  [AcceptVerbs(HttpVerbs.Post)] public ActionResult Create([Bind(Exclude="Id")]Contact contact) { try { contact.Save(); // ... assumes model does validation return RedirectToAction("Index"); } catch (Exception ex) { // ... have to handle model exceptions and populate ModelState errors // ... either here or in the model validation return View(); } } 

I tried both methods and both have pros and cons, IMO.

For example, when using the FormCollection version, I have to deal with "Id" manually in my connecting device, since Bind / Exclude does not work here. With a typed version of a method, I don’t use model binding at all. I like to use the model binder because it allows me to fill in ModelState errors without having any knowledge of ModelState in my model validation module.

Any ideas?

Update: I answered my question, but I will not mark it as an answer for a few days if someone has a better answer.

+7
validation asp.net-mvc
source share
4 answers

Well, after some conversation, I discovered that it should have been obvious: passing the model as a parameter simply leads to the default connection device being used behind the scenes. Since this was my biggest reason not to use a strongly typed version, I think there is no reason not to do it now.

In addition, my code should look like this:

  [AcceptVerbs(HttpVerbs.Post)] public ActionResult Create([Bind(Exclude="Id")]Contact contact) { if(!ModelState.IsValid) return View(); contact.Save(); return RedirectToAction("Index"); } 
+2
source share

Use UpdateModel if you want to update an existing model object that you can get from the database, or if you want to somehow create an instance of the model object.

eg:

  [AcceptVerbs(HttpVerbs.Post)] public ActionResult EditEmployee(int id, FormCollection collection) { try { Contact contact = repository.getContact(id); UpdateModel(contact, collection.ToValueProvider()); repository.save(); return RedirectToAction("Index"); } catch { //Handle return View(); } } 

If you do not have the above requirements, put it as an action parameter.

+3
source share

You should always accept a model as an action parameter because it makes the method more reliable.

It's much easier to pass a model object from your unit test than trying to mock an entire HttpContext to provide the data that UpdateModel needs to raise.

Even if you want to update an existing entity model, you should still use this template by entering a view model:

 [HttpPost] public ActionResult Edit(int id, EditContactViewModel viewModel) { if (ModelState.IsValid) { Contact contact = _db.GetContact(id) contact.Name = viewModel.Name; _db.SaveChanges(); return RedirectToAction("Index"); } return View(viewModel); } 
+1
source share

There are no right or wrong styles. If DefaultModelBinder meets your needs - always use a strongly typed version. If you cannot use DefaultModelBinder, choose between creating a custom ModelBinder or using the FormCollection Action parameter.

0
source share

All Articles