Real Example TryUpdateModel, ASP.NET MVC 3

I cannot figure out how to use TryUpdateModel and save the MVC architecture at the same time.

If I am not mistaken, work with datacontexts should be in Model. So, such a code

var db=new TestEverybody();//it is class, which was generated by EntityFramework var currentTesting=db.Testing.(t => t.id == id).First(); 

should be in the model, not in the controller, right?

But the usual examples of using TryUpdateModel are as follows:

  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 violate the MVC architecture? We work with the database in the controller, and not in the special Model class.

So what is the best way to use TryUpdateModel in a real project?

+27
asp.net-mvc controller model
Oct 12 2018-11-11T00:
source share
2 answers

As the OP asked, here is an example ViewModel template, or whatever I like to call it - ASP.NET MVC is executed correctly.

So why use a specific view model

  • You should transmit information only to your opinion, which you need.
  • Often you need to add additional view meta data (such as title / description attributes). They do not belong to your entities.
  • Using TryUpdateModel / UpdateModel is incorrect. Do not use (I will explain why).
  • It is very rare that your view models will exactly match your objects. People often end up adding an extra jerk to their entities or (not much better) just using the ViewBag and not the strongly typed properties of the view model.
  • If you use ORM, you may encounter problems with Lazy loaded properties (N + 1). Your opinions should not cause inquiries.

We will start with a simple object:

 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 in which the user can only update the Product Name and Description . But you are using (very greedy) TryUpdateModel.

So I use any number of tools (like Fiddler) to create a POST and send the following:

Name = WhatverIWant & Description = UnluckyFool & Price = 0

Itโ€™s good that the ASP.NET MVC modelโ€™s middleware will check the collection of input forms, it can be seen that these properties exist on your entity and automatically bind them for you. Therefore, when you call "TryUpdateModel" on an entity that you just retrieved from your database, all relevant properties will be updated (including the price!). Time for a new option.

View specific model

 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 only the properties that we need in our view. Please note that we also added some validation attributes, display attributes, and some specific mvc attributes.

Not limited to what we have in our model, we can make your views cleaner. For example, we could display the entire editing form, having in our opinion the following:

 @Html.EditorFor(model => model) 

Mvc will check all the attributes that we have added to our view model and automatically include checks, labels, and the correct input fields (i.e. a text field for the description).

Form input

 [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) } 

From this code, it is pretty obvious what it does. We do not have any undesirable effects when we update our object, since we explicitly set properties for our entity.

Hope this explains the View-Model enough for you to use it.

+108
Oct 15 '11 at 9:45
source share

So, such code should be in the model, and not in the controller, right?

Not necessary. Personally, I prefer to put the data access code in the repository. Then use constructor injection to pass the specific repository implementation to the controller (for example, if I used EF, I would write an implementation of the EF repository). Thus, the controller will look like this:

 public class HomeController: Controller { private readonly IMyRepository _repository; public HomeController(IMyRepository repository) { _repository = repository; } public ActionResult Edit(int id) { var currentTesting = _repository.GetTesting(id); TryUpdateModel(currentTesting); _repository.SaveChanges(); return RedirectToAction("Index"); } } 
+18
Oct 12 '11 at 6:16
source share



All Articles