I can't understand, how to use TryUpdateModel and save the MVC architecture at the same time.
If I am not mistaken, work with datacontexts must be in the Model. So, such code
var db=new TestEverybody();//it is class, which was generated by EntityFramework
var currentTesting=db.Testing.(t => t.id == id).First();
must be situated in the Model, not in the Controller, mustn't it?
But the ussual examples of TryUpdateModel usage is following:
public ActionResult Edit(Testing obj)//Testing collection
{
var db = new TestEverybody();
var currentTesting=db.Testing.(t => t.id == obj.id).First();
TryUpdateModel(currentTesting);
db.SaveChanges();
return RedirectToAction("Index");
}
Doesn't this way break the MVC architecture? We work with database in the controller, not in the special Model class.
So, what is the best way to use TryUpdateModel in a real project?
Since the OP asked, here's an example of the ViewModel pattern, or as I like to call it - ASP.NET MVC done properly.
So why use a view specific model
We'll start with a simple entity:
public class Product {
public int Id {get;set;}
public string Name {get;set;}
public string Description {get;set;}
public decimal Price {get;set;}
}
And let's say you have a simple form where the user can only update the Name
and Description
of the product. But you're using (the very greedy) TryUpdateModel.
So I use any number of tools (like Fiddler) to construct a POST myself and send the following:
Name=WhatverIWant&Description=UnluckyFool&Price=0
Well the ASP.NET MVC model binder is going to inspect the input form collection, see that these properties exist on your entity and automatically bind them for you. So when you call "TryUpdateModel" on the entity you've just retrieved from your database, all of the matching properties will be updated (including the Price!). Time for a new option.
public class EditProductViewModel {
[HiddenInput]
public Guid Id {get;set;}
[Required]
[DisplayName("Product Name")]
public string Name {get;set;}
[AllowHtml]
[DataType(DataType.MultilineText)]
public string Description {get;set;}
}
This contains just the properties we need in our view. Notice we've also added some validation attributes, display attributes and some mvc specific attributes.
By not being restricted in what we have in our view model it can make your views much cleaner. For example, we could render out our entire edit form by having the following in our view:
@Html.EditorFor(model => model)
Mvc will inspect all of those attributes we've added to our view model and automatically wire up validation, labels and the correct input fields (i.e. a textarea for description).
[HttpPost]
public ActionResult EditProduct(EditProductViewModel model) {
var product = repository.GetById(model.Id);
if (product == null) {
return HttpNotFound();
}
// input validation
if (ModelState.IsValid) {
// map the properties we **actually** want to update
product.Name = model.Name;
product.Description = model.Description;
repository.Save(product);
return RedirectToAction("index");
}
return View(model)
}
It's fairly obvious from this code what it does. We don't have any undesirable effects when we update our entity since we are explicitly setting properties on our entity.
I hope this explains the View-Model pattern enough for you to want to use it.