Пример MVC ViewModel
Я делал уроки и пытался изучить лучшие практики, когда дело доходит до разработки MVC. Дизайн, который я использую ниже, взят из Pro ASP.Net MVC5 от Apress/Adam Freeman. Пока что все идет хорошо... но я все еще не совсем понял, как работать с контроллерами. Да, я понимаю концепцию контроллеров, но все еще борюсь, когда дело доходит до публикации и получения методов. Вот поток моего примера приложения MVC:
Мое приложение. Доменный проект
У меня есть пользовательская таблица в базе данных и ссылки на нее с 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 дополнительным каналом для получения сущностей? Вместо того, чтобы ссылаться на сами Модели, я должен всегда создавать ViewModel для ВЫБРАТЬ, ОБНОВИТЬ, ВСТАВИТЬ, УДАЛИТЬ данные (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 == "LearningMVC5@gmail.com")
};
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();
}
}
}
А вот мой вид (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.
Внутри моего контроллера я объявляю свою модель вида:
Мне нужны данные:
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's 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);
}
}