Подтвердить что ты не робот

Реальный пример TryUpdateModel, ASP.NET MVC 3

Я не могу понять, как использовать TryUpdateModel и сохранять архитектуру MVC в одно и то же время.

Если я не ошибаюсь, работа с datacontexts должна быть в Модели. Итак, такой код

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

должен находиться в модели, а не в контроллере, не так ли?

Но обычные примеры использования TryUpdateModel следующие:

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

Разве этот способ не нарушает архитектуру MVC? Мы работаем с базой данных в контроллере, а не в специальном классе Model.

Итак, каков наилучший способ использования TryUpdateModel в реальном проекте?

4b9b3361

Ответ 1

Поскольку OP спросил, вот пример шаблона ViewModel, или как мне нравится его называть - ASP.NET MVC выполнен правильно.

Итак, зачем использовать конкретную модель просмотра

  • Вы должны передавать информацию только на свое мнение, которое вам нужно.
  • Часто вам нужно добавить дополнительные мета-данные вида (такие как атрибуты заголовка/описания). Они не принадлежат вашим сущностям.
  • Использование TryUpdateModel/UpdateModel неверно. Не используйте (я объясню, почему).
  • Очень редко, что ваши модели просмотра будут точно соответствовать вашим объектам. Люди часто заканчивают тем, что добавили дополнительный рывок к своим сущностям или (не намного лучше), просто используя ViewBag, а не сильно типизированные свойства модели представления.
  • Если вы используете ORM, вы можете столкнуться с проблемами с Lazy загруженными свойствами (N + 1). Ваши мнения не должны вызывать запросы.

Мы начнем с простого объекта:

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

И скажем, у вас простая форма, в которой пользователь может только обновлять Name и Description продукта. Но вы используете (очень жадный) TryUpdateModel.

Поэтому я использую любое количество инструментов (например, Fiddler) для создания POST и отправляю следующее:

Имя = WhatverIWant & Описание = UnluckyFool & цена = 0

Хорошо, что связующее устройство модели ASP.NET MVC будет проверять коллекцию входных форм, видно, что эти свойства существуют на вашей сущности и автоматически связывают их для вас. Поэтому, когда вы вызываете "TryUpdateModel" на сущности, которую вы только что извлекли из своей базы данных, все соответствующие свойства будут обновлены (включая цену!). Время для новой опции.

Просмотреть конкретную модель

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

Это содержит только те свойства, которые нам нужны в нашем представлении. Обратите внимание, что мы также добавили некоторые атрибуты проверки, отображаемые атрибуты и некоторые специфические атрибуты mvc.

Не ограничиваясь тем, что у нас есть в нашей модели, мы можем сделать ваши взгляды более чистыми. Например, мы могли бы отобразить всю форму редактирования, имея на наш взгляд следующее:

@Html.EditorFor(model => model)

Mvc проверит все те атрибуты, которые мы добавили в нашу модель представления, и автоматически подключаем проверки, метки и правильные поля ввода (т.е. текстовое поле для описания).

Ввод формы

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

Из этого кода довольно очевидно, что он делает. У нас нет каких-либо нежелательных эффектов, когда мы обновляем наш объект, поскольку мы явно устанавливаем свойства для нашей сущности.

Надеюсь, это объяснит модель View-Model, достаточную для того, чтобы вы хотели ее использовать.

Ответ 2

Итак, такой код должен находиться в модели, а не в контроллере, не так ли?

Не обязательно. Лично я предпочитаю помещать код доступа к данным в репозиторий. Затем используйте инъекцию конструктора, чтобы передать определенную реализацию репозитория контроллеру (например, если я использовал EF, я бы написал реализацию репозитория EF). Таким образом, контроллер будет выглядеть следующим образом:

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