web-dev-qa-db-fra.com

Exemple MVC ViewModel

J'ai fait des tutoriels et essayé d'apprendre les meilleures pratiques en matière de développement MVC. La conception que j'utilise ci-dessous provient de Pro ASP.Net MVC5 par Apress/Adam Freeman. Jusqu'à présent, tout se passe bien ... mais je n'ai toujours pas complètement compris comment travailler avec les contrôleurs. Oui, je comprends le concept des contrôleurs, mais j'ai toujours du mal à publier et à obtenir des méthodes. Voici le flux de mon exemple d'application MVC:

Mon projet de domaine d'application

J'ai une table d'utilisateurs dans la base de données et je la référence avec 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; }

}
}

Ensuite, j'ai une interface et elle se trouve Abstract/IUsersRepository.cs

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

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

En continuant, maintenant je remplis mes entités 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; }
    }
}
}

De plus, le manuel utilise Ninject que je comprends et tout est relié correctement. Je ne publierai pas ce code à moins que quelqu'un ne me le demande.

Voici ma solution app.WebUI:

Le manuel me guide à travers la création d'un ViewModel. C'est là que les choses deviennent un peu floues pour moi. Le ViewModel est-il un canal supplémentaire pour obtenir les entités? Au lieu de référencer les modèles eux-mêmes, dois-je toujours créer des ViewModels pour sélectionner, mettre à jour, insérer, supprimer des données (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; }
}
}

Le scénario consiste pour l'utilisateur à saisir un e-mail, puis le contrôleur vérifie la base de données pour l'e-mail. S'il existe, redirigez vers la vue À propos (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();
    }
}
}

Et voici ma vue (Accueil/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>
}

Des conseils sur la façon d'utiliser correctement un ViewModel?

18
JoshYates1980

En juin 2014, j'ai posé cette question tout en apprenant le MVC. Aujourd'hui, je comprends le concept d'un modèle de vue. J'espère que cela aidera un autre débutant MVC:

Mon modèle qui représente la table de base de données:

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

Il existe deux relations un-à-plusieurs et une relation un-à-un. Framework d'entité et injection de dépendances. (Cela n'est pas nécessaire pour l'explication du modèle d'affichage.)

Tout d'abord, je crée un modèle de vue pour le stockage temporaire à passer du contrôleur à la vue. 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; }
}

Vous avez la possibilité d'utiliser des noms et des types de données différents de ceux de votre modèle. Par exemple, ma colonne de base de données est UserID, mon modèle est UserID, mais mon viewmodel est UserName. Vous n'avez pas besoin de transmettre à la vue des données qui ne seront pas utilisées (par exemple, le modèle entier.) Cet exemple n'a besoin que de trois parties du modèle County.

Au sein de mon contrôleur, je déclare mon viewmodel:

J'ai besoin de données:

var county = _countyService.Get(countyId);

Prochain,

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

Vous pouvez également déclarer de cette façon:

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

Il est maintenant temps de passer la vue:

return View(countyViewModel);

Dans la vue:

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

Voici un exemple simple de transmission de données à l'aide d'un modèle de vue et d'utilisation d'appels de service à la base de données avec Entity Framework:

Exemple Contrôleur

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

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

Exemple Couche de service

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

Exemple Couche de référentiel

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);
    }
}
25
JoshYates1980