Exemplo real de TryUpdateModel, ASP .NET MVC 3

Não consigo entender como usar o TryUpdateModel e salvar a arquitetura do MVC ao mesmo tempo.

Se não me engano, o trabalho com datacontextos deve estar no modelo. Então, esse código

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

deve estar situado no Modelo, não no Controlador, não deve?

Mas os exemplos usuais do uso do TryUpdateModel são os seguintes:

  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"); } 

Isso não quebra a arquitetura MVC? Trabalhamos com database no controlador, não na class especial Model.

Então, qual é a melhor maneira de usar TryUpdateModel em um projeto real?

    Como o OP perguntou, aqui está um exemplo do padrão ViewModel, ou como eu gosto de chamá-lo – ASP.NET MVC feito corretamente.

    Então, por que usar um modelo específico de visão

    1. Você só deve passar as informações para a sua opinião de que precisa.
    2. Muitas vezes, você precisará adicionar metadados de visualização adicionais (como atributos title / description). Estes não pertencem às suas entidades.
    3. Usando TryUpdateModel / UpdateModel está errado. Não use (eu vou explicar porque).
    4. É muito raro que seus modelos de visualização correspondam exatamente às suas entidades. As pessoas geralmente acabam adicionando informações adicionais a suas entidades ou (não muito melhor) usando apenas ViewBag em vez de propriedades de modelo de visualização fortemente tipadas.
    5. Se você estiver usando um ORM, poderá encontrar problemas com as propriedades carregadas de Lazy (N + 1). Suas visualizações não devem emitir consultas.

    Vamos começar com uma entidade simples:

     public class Product { public int Id {get;set;} public string Name {get;set;} public string Description {get;set;} public decimal Price {get;set;} } 

    E digamos que você tenha um formulário simples em que o usuário possa atualizar apenas o Name e a Description do produto. Mas você está usando (o muito ganancioso) TryUpdateModel.

    Então eu uso qualquer número de ferramentas (como o Fiddler) para construir um POST e enviar o seguinte:

    Nome = WhatverIWant & Description = UnluckyFool & Price = 0

    Bem, o fichário de modelo da ASP.NET MVC vai inspecionar a coleção de formulários de input, ver se essas propriedades existem na sua entidade e vinculá-las automaticamente a você. Portanto, quando você chamar “TryUpdateModel” na entidade que acabou de recuperar de seu database, todas as propriedades correspondentes serão atualizadas (incluindo o Preço!). Hora de uma nova opção.

    Visualizar modelo específico

     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;} } 

    Isso contém apenas as propriedades que precisamos em nossa visão. Observe que também adicionamos alguns atributos de validação, atributos de exibição e alguns atributos específicos de mvc.

    Por não ser restrito no que temos em nosso modelo de visão, pode tornar suas visões muito mais limpas. Por exemplo, poderíamos processar todo o nosso formulário de edição, tendo o seguinte na nossa opinião:

     @Html.EditorFor(model => model) 

    O Mvc irá inspecionar todos os atributos que adicionamos ao nosso modelo de visualização e automaticamente fornecerá validação, labels e campos de input corretos (por exemplo, uma área de texto para descrição).

    POSTANDO O FORMULÁRIO

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

    É bastante óbvio a partir desse código o que ele faz. Não temos efeitos indesejáveis ​​quando atualizamos nossa entidade, pois estamos explicitamente definindo propriedades em nossa entidade.

    Espero que isso explique o padrão View-Model o suficiente para você querer usá-lo.

    Então, tal código deve estar situado no Modelo, não no Controlador, não deve?

    Não necessariamente. Pessoalmente, prefiro colocar o código de access a dados em um repository. Em seguida, use injeção de construtor para passar uma implementação de repository específica para o controlador (por exemplo, se eu estivesse usando o EF, eu escreveria uma implementação do repository do EF). Então o controlador ficará assim:

     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"); } }