views:

393

answers:

3

I've seen numerous examples of create actions in articles, books, and examples. It seem there are two prevalent 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();
     }
 }

And...

 [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's validation
         return View();
     }
 }

I've tried both methods and both have pluses and minuses, IMO.

For example, when using the FormCollection version I have to deal with the "Id" manually in my model binder as the Bind/Exclude doesn't work here. With the typed version of the method I don't get to use the model binder at all. I like using the model binder as it lets me populate the ModelState errors without having any knowledge of the ModelState in my model's validation code.

Any insights?

Update: I answered my own question, but I wont mark it as answered for a few days in case somebody has a better answer.

+1  A: 

Well, after some dinking around I discovered what should have been obvious: passing the model as the parameter merely causes the default model binder to get used behind the scenes. Since this was my biggest reason not to use the strongly-typed version, then I guess there is no reason not to now.

Also, 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");
 }
Sailing Judo
Problem you will find not using FormCollection however, is restrictions. You do not have fine-grain control on what is being bound. See my post on this http://goneale.com/2009/07/27/updating-multiple-child-objects-and-or-collections-in-asp-net-mvc-views/
GONeale
A: 

There are no correct or incorrect styles. If DefaultModelBinder suits your needs - always use strongly-typed version. If you can not use DefaultModelBinder - choose between creating a custom ModelBinder or using FormCollection Action parameter.

eu-ge-ne
+1  A: 

Use UpdateModel when you want to update an already present model object, which you may get from database or you want to instantiate the model object in some specific way

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 dont have the above requirements then put it as action parameter.

San