2014-06-28 15 views
8

Ho svolto esercitazioni e ho cercato di apprendere le best practice per lo sviluppo di MVC. Il design che sto usando di seguito proviene da Pro ASP.Net MVC5 di Apress/Adam Freeman. Finora, tutto sta andando bene ... ma non ho ancora imparato completamente a lavorare con i Controller. Sì, capisco il concetto di Controller, ma continuo a lottare quando si tratta di pubblicare e ottenere metodi. Ecco il flusso del mio campione applicazione MVC:MVC ViewModel example

Il mio progetto app.Domain

Ho una tabella utente nel database e di riferimento con Enti/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; } 

} 
} 

Successivamente, hanno un'interfaccia e si trova astratta/IUsersRepository.cs

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

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

si muove lungo, ora riempire i miei entità concrete/EFUsersRepository.cs

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

Inoltre, il libro di testo usa Ninject che capisco e tutto è legato correttamente. Non posterò quel codice a meno che qualcuno non me lo chieda.

Ecco la mia soluzione app.WebUI:

Il libro di testo mi guida attraverso la creazione di un ViewModel. Questo è dove le cose si fanno un po 'confuse per me. ViewModel è un canale aggiuntivo per ottenere le entità? Invece di fare riferimento ai Modelli stessi, dovrei sempre creare ViewModels su SELECT, UPDATE, INSERT, DELETE data (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; } 
} 
} 

Lo scenario è per l'utente che digita un'email, quindi il controllore controlla il database per l'e-mail. Se esiste, quindi reindirizzare alla vista Informazioni (Controller/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(); 
    } 
} 
} 

E qui è la mia opinione (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> 
} 

Qualche consiglio su come utilizzare correttamente un ViewModel?

+2

ViewModel dovrebbe rappresentare lo stato della vostra pagina. Ad esempio, se nella pagina è presente un pulsante di opzione, il modello di visualizzazione avrà una proprietà per lo stato del pulsante di opzione. Viste semplici potrebbero non avere alcuna necessità per un viewmodel, se tutto ciò che stanno facendo è visualizzare direttamente le viste senza ulteriori elementi. –

+0

Grazie Daniel. Quindi, una casella di testo vuota non avrebbe bisogno di un ViewModel. Ma una casella di testo che voglio popolare quando la vista viene caricata dovrebbe usare un ViewModel? – JoshYates1980

+0

Voglio dire popolare con i dati dal database. – JoshYates1980

risposta

8

Nel giugno 2014, ho fatto questa domanda mentre imparavo MVC. A partire da oggi, capisco il concetto di un modello visivo. Speriamo che questo aiuterà un altro principiante MVC:

Il mio modello che rappresenta la tabella del database:

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

Ci sono due uno-a-molti e una relazione uno-a-uno. Inquadramento delle entità e iniezione delle dipendenze. (Questo non è necessario per la spiegazione di modelmodello.)

Innanzitutto, creo un modello di visualizzazione per la memorizzazione temporanea da passare dal controller alla vista. 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; } 
} 

si ha la flessibilità di utilizzare nomi e tipi di dati diversi che il vostro modello. Ad esempio, la mia colonna di database è UserID, il mio modello è UserID, ma my viewmodel è UserName. E non è necessario passare dati alla vista che non verranno utilizzati (modello intero). Questo esempio richiede solo tre parti del modello County.

All'interno mio controller, dichiaro la mia vista del modello:

ho bisogno di dati:

var county = _countyService.Get(countyId); 

Avanti,

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

È possibile anche dichiarare in questo modo:

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

Ora è tempo per passare sulla View:

return View(countyViewModel); 

All'interno della Vista:

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

Ecco un semplice esempio di passaggio di dati utilizzando un ViewModel e utilizzando il servizio chiamate al database con Entity Framework:

Esempio controller

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

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

Esempio strato Servizio

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

Esempio strato Repository

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

Josh, da dove viene "_countyService"? L'unica menzione che ne fai è nel suo utilizzo. – muybn

+0

Ho aggiornato la mia risposta con un esempio di come my _countyService ottiene i dati. – JoshYates1980

+0

Questi livelli di servizio sono necessari? Non potresti semplicemente chiamare il tuo 'DbContext'? – Sinjai