CRUD in ASP.NET MVC 1 vs MVC 3
I am doing [this tutorial][1]开发者_JAVA技巧 over at www.asp.net. It is written for ASP.NET MVC 1. Although most of the stuff works for MVC 3, I do have a question regarding this code:
ASP.NET MVC 1.0 (straight from the tutorial)
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Create([Bind(Exclude = "Id")] Contact contactToCreate)
{
if (!ModelState.IsValid)
return View();
try
{
_entities.AddToContactSet(contactToCreate);
_entities.SaveChanges();
return RedirectToAction("Index");
}
catch
{
return View();
}
}
ASP.NET MVC 3 (default Create action generated by MVC 3 Project, except my _entities object)
[HttpPost]
public ActionResult Create(FormCollection collection)
{
try
{
_entities.AddToContacts(collection); // synax error
_entities.SaveChanges();
return RedirectToAction("Index");
}
catch
{
return View();
}
}
So my question is why do we pass Contact contactToCreate
in the first case, but FormCollection collection
in the second?
I could easily change argument in the second example to just Contact Contact contactToCreate
, but I am curious as to what is this FormCollection collection
stuff? Why did MVC 3 generate it for us? If it's possible to use FormCollection instead, how would the modified example look like?
[1]: http://www.asp.net/mvc/tutorials/iteration-1-create-the-application-cs
Personally, I'd stick with your MVC1 example -- no need to go back into loosey goosey key value collection land.
You should not use FormCollection. This great tutorial from Microsoft explains that you should change the created signature to use your Model. The reason it uses FormCollection is because the Model isn't specified when it generates the scaffolding code. Hope this helps.
The second Create method is of more interest. This is the one that will be called when the Create view posts back. By default, the template told this Create method to expect a FormCollection to be passed in as a parameter.
Because the Create view was created as a strongly-typed view, it will be able to pass back a strongly typed Blog object. This means you can change that signature so that the method receives a Blog type. That will simplify the task of adding the new blog to the BlogModelContainer and saving it back to the database using Entity Framework code.
FormCollection
is the values entered by the user and Contact
is the enderlying entity that you are creating.
Remember that this method is essentially called directly by the user as the result of a HTTP post and its bad practice to be blindly accepting user input without validating it. This and the fact that in real-world scenarios the values available to you in a HTTP post request don't exactly match up to your data entity properties is probably the reason why its probably a good idea to accept a FormCollection
(or other abstracted input representing your form values) rather than directly accepting an entity in your database.
Personally my modified example would look a little like this:
[HttpPost]
public ActionResult Create(FormCollection collection)
{
try
{
var contactToCreate = validateAndCreateContact(collection);
if (contactToCreate != null)
{
_entities.AddToContacts(collection);
_entities.SaveChanges();
return RedirectToAction("Index");
}
}
catch (Exception ex)
{
// Logic to display error on the view goes here, e.g.
base.ViewData["Exception"] = ex;
}
return View();
}
private Contact validateAndCreateContact(FormCollection collection)
{
// Your implementation here
}
The validateAndCreateContact
should validate user input and return a suitable Contact
object if the input is all OK. If not it should return null
and handle displaying a suitable error to the user (for example by setting properties on the ViewData
).
精彩评论