Имеет ли смысл использовать ViewModel - PullRequest
2 голосов
/ 13 июля 2011

Я пробую себя в программировании MVC3.Просматривая примеры приложений, я часто вижу такие вещи, как ViewModels, дополнительные к моделям, представлениям и контроллерам.

Мой вопрос: имеет ли смысл их использовать?Если да: как и в чем разница между Model и ViewModel?

Большое спасибо!

Редактировать: Спасибо за ваши ответы:

Это значит, что у меня естьмодель Модель:

public string Username {get;set;}
public string mail{get;set;}
public string password{get;set;}
public string gender {get;set;}

And some methods like:
public int instertUserToDb()
{
...
}
public bool UserAllreadyExists()
{
...
}
public bool UpdateUserDatas()
{
...
}

Viewmodel не имеет связи с базой данных?И мне нужно создать ViewModel: NewUser, UpdateUser, UserDetails?

Правильно ли помещать в модель все такие вещи, как вставка, выбор и т. Д., И просто использовать ViewModel как шаблон для представления?Кто-нибудь знает хороший пример в интернете?

Спасибо большое!

Ответы [ 8 ]

8 голосов
/ 13 июля 2011

Мало того, что ViewModels - единственные, которые СЛЕДУЕТ использовать в MVC. Они дают ряд преимуществ, и основными из них являются статическая типизация и проверка времени компиляции. ViewData и ViewBag используют уродливые строки и динамические имена свойств, которые сложно поддерживать и подвержены ошибкам. В asp.net MVC M обозначает ViewModel s, а не доменные модели. Модели - это бизнес, доменные объекты, которые инкапсулируют бизнес-логику и предназначены для работы в домене. Модели остаются неизменными, несмотря на используемую технологию представления, будь то приложение Windows, Silverlight, ASP.NET MVC или другие. В отличие от этого, ViewModels в asp.net MVC - это классы, разработанные для работы в рамках MVC, они выполняют специфичные для контроллера и просматривают конкретные данные и позволяют упростить итерацию между моделями домена и контроллером. Например, при проектировании сущности пользователя в домене (модель)

public class User
{
    public string UserName { get; set; }
    public string Password { get; set; }
}

и при разработке контроллера входа в систему для вашего приложения - UserViewModel

public class UserViewModel
{
    public string UserName { get; set; }
    public string Password { get; set; }
    public string ConfirmPassword { get; set; }
    public string LoginHelpText { get; set; }
}

это не реальный пример, но вы должны увидеть основное отличие при разработке моделей представлений от моделей доменов. Как вы видите, ViewModels зависят от контроллера режима и действия и содержат данные для лучшего представления и итерации пользователя, в то время как доменные модели предназначены для работы в домене и не заботятся о представлении - для моделей домена никогда не требуется, например, второе поле ConfirmPassword. , Чтобы лучше использовать ViewModels с моделями доменов, вы можете взглянуть на AutoMapper и другие инструменты сообщества.

ViewModels не должна содержать ни логику доступа к данным для базы данных, ни бизнес-логику. В случае, Модели также не должны содержать доступ к базе данных. Для этого вам следует создать репозитории.

public interface IUserRepository
{
    int Create(User user);
    bool UserAlreadyExists(string userName);
    bool UpdateUserDatas(User user);
}

//than the implementation

public class UserRepository
{
    // Implementation of user repository.
}

//controller

public class UserController
{
    IUserRepository _userRepository;
    public UserController(IUserRepository userRepository)
    {
        _userRepository = userRepository ?? new UserRepository();// better to write this using Dependency Injection. Search google for Ninject, StructureMap, Unity, etc
    }

    public ActionResult Create(UserViewModel user)
    {
        if (ModelState.IsValid)
        {
            User domainUser = new User()
            {
                UserName = user.UserName // etc. written for simplicity, Use Automapper instead
            };
            _userRepository.Create(domainUser);// create user via repository
            return RedirectToAction("Index");
        }
        return View(user);
    }
}

Прочтите книгу Стивена Сандерсона про asp.net mvc 3 для полной информации

2 голосов
/ 13 июля 2011

Давайте приведем пример приложения для блога.Вот модель вашего блога;

  public class Blog {

    public int BlogID {get;set;}
    public string Title {get;set;}
    public DateTime PublishDate {get;set;}
    public string Content {get;set;}

  }

А вот модель вашего комментария;

  public class Comment {

    public int CommentID {get;set;}
    public int BlogID {get;set;}
    public string CommentContent {get;set;}
    public DateTime CommentDate {get;set;}
    public bool IsApproved {get;set;}

  }

Ниже показана ваша модель представления;

  public class BlogViewModel { 

    public Blog Blog {get;set;}
    public IEnumerable<Comment> Comments {get;set;}
  }

Когда вы создаетеПредставление строгого типа для класса BlogViewModel . Вы можете использовать свое представление следующим образом:

@model MyApp.BlogViewModel

<h2>@Model.Blog.Title</h2>

<p>
  @Model.Blog.Content
</p>

<div id="comments">

  <ul>

   @foreach(var item in Model.Comments) { 

    <li>@item.CommentContent</li>

   }

  </ul>

</div>

Чтобы использовать это представление работоспособным, ваш контроллер должен передать объект BlogViewModel в представление следующим образом;

  public ActionResult Blog(int id) { 

    //this is just an example here.
    //you need to put your logic here to get single Blog model
    var blogModel = myBlogRepo.GetSingleBlog(id);

    //this is just an example here.
    //you need to put your logic here to get IQueryable<Comment> model
    var commentsModel = myCommentRepo.GetAllCommnetsForBlog(id);

    BlogViewModel model = new BlogViewModel();
    model.Blog = blogModel;
    model.Comments = commentsModel;

    return View(model);

  }

Подобные ситуации являются наиболее разумными для использования ViewModel.Надеюсь, что это поможет.

2 голосов
/ 13 июля 2011

Модели являются объектами домена.Лучше всего использовать модели представления вместо объектов домена, поскольку иногда логика представления отличается от моделей вашего домена.См. Это Когда я использую View Models, Partials, Templates и обрабатываю дочерние привязки с MVC 3

0 голосов
/ 14 июля 2011

Вы украшаете свои доменные объекты материалами, связанными с презентацией. Например: пейджинг и категория

ProductsListViewModel productsListViewModel = new ProductsListViewModel {
        Products = _repository.GetAll(),
        PagingInfo = new PagingInfo {
            CurrentPage = page,
            ItemsPerPage = PageSize,
            TotalItems = _repository.GetAll().Count()
        },
        CurrentCategory = category
    };
0 голосов
/ 13 июля 2011

У меня обычно есть 3 слоя классов.Во-первых, ApplicationName.Domain, который содержит объекты POCO.Это объекты, используемые ORM для их сохранения (обычно в базе данных).Второй набор классов находится в папке Models приложения MVC.Это отображается с помощью AutoMapper внутри контроллера.Тогда третий набор классов находится в папке ViewModels приложения MVC.Эти последние используются как @model для представления.

Для объяснения структурирования.

  • Объекты POCO не должны ничего знать о представлении.Однако они должны знать о правилах данных.Я украшаю объекты POCO атрибутами, такими как RequiredAttribute или StringLengthAttribute.
  • Модели в приложении MVC должны знать о представлении того, как отображается каждое свойство.Я автоматически сопоставляю модели из классов POCO и украшаю их атрибутами, такими как DisplayAttribute и аналогичными.
  • Поскольку пользовательский интерфейс также должен знать о проверке, чтобы отобразить ошибки проверки, вы должны совместно использовать атрибуты правила данных между POCO и моделями.Вы можете сделать это с помощью мета-классов.Так, например, класс POCO User и класс Model UserModel совместно используют атрибут MetaClass, ссылающийся на UserMetaData.В этом случае вы можете достичь точно таких же правил для валидации приложения и уровня базы данных MVC.
  • Классы ViewModels, однако, используются, когда некоторые действительно сложные данные необходимо передать в представление.В соответствии с приведенным выше примером у меня будет UserViewModel, например, так:

    открытый класс UserViewModel {public UserModel User {get;задавать;} public IEnumerable {get;задавать;} public int?SelectedRoleId {get;задавать;}}

Модель представления компилируется в контроллере.Коллекция ролей - это не настоящие объекты POCO, а модели, так как вы можете автоматически сопоставлять роли, используя

var roles = _roleService.GetAll();
AutoMapper.Mapper.Map<IEnumerable<Role>, IEnumerable<RoleModel>>(roles);

В любом случае, короче говоря, идея Models и ViewModels заключается в том, что вы можете создавать все свое приложение, не беспокоясьо постоянстве (хранении объектов) и об этом позже.

0 голосов
/ 13 июля 2011

По моему мнению, настоящая причина, по которой существует MVVM, заключается в следующем: ViewModel необходим для использования в некоторых технологиях, таких как WPF, которые имеют ограниченную совместимость View с моделью. Благодаря этому ViewModel создается как промежуточное звено, чтобы сделать Модель более удобной для просмотра.

Как пример: в модели у вас есть простая переменная, но в представлении (поскольку представление WPF в большинстве случаев представлено XAML), вам необходимо свойство зависимости. Задача ViewModel - представить переменную Model в качестве свойства зависимости.

Если у вас есть возможность связать данные, как они есть между Model и View, модель ViewModel теряет свою полезность.

0 голосов
/ 13 июля 2011

M в MVC не обозначает Вид Модель, оно обозначает Модель. Модель может быть моделью представления, но может быть также моделью домена.

Я всегда использую модель предметной области, особенно для простых операций типа crud. Затем, когда придет время для дополнительной логики представления, я добавлю ViewModel, которая содержит логику представления. ИМХО, это придерживается принципа ЯГНИ. Просто убедитесь, что ваша доменная модель не содержит никакой логики представления, и переходите от этого.

0 голосов
/ 13 июля 2011

ViewModel позволяет вашему представлению работать с типизированным представлением данных, которые ему необходимы.Более того, если представление требует специальных вычислений (например, агрегировать несколько подэлементов), оно может вызвать некоторые события, которые вы не хотите видеть в представлении, например, запрос к базе данных, если объект-виноград загружен лениво, и т. Д... Построение ViewModel в слое Service / Controller / независимо от того, что позволяет вам избежать этих проблем

Если вам кажется, что ViewModels создает трудности, я бы рекомендовал использовать некоторые инструменты, такие как Automapper чтобы помочь вам сопоставить объекты модели с объектами ViewModel.

Короче говоря, да, Asp.Net MVC и ViewModels идут рука об руку:)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...