Пример MVC ViewModel

Я занимаюсь учебными пособиями и пытаюсь научиться лучшей практике, когда дело доходит до разработки MVC. Дизайн, который я использую ниже, представлен Pro ASP.Net MVC5 от Apress/Adam Freeman. Пока все идет хорошо... но я до сих пор не совсем понимаю, как работать с контроллерами. Да, я понимаю концепцию Контроллеров, но все еще борюсь, когда дело доходит до поста и получает методы. Вот поток моего примера приложения MVC:

Мой проект app.Domain

У меня есть пользовательская таблица в базе данных и ссылаюсь на нее с Entities/Users.cs

using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;

namespace app.Domain.Entities
{
public class Users
{
    [Key]
    public int UserID { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public string Email { get; set; }
    public string City { get; set; }
    public string State { get; set; }
    public DateTime CreateDate { get; set; }
    public DateTime LastLogin { get; set; }

}
}

Далее у меня есть интерфейс, и он расположен Аннотация /IUsersRepository.cs

using System;
using System.Collections.Generic;
using app.Domain.Entities;

namespace app.Domain.Abstract
{
public interface IUsersRepository
{
    IEnumerable<Users> Users { get; }
}
}

Двигаясь вперед, теперь я заполняю свои объекты Concrete/EFUsersRepository.cs

using System;
using System.Collections.Generic;
using app.Domain.Entities;
using app.Domain.Abstract;

namespace app.Domain.Concrete
{
public class EFUsersRepository : IUsersRepository
{
    private EFDbContext context = new EFDbContext();

    public IEnumerable<Users> Users
    {
        get { return context.Users; }
    }
}
}

Кроме того, в учебнике используется Ninject, который я понимаю, и все связано правильно. Я не буду публиковать этот код, если кто-то не попросит меня.

Вот мое приложение app.WebUI:

Учебник проводит меня через создание ViewModel. Здесь все становится немного нечетким для меня. Является ли ViewModel дополнительным каналом для получения объектов? Вместо того, чтобы ссылаться на сами модели, должен ли я всегда создавать ViewModels для SELECT, UPDATE, INSERT, DELETE данных (Models/UsersViewModel.cs)?

using System;
using System.Collections.Generic;
using app.Domain.Entities;

namespace app.WebUI.Models
{
public class UsersViewModel
{
    //public string FirstName { get; set; }
    //public string LastName { get; set; }
    //public string Email { get; set; }
    //public string City { get; set; }
    //public string State { get; set; }
    public IEnumerable<Users> Users { get; set; }
}
}

Сценарий заключается в том, что пользователь вводит электронное письмо, затем контроллер проверяет базу данных для электронной почты. Если он существует, переадресовываем его в "О представлении" (Controllers/HomeController.cs).

using System.Linq;
using System.Web.Mvc;
using app.Domain.Abstract;
using app.WebUI.Models;


namespace app.Controllers
{
public class HomeController : Controller
{
    private IUsersRepository repository;

    public HomeController(IUsersRepository usersRepository)
    {
        this.repository = usersRepository;
    }

    [HttpGet]
    public ActionResult Index()
    {
        return View();
    }

    [HttpPost]
    public ActionResult Index()
    {
        UsersViewModel userViewModel = new UsersViewModel()
        {
            Users = repository.Users
            .Where(p => p.Email == "[email protected]")
        };
        return View("About", userViewModel);

    }

    public ActionResult About()
    {
        ViewBag.Message = "Your application description page.";
        return View();
    }

    public ActionResult Contact()
    {
        ViewBag.Message = "Your contact page.";
        return View();
    }
}
}

И вот мой View (Home/Index.cshtml):

@model app.WebUI.Models.UsersViewModel

@{
    ViewBag.Title = "Home Page";
    Layout = "~/Views/Shared/_LayoutNoMenu.cshtml";
}


@foreach (var p in Model.Users)
{ 
<div class="container">
@using (Html.BeginForm("About", "Home", FormMethod.Get, new { @class = "begin-form" }))
{
    <h1>Welcome</h1>
    <div class="required-field-block">
    <textarea rows="1" class="form-control" placeholder="Email" id="filter"></textarea>
    </div>
    <button class="btn btn-primary" type="submit">Login</button>
}
</div>
}

Любые советы по правильному использованию ViewModel?

Ответ 1

В июне 2014 года я задал этот вопрос во время обучения MVC. На сегодняшний день я понимаю концепцию модели представления. Надеюсь, это поможет другому новичку MVC:

Моя модель, которая представляет таблицу базы данных:

public partial class County : Entity
{
    public int CountyID { get; set; }
    public string CountyName { get; set; }
    public string UserID { get; set; }
    public DateTime? CreatedDate { get; set; }
    public string ModifiedUserID { get; set; }
    public DateTime? ModifiedDate { get; set; }

    public virtual IList<Property> Properties { get; set; }
    public virtual DistrictOffice DistrictOffice { get; set; }
    public virtual IList<Recipient> Recipients { get; set; }
}

Существует два отношения один-ко-многим и отношение один-к-одному. Сущность и внедрение зависимостей. (Это не обязательно для объяснения модели представления.)

Во-первых, я создаю модель представления для временного хранилища для передачи из контроллера в представление. CountyViewModel.cs

public class CountyViewModel
{
    [HiddenInput]
    public int? CountyId { get; set; }

    [DisplayName("County Name")]
    [StringLength(25)]
    public string CountyName { get; set; }

    [DisplayName("Username")]
    [StringLength(255)]
    public string Username{ get; set; }
}

У вас есть возможность использовать имена и типы данных, отличные от вашей модели. Например, мой столбец базы данных - UserID, моя модель - UserID, но моя модель представления - UserName. Вам не нужно передавать данные в представление, которые не будут использоваться (например, всю модель). В этом примере нужны только три части модели County.

В моем контроллере я объявляю свою view-модель:

Мне нужны данные:

var county = _countyService.Get(countyId);

Следующий,

CountyViewModel countyViewModel = new CountyViewModel();
countyViewModel.CountyId = county.CountyID;
countyViewModel.CountyName = county.CountyName;
countyViewModel.UserName = county.UserID;

Вы также можете объявить так:

CountyViewModel countyViewModel = new CountyViewModel
{
    CountyId = county.CountyID,
    CountyName = county.CountyName,
    UserName = county.UserID
};

Теперь пришло время перейти к представлению:

return View(countyViewModel);

В представлении:

@model Project.Web.ViewModels.CountyViewModel

@{
    Layout = "~/Views/Shared/_Layout.cshtml";
 }

 <div>@Model.CountyName</div>
 @Html.HiddenFor(model => model.CountyId)

 <div>
 @Html.TextBoxFor(model => model.CountyName, new { @class = "form-control" })

Вот простой пример передачи данных с использованием viewmodel и использования сервисных вызовов в базу данных с Entity Framework:

Пример контроллера

public class PropertyController : Controller
{
    private readonly ICountyService _countyService;

    public PropertyController(ICountyService countyService)
        : base()
    {
        _countyService = countyService;
    }


    [HttpGet]
    public ActionResult NewProperty()
    {
        using (UnitOfWorkManager.NewUnitOfWork())
        {
            ListAllCountiesViewModel listAllCountyViewModel = new ListAllCountiesViewModel()
            {
                ListAllCounty = _countyService.ListOfCounties().ToList()
            };

            PropertyViewModel viewModel = new PropertyViewModel()
            {
                _listAllCountyViewModel = listAllCountyViewModel,
                _countyViewModel = new CountyViewModel(),
            };
            return View(viewModel);
        }
     }
 }

Пример ViewModels

public class CountyViewModel
{
    [HiddenInput]
    public int? CountyId { get; set; }

    [DisplayName("County Name")]
    [StringLength(25)]
    public string CountyName { get; set; }

    [DisplayName("County URL")]
    [StringLength(255)]
    public string URL { get; set; }
}

public class ListAllCountiesViewModel
{
    public string CountyName { get; set; }
    public IEnumerable<County> ListAllCounty { get; set; }
}

public class PropertyViewModel
{
    public ListAllCountiesViewModel _listAllCountyViewModel { get; set; }
    public CountyViewModel _countyViewModel { get; set; }
}

Пример сервисного уровня

public partial interface ICountyService
{
    County Get(int id);
    County GetByCompanyCountyID(int id);
    IEnumerable<County> ListOfCounties();
    void Delete(County county);
    IEnumerable<State> ListOfStates();
    void Add(County county);
    County SearchByName(string county);
}


public partial class CountyService : ICountyService
{
    private readonly ICountyRepository _countyRepository;

    public CountyService(ICountyRepository countryRepository)
    {
        _countyRepository = countryRepository;
    }

    /// <summary>
    /// Returns a county
    /// </summary>
    /// <param name="id"></param>
    /// <returns></returns>
    public County Get(int id)
    {
        return _countyRepository.Get(id);
    }

    /// <summary>
    /// Returns a county by County Id
    /// </summary>
    /// <param name="id"></param>
    /// <returns></returns>
    public County GetByCountyID(int id)
    {
        return _countyRepository.GetByMedicaidCountyID(id);
    }

    /// <summary>
    /// Returns all counties
    /// </summary>
    /// <returns></returns>
    public IEnumerable<County> ListOfCounties()
    {
        return _countyRepository.ListOfCounties();
    }

    /// <summary>
    /// Deletes a county
    /// </summary>
    /// <param name="county"></param>
    public void Delete(County county)
    {
        _countyRepository.Delete(county);
    }

    /// <summary>
    /// Return a static list of all U.S. states
    /// </summary>
    /// <returns></returns>
    public IEnumerable<State> ListOfStates()
    {
        var states = ServiceHelpers.CreateStateList(); 
        return states.ToList();
    }

    /// <summary>
    /// Add a county
    /// </summary>
    /// <param name="county"></param>
    public void Add(County county)
    {
        county.CreatedUserID = System.Web.HttpContext.Current.User.Identity.Name;
        county.CreatedDate = DateTime.Now;
        _countyRepository.Add(county);
    }

    /// <summary>
    /// Return a county by searching it name
    /// </summary>
    /// <param name="county"></param>
    /// <returns></returns>
    public County SearchByName(string county)
    {
        return _countyRepository.SearchByName(county);
    }
}

Пример уровня репозитория

public partial class CountyRepository : ICountyRepository
{
    private readonly Context _context;

    public CountyRepository(IContext context)
    {
        _context = context as Context;
    }

    public County Get(int id)
    {
        return _context.County.FirstOrDefault(x => x.CountyID == id);
    }

    public County GetByCompanyCountyID(int id)
    {
        return _context.County.FirstOrDefault(x => x.CountyID == id);
    }

    public IList<County> ListOfCounties()
    {
        return _context.County.ToList()
            .OrderBy(x => x.CountyName)  
            .ToList();
    }

    public void Delete(County county)
    {
        _context.County.Remove(county);
    }

    public County Add(County county)
    {
        _context.County.Add(county);
        return county;
    }

    public County SearchByName(string county)
    {
        return _context.County.FirstOrDefault(x => x.CountyName == county);
    }
}