MVC'de ViewModel nedir?


429

ASP.NET MVC için yeniyim. Bir ViewModel'in amacını anlama konusunda bir sorunum var.

ViewModel nedir ve neden bir ASP.NET MVC uygulaması için bir ViewModel'e ihtiyacımız var?

Çalışması ve açıklaması hakkında iyi bir örnek alırsam daha iyi olur.


4
Bu yazı sizin için ne arıyor - "ASP.NET MVC ViewModel nedir?"
Yusubov

6
Bu makale harika görünüyor: rachelappel.com/…
Andrew

Yanıtlar:


607

A view model, ister statik metin ister veritabanına eklenebilecek (veya düzenlenebilir) giriş değerleri (metin kutuları ve açılır listeler gibi) için kullanılsın, görünümünüzde / sayfanızda görüntülemek istediğiniz verileri temsil eder. Bu seninkinden farklı bir şey domain model. Bu görünüm için bir model.

Diyelim ki Employeeçalışan alan modelinizi temsil eden bir sınıfınız var ve bu sınıf aşağıdaki özellikleri içeriyor (benzersiz tanımlayıcı, ad, soyadı ve oluşturulma tarihi):

public class Employee : IEntity
{
     public int Id { get; set; }

     public string FirstName { get; set; }

     public string LastName { get; set; }

     public DateTime DateCreated { get; set; }
}

Görünüm modelleri, yalnızca görünümünüzde kullanmak istediğiniz verileri (özelliklerle temsil edilir) içerdiği için alan modellerinden farklıdır. Örneğin, yeni bir çalışan kaydı eklemek istediğinizi varsayalım, görünüm modeliniz şöyle görünebilir:

public class CreateEmployeeViewModel
{
     public string FirstName { get; set; }

     public string LastName { get; set; }
}

Gördüğünüz gibi sadece iki özellik içeriyor. Bu iki özellik çalışan etki alanı modelindedir. Neden sorabilirsiniz? Idgörünümden ayarlanmamış olabilir, Çalışan tablosu tarafından otomatik olarak oluşturulabilir. Ayrıca DateCreatedsaklı yordamda veya uygulamanızın hizmet katmanında da ayarlanmış olabilir. Yani Idve DateCreatedgörünüm modelinde gerekli değildir. Bir çalışanın ayrıntılarını (önceden yakalanmış bir çalışan) statik metin olarak görüntülerken bu iki özelliği görüntülemek isteyebilirsiniz.

Görünümü / sayfayı yüklerken, çalışan denetleyicinizdeki eylem oluştur yöntemi bu görünüm modelinin bir örneğini oluşturur, gerekirse tüm alanları doldurur ve ardından bu görünüm modelini görünüme / sayfaya iletir:

public class EmployeeController : Controller
{
     private readonly IEmployeeService employeeService;

     public EmployeeController(IEmployeeService employeeService)
     {
          this.employeeService = employeeService;
     }

     public ActionResult Create()
     {
          CreateEmployeeViewModel model = new CreateEmployeeViewModel();

          return View(model);
     }

     public ActionResult Create(CreateEmployeeViewModel model)
     {
          // Do what ever needs to be done before adding the employee to the database
     }
}

Kişisel görünümü / sayfa kullandığınız varsayarak (aşağıdaki gibi görünebilir ASP.NET MVCveRazor görünümü motoru):

@model MyProject.Web.ViewModels.CreateEmployeeViewModel

<table>
     <tr>
          <td><b>First Name:</b></td>
          <td>@Html.TextBoxFor(m => m.FirstName, new { maxlength = "50", size = "50" })
              @Html.ValidationMessageFor(m => m.FirstName)
          </td>
     </tr>
     <tr>
          <td><b>Last Name:</b></td>
          <td>@Html.TextBoxFor(m => m.LastName, new { maxlength = "50", size = "50" })
              @Html.ValidationMessageFor(m => m.LastName)
          </td>
     </tr>
</table>

Dolayısıyla doğrulama sadece FirstNameve üzerinde yapılacaktır LastName. FluentValidation'ı kullanma şu şekilde doğrulama yapabilirsiniz:

public class CreateEmployeeViewModelValidator : AbstractValidator<CreateEmployeeViewModel>
{
     public CreateEmployeeViewModelValidator()
     {
          RuleFor(m => m.FirstName)
               .NotEmpty()
               .WithMessage("First name required")
               .Length(1, 50)
               .WithMessage("First name must not be greater than 50 characters");

          RuleFor(m => m.LastName)
               .NotEmpty()
               .WithMessage("Last name required")
               .Length(1, 50)
               .WithMessage("Last name must not be greater than 50 characters");
     }
}

Ve Veri Ek Açıklamaları ile şöyle görünebilir:

public class CreateEmployeeViewModel : ViewModelBase
{
    [Display(Name = "First Name")]
    [Required(ErrorMessage = "First name required")]
    public string FirstName { get; set; }

    [Display(Name = "Last Name")]
    [Required(ErrorMessage = "Last name required")]
    public string LastName { get; set; }
}

Hatırlanması gereken en önemli şey, görünüm modelinin yalnızca kullanmak istediğiniz verileri temsil etmesi , başka bir şey olmamasıdır . 30 özellikli bir etki alanı modeliniz varsa ve yalnızca tek bir değeri güncellemek istiyorsanız tüm gereksiz kodu ve doğrulamayı hayal edebilirsiniz. Bu senaryo göz önüne alındığında, etki alanı nesnesindeki tüm özelliklere değil, görünüm modelinde yalnızca bir değere / özelliğe sahip olursunuz.

Bir görünüm modelinde yalnızca bir veritabanı tablosundan veri bulunmayabilir. Başka bir tablodaki verileri birleştirebilir. Yeni bir çalışan kaydı ekleme ile ilgili yukarıdaki örneğimi ele alalım. Sadece ad ve soyadları eklemenin yanı sıra, çalışanın departmanını da eklemek isteyebilirsiniz. Bu departman listesi Departmentsmasanızdan gelecek . Şimdi Employeesve Departmentsgörünümlerinden bir görünüm modelinde tablolar var. Bundan sonra, görünüm modelinize aşağıdaki iki özelliği eklemeniz ve veriyle doldurmanız gerekir:

public int DepartmentId { get; set; }

public IEnumerable<Department> Departments { get; set; }

Çalışan verilerini (veritabanına zaten eklenmiş bir çalışan) düzenlerken, yukarıdaki örneğimden çok farklı olmaz. Bir görünüm modeli oluşturun, örneğin arayın EditEmployeeViewModel. Bu görünüm modelinde yalnızca ad ve soyadı gibi düzenlemek istediğiniz verilere sahip olun. Verileri düzenleyin ve gönder düğmesini tıklayın. Değer muhtemelen URL'de olacak Idçünkü alan hakkında çok fazla endişe olmaz Id, örneğin:

http://www.yourwebsite.com/Employee/Edit/3

Bunu alın Idve adınız ve soyadınızla birlikte depo katmanınıza iletin.

Bir kaydı silerken, normalde düzenleme görünümü modeliyle aynı yolu izlerim. Ayrıca bir URL olurdu, örneğin:

http://www.yourwebsite.com/Employee/Delete/3

Görünüm ilk kez yüklendiğinde Id3 kullanarak çalışanın veritabanından veri almak istiyorum. Sonra kullanıcı görünümün silinmiş görebilirsiniz, böylece benim görünüm / sayfa sadece statik metin görüntüler. Kullanıcı Sil düğmesini tıkladığında, yalnızca Id3 değerini kullanır ve depo katmanıma iletirim. Yalnızca Idbir kaydı tablodan silmeniz gerekir .

Başka bir nokta, her eylem için gerçekten bir görünüm modeline ihtiyacınız yok. Basit bir veri ise, sadece kullanmak iyi olur EmployeeViewModel. Karmaşık görünümler / sayfalar ve birbirlerinden farklıysa, her biri için ayrı görünüm modelleri kullanmanızı öneririm.

Umarım bu, görünüm modelleri ve alan modelleri hakkında yaşadığınız karışıklığı giderir.


5
@Kenny: Sonra göstermek :) Ne olduğunu söylemeye çalıştığım 50 özelliklerine ve görünüm yalnızca sonra sadece 5. gösterilecek 50 özelliklerine gönderme hiçbir kullanımıdır 5 görüntülemek için gereken bir alan modeli var diyelim
Brendan Vogt

5
@BrendanVogt - Bunu açıklayan iyi bir iş çıkardınız, ama "50 mülkün tamamını gönderme" nin maliyetinin ne olduğunu anlamıyorum. Diğer kod zaten tüm 50 özelliklere sahip bir model nesnesi yarattı ve sadece başka bir sınıf korumak için değerli görünmüyor değil 45 özelliklerini gönderiyorsunuz - özellikle olabilir gelecekte bu 45 özelliklerden birini göndermek istiyorum.
Kenny Evitt

5
@BrendanVogt - Sanırım LukLed'in cevabı, bunların neden yararlı olabileceğini anlamama yardımcı oluyor, özellikle de bir ViewModel (can) "... farklı veritabanı varlıklarından değerleri birleştiriyor" [ifadenin aynen geçerli olduğunu varsayıyorum " "" Model nesneleri "ile değiştirilecek veritabanı varlıkları". Ancak yine de, ViewModels'ın hangi spesifik sorunları ele alması amaçlanmıştır? Hiç bağlantınız var mı? Kendim hiçbir şey bulamadım. [Ve seni
seçiyorsam

1
Birisinin ViewModels'ın, viewBag'de doldurmak zorunda kalmadan tek bir görünüme birden çok koleksiyon (veya çapraz model özellikleri) göndermek için iyi bir yol olduğunu söylediğini duydum. Bana mantıklı geldi.
Ayyash

3
Kritik olduğum için üzgünüm ama bu cevap maalesef eksik. Bir görünüm modelini yalnızca sayfanızda görüntülenmesi gereken şey olarak tanımlamak, "Araba nedir?" ve "Bu bir uçak değil" cevabını alıyor. Peki bu doğru ama çok yararlı değil. Bir VM'nin en doğru tanımı "Sayfanızı oluşturmak için ihtiyacınız olan her şey" dir. Aşağıya doğru okursanız, VM'lerinizi doğru ve kolay bir şekilde oluşturmak için ihtiyaç duyduğunuz bileşenleri belirledim, çoğu durumda mevcut etki alanı modellerinizi ve sunum modellerinizi kullanın.
Sam

133

Görünüm modeli , belirli bir görünümde kullanılan veri modelini temsil eden bir sınıftır. Bu sınıfı bir giriş sayfası için model olarak kullanabiliriz:

public class LoginPageVM
{
    [Required(ErrorMessage = "Are you really trying to login without entering username?")]
    [DisplayName("Username/e-mail")]
    public string UserName { get; set; }
    [Required(ErrorMessage = "Please enter password:)")]
    [DisplayName("Password")]
    public string Password { get; set; }
    [DisplayName("Stay logged in when browser is closed")]
    public bool RememberMe { get; set; }
}

Bu görünüm modelini kullanarak görünümü tanımlayabilirsiniz (Jilet görünümü motoru):

@model CamelTrap.Models.ViewModels.LoginPageVM

@using (Html.BeginForm()) {
    @Html.EditorFor(m => m);
    <input type="submit" value="Save" class="submit" />
}

Ve eylemler:

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

[HttpPost]
public ActionResult LoginPage(LoginPageVM model)
{
    ...code to login user to application...
    return View(model);
}

Bu sonucu üretir (doğrulama formu ile form gönderildikten sonra ekran alınır):

Gördüğünüz gibi, bir görünüm modelinin birçok rolü vardır:

  • Görünüm modelleri, görünümü yalnızca temsil edilen alanları içererek bir görünümü belgeler.
  • Görünüm modelleri, veri ek açıklamalarını veya IDataErrorInfo kullanarak belirli doğrulama kuralları içerebilir.
  • Görünüm modeli bir görünüm (için nasıl görünmesi gerektiğini tanımlar LabelFor, EditorFor, DisplayForyardımcıları).
  • Görünüm modelleri, farklı veritabanı varlıklarından değerleri birleştirebilir.
  • Görünüm modelleri için kolayca görüntüleme şablonlarını belirleyebilir ve DisplayFor veya EditorFor yardımcılarını kullanarak birçok yerde yeniden kullanabilirsiniz.

Bir görünüm modeline ve erişimine başka bir örnek: Temel kullanıcı verilerini, ayrıcalıklarını ve kullanıcı adını göstermek istiyoruz. Yalnızca gerekli alanları içeren özel bir görünüm modeli oluşturuyoruz. Veritabanından farklı varlıklardan veri alırız, ancak görünüm yalnızca görünüm modeli sınıfının farkındadır:

public class UserVM {
    public int ID { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public bool IsAdministrator { get; set; }
    public string MothersName { get; set; }
}

alma:

var user = db.userRepository.GetUser(id);

var model = new UserVM() {
   ID = user.ID,
   FirstName = user.FirstName,
   LastName = user.LastName,
   IsAdministrator = user.Proviledges.IsAdministrator,
   MothersName = user.Mother.FirstName + " " + user.Mother.LastName
} 

Ben user.Mother.FirstName + "" + user.Mother.LastName View Model End'de yapılmalıdır. Tüm Mantık, Modeli Görüntüle sonunda yapılmalıdır.
Kurkula

3
@Chandana: Görünüm modelinde basit birleştirme yapılabileceğine inanıyorum. Birlikte sunulmaları isteniyorsa, iki alanı ortaya çıkarmak için hiçbir neden yoktur.
LukLed

82

Düzenleme: Blogumdaki bu yanıtı güncelledim:

http://www.samwheat.com/post/The-function-of-ViewModels-in-MVC-web-development

Cevabım biraz uzun, ancak neden farklı olduklarını ve neden gerekli olduklarını anlamak için görünüm modellerini yaygın olarak kullanılan diğer modellerle karşılaştırmanın önemli olduğunu düşünüyorum.

Özetlemek ve sorulan soruyu doğrudan cevaplamak için:

Genel olarak, bir görünüm modeli, bir görünümü oluşturmak için gerekli tüm özellikleri ve yöntemleri içeren bir nesnedir. Görünüm modeli özellikleri genellikle müşteriler ve siparişler gibi veri nesneleriyle ilgilidir ve ayrıca sayfa veya kullanıcı adı, uygulama adı vb. Gibi kendisiyle ilgili özellikler de içerir. Görünüm modelleri, bir oluşturma motoruna iletmek için uygun bir nesne sağlar bir html sayfası oluşturun. Bir görünüm modelini kullanmanın birçok nedeninden biri, görünüm modellerinin kullanıcı girişini işleme, verileri doğrulama, görüntüleme için veri alma gibi belirli sunum görevlerini birim olarak test etmenin bir yolunu sağlamasıdır.

Burada Varlık modelleri (a.ka. DTO's a.ka. modelleri), Sunum Modelleri ve Görünüm Modelleri karşılaştırılmıştır.

Veri Aktarım Nesneleri aka “Model”

Veri Aktarım Nesnesi (DTO), veritabanındaki tablo şemasına uyan özelliklere sahip bir sınıftır. DTO'lar, bir veri deposuna / veri deposundan veri aktarımı için ortak kullanımları olarak adlandırılır.
DTO'ların özellikleri:

• İş nesneleri - tanımları uygulama verilerine bağlıdır.

• Genellikle yalnızca özellikler içerir - kod yoktur.

• Öncelikle bir veritabanına ve veritabanından veri taşımak için kullanılır.

• Özellikler, veri deposundaki belirli bir tablodaki alanlarla tam olarak veya yakından eşleşir.

Veritabanı tabloları genellikle normalleştirilir, bu nedenle DTO'lar da genellikle normalleştirilir. Bu onları veri sunmak için sınırlı kullanım haline getirir. Bununla birlikte, bazı basit veri yapıları için genellikle oldukça iyi çalışırlar.

İşte DTO'ların nasıl görünebileceğine dair iki örnek:

public class Customer
{
    public int ID { get; set; }
    public string CustomerName { get; set; }
}


public class Order
{
    public int ID { get; set; }
    public int CustomerID { get; set; }
    public DateTime OrderDate { get; set; }
    public Decimal OrderAmount { get; set; }
}

Sunum Modelleri

Sunu modeli bir yardımcı programdır bir ekranda veya raporda veri oluşturmak için kullanılan sınıfıdır. Sunum modelleri tipik olarak birden çok DTO'dan elde edilen verilerden oluşan karmaşık veri yapılarını modellemek için kullanılır. Sunum modelleri genellikle verilerin normalleştirilmiş bir görünümünü temsil eder.

Sunum Modellerinin Özellikleri:

• İş nesneleri - tanımları uygulama verilerine bağlıdır.

• Çoğunlukla özellikler içerir. Kod genellikle verilerin biçimlendirilmesi veya bir DTO'ya veya bir DTO'dan dönüştürülmesi ile sınırlıdır. Sunum Modelleri iş mantığı içermemelidir.

• Genellikle verilerin normalden arındırılmış bir görünümünü sunar. Yani, genellikle birden çok DTO'dan gelen özellikleri birleştirirler.

• Genellikle bir DTO'dan farklı bir baz tipinde özellikler içerir. Örneğin, dolar tutarları virgül ve bir para birimi simgesi içerebilmeleri için dize olarak temsil edilebilir.

• Genellikle nasıl kullanıldıkları ve nesne özellikleri ile tanımlanır. Başka bir deyişle, bir ızgara oluşturmak için destekleme modeli olarak kullanılan basit bir DTO aslında bu ızgara bağlamında bir sunum modelidir.

Sunum modelleri “gerektiği gibi” ve “gerektiğinde” kullanılır (oysa DTO'lar genellikle veritabanı şemasına bağlıdır). Bir sunum modeli, bir sayfanın tamamı, bir sayfadaki ızgara veya bir sayfadaki ızgaradaki açılır listenin verilerini modellemek için kullanılabilir. Sunum modelleri genellikle diğer sunum modelleri olan özellikler içerir. Sunum modelleri genellikle tek bir sayfada belirli bir ızgara oluşturmak gibi tek kullanımlık bir amaç için oluşturulur.

Örnek bir sunum modeli:

public class PresentationOrder
{
    public int OrderID { get; set; }
    public DateTime OrderDate { get; set; }
    public string PrettyDate { get { return OrderDate.ToShortDateString(); } }
    public string CustomerName { get; set; }
    public Decimal OrderAmount { get; set; }
    public string PrettyAmount { get { return string.Format("{0:C}", OrderAmount); } }
}

Modelleri Görüntüle

Bir görünüm modeli, bir görünümü oluşturmak için bir destek sınıfı olan bir sunum modeline benzer. Ancak, bir Sunum Modeli veya bir DTO'dan nasıl oluşturulduğundan çok farklıdır. Görünüm modelleri genellikle sunum modelleri ve DTO'lar ile aynı özellikleri içerir ve bu nedenle genellikle diğeri için karıştırılırlar.

Görünüm Modellerinin Özellikleri:

• Sayfa veya ekran oluşturmak için kullanılan tek veri kaynağıdır. Bu genellikle bir görünüm modelinin, sayfadaki herhangi bir denetimin kendisini doğru bir şekilde oluşturması gereken her özelliği göstereceği anlamına gelir. Görünüm modelini görünüm için tek veri kaynağı yapmak, birim testi için kapasitesini ve değerini büyük ölçüde artırır.

• Uygulama verileri tarafından kullanılan özelliklerin yanı sıra uygulama verilerinden oluşan özellikler içeren bileşik nesnelerdir . Bu özellik, yeniden kullanılabilirlik için görünüm modelini tasarlarken çok önemlidir ve aşağıdaki örneklerde tartışılmıştır.

• Uygulama kodunu içerir. Görünüm Modelleri genellikle oluşturma sırasında ve kullanıcı sayfa ile etkileşime girdiğinde çağrılan yöntemleri içerir. Bu kod genellikle olay işleme, animasyon, kontrollerin görünürlüğü, stil vb.

• Verileri almak veya bir veritabanı sunucusuna göndermek amacıyla iş servislerini çağıran kodu içerir. Bu kod genellikle yanlışlıkla bir denetleyiciye yerleştirilir. İşletme hizmetlerini bir denetleyiciden çağırmak, genellikle görünüm testinin birim testi için yararlılığını sınırlar. Açık olmak gerekirse, görünüm modellerinin kendileri iş mantığı içermemeli, iş mantığı içeren hizmetlere çağrı yapmalıdır.

• Genellikle diğer sayfalar veya ekranlar için diğer görünüm modelleri olan özellikler içerir.

• “Sayfa başına” veya “ekran başına” yazılır. Bir uygulamadaki her sayfa veya ekran için genellikle benzersiz bir Görünüm Modeli yazılır.

• Çoğu sayfa ve ekran ortak özellikleri paylaştığından, genellikle bir temel sınıftan türetilir.

Model Kompozisyonunu Görüntüle

Daha önce belirtildiği gibi, görünüm modelleri, uygulama özelliklerini ve iş verileri özelliklerini tek bir nesne üzerinde birleştirdikleri için bileşik nesnelerdir. Görünüm modellerinde kullanılan yaygın olarak kullanılan uygulama özelliklerine örnekler:

• Hata durumları, kullanıcı adı, durum vb. Gibi uygulama durumunu görüntülemek için kullanılan özellikler.

• Denetimleri biçimlendirmek, görüntülemek, stilize etmek veya canlandırmak için kullanılan özellikler.

• Liste nesneleri gibi veri bağlama için kullanılan özellikler ve kullanıcı tarafından girilen ara verileri tutan özellikler.

Aşağıdaki örnekler, görünüm modellerinin bileşik yapısının neden önemli olduğunu ve bu verimli ve tekrar kullanılabilir bir Görünüm Modelini en iyi nasıl oluşturabileceğimizi göstermektedir.

Bir web uygulaması yazdığımızı varsayın. Uygulama tasarımının gereksinimlerinden biri, sayfa başlığının, kullanıcı adının ve uygulama adının her sayfada görüntülenmesi gerektiğidir. Bir sunum sırası nesnesini görüntülemek için bir sayfa oluşturmak istiyorsak, sunum modelini aşağıdaki gibi değiştirebiliriz:

public class PresentationOrder
{
    public string PageTitle { get; set; }
    public string UserName { get; set; }
    public string ApplicationName { get; set; }
    public int OrderID { get; set; }
    public DateTime OrderDate { get; set; }
    public string PrettyDate { get { return OrderDate.ToShortDateString(); } }
    public string CustomerName { get; set; }
    public Decimal OrderAmount { get; set; }
    public string PrettyAmount { get { return string.Format("{0:C}", OrderAmount); } }
}

Bu tasarım işe yarayabilir… ancak siparişlerin listesini görüntüleyecek bir sayfa oluşturmak istersek ne olur? PageTitle, UserName ve ApplicationName özellikleri tekrarlanacak ve üzerinde çalışılmayacaktır. Ayrıca, sınıfın yapıcısında sayfa düzeyinde bir mantık tanımlamak istersek ne olur? Görüntülenecek her sipariş için bir örnek oluşturursak bunu artık yapamayız.

Kalıtım üzerine kompozisyon

Sipariş sunumu modelini, gerçek bir görünüm modeli olacak ve tek bir PresentationOrder nesnesini veya bir PresentationOrder nesneleri koleksiyonunu görüntülemek için yararlı olacak şekilde yeniden hesaba katmanın bir yolu:

public class PresentationOrderVM
{
    // Application properties
    public string PageTitle { get; set; }
    public string UserName { get; set; }
    public string ApplicationName { get; set; }

    // Business properties
    public PresentationOrder Order { get; set; }
}


public class PresentationOrderVM
{
    // Application properties
    public string PageTitle { get; set; }
    public string UserName { get; set; }
    public string ApplicationName { get; set; }

    // Business properties
    public List<PresentationOrder> Orders { get; set; }
}

Yukarıdaki iki sınıfa baktığımızda, bir görünüm modeli hakkında düşünmenin bir yolunun, özellik olarak başka bir sunum modeli içeren bir sunum modeli olduğunu görebiliriz. Üst düzey sunum modeli (ör. Görünüm modeli) sayfa veya uygulama ile ilgili özellikler içerirken sunum modeli (özellik) uygulama verileriyle ilgili özellikler içerir.

Tasarımımızı bir adım öteye taşıyabilir ve yalnızca PresentationOrders için değil, diğer sınıflar için de kullanılabilecek bir temel görünüm modeli sınıfı oluşturabiliriz:

public class BaseViewModel
{
    // Application properties
    public string PageTitle { get; set; }
    public string UserName { get; set; }
    public string ApplicationName { get; set; }
}

Şimdi PresentationOrderVM'imizi şu şekilde basitleştirebiliriz:

public class PresentationOrderVM : BaseViewModel
{
    // Business properties
    public PresentationOrder Order { get; set; }
}

public class PresentationOrderVM : BaseViewModel
{
    // Business properties
    public List<PresentationOrder> Orders { get; set; }
}

BaseViewModel ürünümüzü genel hale getirerek daha da kullanılabilir hale getirebiliriz:

public class BaseViewModel<T>
{
    // Application properties
    public string PageTitle { get; set; }
    public string UserName { get; set; }
    public string ApplicationName { get; set; }

    // Business property
    public T BusinessObject { get; set; }
}

Şimdi uygulamalarımız zahmetsiz:

public class PresentationOrderVM : BaseViewModel<PresentationOrder>
{
    // done!
}

public class PresentationOrderVM : BaseViewModel<List<PresentationOrder>>
{
    // done!
}

2
Sam Teşekkür Ederim !! bu, çok yönlü varlığı şu şekilde kavramama yardımcı oldu: View-Model. Ben sadece MVC mimarisini öğrenen bir üniversite öğrencisiyim ve bu, geliştiriciye maruz kalan yeteneklerin bir kısmını açıklığa kavuşturdu. Yapabilseydim cevabının yanına bir yıldız koyardım.
Chef_Code

1
@Sam 'Görünüm modelleri genellikle sunum modelleri ve DTO'larla aynı özellikleri içerir ve bu nedenle genellikle diğeriyle karıştırılırlar.' Bu , sunum modelleri yerine yaygın olarak kullanıldıkları veya sunum modellerini / dtos'ları içermesi anlamına mı geliyor?
Alexander Derck

2
@AlexanderDerck Farklı amaçlar için kullanılırlar. Biri diğeri için karıştırılır (hatayla). Hayır, genellikle görünüm modeli yerine bir pres modeli kullanmayacaksınız. Çok daha yaygın olan, VM'nin sunum modelini "içerdiğidir" yani MyViewModel<MyPresModel>
Sam

2
@Sam Model nesnelerin canlı nesneler olduğunu varsayalım örneğin nhibernate modeller .. öyleyse BusinessObject ile model / canlı nesneleri doğrudan görünüme maruz bırakmıyor muyuz? yani iş nesnesi doğrudan veritabanı durumunu değiştirmek için kullanılabilir? Ayrıca, iç içe görünüm modelleri ne olacak? Bunun için birden çok iş nesnesi özelliği gerekir, değil mi?
Muhammed Ali

22

Görünüme özgü özellikleriniz varsa ve DB / Hizmet / Veri deposuyla ilgili değilseniz, ViewModels kullanmak iyi bir uygulamadır. Diyelim ki, bir DB alanına (veya ikisine) dayalı bir onay kutusunu seçili bırakmak istiyorsunuz, ancak DB alanının kendisi bir boolean değil. Bu özellikleri Modelin kendisinde oluşturmak ve onu veriye bağlanmaktan saklı tutmak mümkün olsa da, bu tür alanların ve işlemlerin miktarına bağlı olarak Modeli karıştırmak istemeyebilirsiniz.

Görünüme özgü çok az veri ve / veya dönüşüm varsa, Modelin kendisini kullanabilirsiniz


19

Tüm mesajları okumadım ama her cevabın gerçekten "anlamamı" sağlayan bir kavram eksik gibi görünüyor ...

Bir Model veritabanı Tablosuna benziyorsa, ViewModel bir veritabanına benzer Görünüm - Görünüm genellikle bir tablodan az miktarda veri döndürür veya birden çok tablodan (birleşme) karmaşık veri kümeleri döndürür.

Kendimi bir görünüme / forma bilgi aktarmak için ViewModels kullanarak ve sonra form denetleyiciye geri gönderildiğinde bu verileri geçerli bir Model'e aktarırken buluyorum - ayrıca Listeleri (IEnumerable) depolamak için çok kullanışlı.


11

MVC'nin bir görünüm modeli yoktur: bir modeli, görünümü ve denetleyicisi vardır. Viewmodel, MVVM'nin (Model-View-Viewmodel) bir parçasıdır. MVVM Sunum Modeli'nden türetilmiştir ve WPF'de popülerdir. MVVM'de de bir model olmalı, ancak çoğu insan bu modelin noktasını tamamen özlüyor ve sadece bir görüş ve bir model var. MVC'deki model MVVM'deki modele benzer.

MVC'de süreç 3 farklı sorumluluğa ayrılmıştır:

  • Görünüm, verileri kullanıcıya sunmaktan sorumludur
  • Sayfa akışından bir denetleyici sorumludur
  • Bir model iş mantığından sorumludur

MVC web uygulamaları için çok uygun değildir. Masaüstü uygulamaları oluşturmak için Smalltalk tarafından tanıtılan bir modeldir. Bir web ortamı tamamen farklı davranır. 40 yıllık bir konsepti masaüstü geliştirmeden kopyalamak ve bir web ortamına yapıştırmak pek mantıklı değil. Ancak birçok insan bunun iyi olduğunu düşünüyor, çünkü uygulamaları doğru değerleri derliyor ve döndürüyor. Yani, bence, belirli bir tasarım seçimini tamam olarak ilan etmek için yeterli değil.

Bir web uygulamasındaki bir model örneği şunlar olabilir:

public class LoginModel
{
    private readonly AuthenticationService authentication;

    public LoginModel(AuthenticationService authentication)
    {
        this.authentication = authentication;
    }

    public bool Login()
    {
        return authentication.Login(Username, Password);
    }

    public string Username { get; set; }
    public string Password { get; set; }
}

Kontrolör şu şekilde kullanabilir:

public class LoginController
{
    [HttpPost]
    public ActionResult Login(LoginModel model)
    {
        bool success = model.Login();

        if (success)
        {
            return new RedirectResult("/dashboard");
        }
        else
        {
            TempData["message"] = "Invalid username and/or password";
            return new RedirectResult("/login");
        }
    }
}

Denetleyici yöntemleriniz ve modelleriniz küçük, kolayca test edilebilir ve noktaya gelecektir.


MVVM mimarisine ilişkin anlayışınız için teşekkür ederiz, ancak MVC neden iyi değil? Akıl yürütmeniz şüphelidir ve kayırmacılığa şüphelidir. MVVM hakkında hiçbir şey bilmiyordum, ancak MVC gibi bir mimari 50k kod satırı yazmak zorunda kalmadan davranışı taklit edebilirse, o zaman büyük sorun nedir?
Chef_Code

@Chef_Code: Şüpheli ya da kayırmacılık değildir: MVC hakkındaki orijinal makaleyi okuyun. Kaynağa geri dönmek, sürüyü sorgulamadan körü körüne takip etmekten çok daha iyidir (aka "en iyi uygulamalar"). MVC çok daha küçük birimler içindir: örn. Ekrandaki bir düğme bir model, görünüm ve kontrolörden oluşur. Web-MVC'de tüm sayfa bir denetleyiciye, bir modele ve bir görünüme sahiptir. Model ve görünümün birbirine bağlı olması gerekir, böylece modeldeki değişiklikler hemen görünüme yansıtılır veya tersi de geçerlidir. Taklit etmek çok önemli. Bir mimari, geliştiricilerine yalan söylememelidir.
Jeroen

1
@jeroen MVC kısaltması çalındı ​​ve karıştırıldı. Evet MVC'nin bir VM'si yoktur ancak aynı zamanda bir Havuzu veya hizmet katmanı yoktur ve bu nesneler web sitelerinde yaygın olarak kullanılmaktadır. OP'nin "MVC'de VM'yi nasıl tanıtıp nasıl kullanacağımı" sorduğuna inanıyorum. MVC'nin yeni anlamında bir model iş mantığının ait olduğu bir model değildir. İş mantığı, MVC veya MVVM kullanan bir web veya masaüstü uygulaması için bir hizmet katmanına aittir. Model terimi, hizmet katmanına / hizmet katmanından iletilen iş nesnelerini açıklar. Bu tanımlar MVC'nin orijinal tanımından oldukça farklıdır.
Sam

1
@Sam Bir web sitesinin parçası olan her şey MVC'nin bir parçası olarak adlandırılamaz. MVC'nin yeni bir anlamı yok. Doğru anlamı ve "insanların MVC ile karıştırdığı tamamen ilgisiz bir şey" -meaning. Modelin iş mantığından sorumlu olduğunu söylemek, iş mantığının modelde kodlandığı ile aynı değildir. Çoğu zaman model uygulamaya bir cephe görevi görür.
Jeroen

Microsoft'un MVC'sinde gördüğüm ana kusur, bir Modelin bir Görünüm ile kilitlenmesidir. Bu, son 20 yılda N-Tier tasarımlarında devam eden tüm bu ayrımın tüm amacını yendi. Bizi 2002'de Web Dünyası'na çekilen bir başka Masaüstü esintili model olan "WebForms" ı kullanmaya zorlayarak zamanımızı boşa harcadılar. Şimdi bunu attılar, ancak web geliştirici için bu yeni paradigmada başka bir masaüstü modelini kaldırdılar. Bu arada Google ve diğerleri, hepsini ayıran devasa istemci tarafı modeller geliştiriyorlar. Im 1998 eski ASP VBScript düşünüyorum onların gerçek web dev sistemi oldu.
Stokely

11

Görünüm modeli a, birden fazla sınıf özelliği içerebilen basit bir sınıftır. Gerekli tüm özellikleri devralmak için kullanıyoruz, örneğin iki dersim var Öğrenci ve Konu

Public class Student
{
public int Id {get; set;}
public string Name {get; set;}
}  
Public class Subject
{
public int SubjectID {get; set;}
public string SubjectName {get; set;}
}

Şimdi kayıtları öğrencinin Adını ve Öznenin Adını Görünümde görüntülemek istiyoruz (MVC'de), ancak aşağıdaki gibi birden fazla sınıf eklemek mümkün değil:

 @model ProjectName.Model.Student  
 @model ProjectName.Model.Subject

yukarıdaki kod bir hata verir ...

Şimdi bir sınıf yaratıyoruz ve ona herhangi bir isim verebiliriz, ancak bu "XyzViewModel" biçiminin anlaşılmasını kolaylaştıracaktır. Kalıtım kavramdır. Şimdi aşağıdaki isimle üçüncü bir sınıf oluşturuyoruz:

public class StudentViewModel:Subject
{
public int ID {get; set;}
public string Name {get; set;}
}

Şimdi bu ViewModel'i View'da kullanıyoruz

@model ProjectName.Model.StudentViewModel

Artık View'da StudentViewModel ve miras alınan sınıfın tüm özelliklerine erişebiliyoruz.


10

Birçok büyük örnek, net ve gevrek bir şekilde açıklayayım.

ViewModel = Görünümü sunmak için oluşturulan model.

ASP.NET MVC görünümünde birden fazla model olamaz. ViewModel bu amaca hizmet eder.

Görünüm Modeli, yalnızca görünüm için gereken özellikleri barındırabilen bir model sınıfıdır. Ayrıca, veritabanının birden çok varlığından (tablolarından) özellikler de içerebilir. Adından da anlaşılacağı gibi, bu model Görünüm gereksinimlerine özel olarak oluşturulur.

Görüntüleme Modellerine birkaç örnek aşağıda verilmiştir

  • Bir görünüm sayfasında birden fazla varlıktan veri listelemek için bir Görünüm modeli oluşturabilir ve verilerini listelemek istediğimiz tüm varlıkların özelliklerine sahip olabiliriz. Bu veritabanı varlıklarına katılın ve Model özelliklerini görüntüle'yi ayarlayın ve farklı varlıkların verilerini tek bir sekmeli biçimde göstermek için Görünüm'e dönün
  • Görünüm modeli, Görünüm için gereken tek bir varlığın yalnızca belirli alanlarını tanımlayabilir.

ViewModel, kayıtları birden fazla objeye eklemek, güncellemek için de kullanılabilir, ancak ViewModel'in ana kullanımı, birden fazla objeden (model) sütunları tek bir görünümde görüntülemektir.

ViewModel oluşturma yöntemi Model oluşturma ile aynıdır, Viewmodel için görünüm oluşturma yöntemi Model için görünüm oluşturma ile aynıdır.

İşte küçük bir örnek ViewModel kullanarak Liste verilerinin .

Umarım faydalı olacaktır.


6

ViewModel, MVC çerçevesinin kavramsal becerikliliğini yatıran bir çözümdür. 3 katmanlı Model-Görünüm-Denetleyici mimarisinde 4. katmanı temsil eder. Model (alan modeli) uygun olmadığında, Görünüm için çok büyük (2-3 alandan daha büyük) olduğunda, onu Görünüme geçirmek için daha küçük ViewModel oluştururuz.


1

Görünüm modeli kavramsal bir veri modelidir. Bunun kullanımı, örneğin bir altküme almak veya farklı tablolardan veri birleştirmektir.

Yalnızca belirli özellikler isteyebilirsiniz, bu nedenle bu yalnızca ek yükleyici özellikleri yüklemenize izin verir, gereksiz gereksiz özellikleri yüklemenize olanak tanır


1
  • ViewModel, görünümde temsil edilen alanları içerir (LabelFor, EditorFor, DisplayFor yardımcıları için)
  • ViewModel, veri ek açıklamalarını veya IDataErrorInfo kullanarak belirli doğrulama kurallarına sahip olabilir.
  • ViewModel, farklı veri modellerinden veya veri kaynağından birden fazla varlığa veya nesneye sahip olabilir.

ViewModel Tasarlama

public class UserLoginViewModel 
{ 
[Required(ErrorMessage = "Please enter your username")] 
[Display(Name = "User Name")]
[MaxLength(50)]
public string UserName { get; set; }
 [Required(ErrorMessage = "Please enter your password")]
 [Display(Name = "Password")]
 [MaxLength(50)]
 public string Password { get; set; } 
} 

Viewmodel'i görünümde sunma

@model MyModels.UserLoginViewModel 
@{
 ViewBag.Title = "User Login";
 Layout = "~/Views/Shared/_Layout.cshtml";
}
@using (Html.BeginForm())
{
<div class="editor-label">
 @Html.LabelFor(m => m.UserName)
</div>
<div class="editor-field">
 @Html.TextBoxFor(m => m.UserName)
 @Html.ValidationMessageFor(m => m.UserName)
</div>
<div class="editor-label">
 @Html.LabelFor(m => m.Password)
</div>
<div class="editor-field">
 @Html.PasswordFor(m => m.Password)
 @Html.ValidationMessageFor(m => m.Password)
</div>
<p>
 <input type="submit" value="Log In" />
</p>
</div>
}

Eylemle Çalışma

public ActionResult Login()
{ 
return View();
}
[HttpPost]
public ActionResult Login(UserLoginViewModel user)
{
// To acces data using LINQ
DataClassesDataContext mobjentity = new DataClassesDataContext();
 if (ModelState.IsValid) 
{ 
try
 {
 var q = mobjentity.tblUsers.Where(m => m.UserName == user.UserName && m.Password == user.Password).ToList(); 
 if (q.Count > 0) 
 { 
 return RedirectToAction("MyAccount");
 }
 else
 {
 ModelState.AddModelError("", "The user name or password provided is incorrect.");
 }
 }
 catch (Exception ex)
 {
 } 
 } 
 return View(user);
} 
  1. ViewModel'de yalnızca görünümde / sayfada görüntülemek istediğiniz alanları / verileri yerleştirin.
  2. Görünüm, ViewModel'in özelliklerini temsil ettiğinden, oluşturma ve bakım kolaydır.
  3. ViewModel daha karmaşık hale geldiğinde bir eşleyici kullanın.

1

Görünüm Modeli, Görünüm'de veri oluşturmak için kullanabileceğimiz bir sınıftır. İki öğe Place ve PlaceCategory'niz olduğunu ve her iki varlıktaki verilere tek bir model kullanarak erişmek istediğinizi varsayalım, o zaman ViewModel kullanırız.

  public class Place
    {
       public int PlaceId { get; set; }
        public string PlaceName { get; set; }
        public string Latitude { get; set; }
        public string Longitude { get; set; }
        public string BestTime { get; set; }
    }
    public class Category
    {
        public int ID { get; set; }
        public int? PlaceId { get; set; }
        public string PlaceCategoryName { get; set; }
        public string PlaceCategoryType { get; set; }
    }
    public class PlaceCategoryviewModel
    {
        public string PlaceName { get; set; }
        public string BestTime { get; set; }
        public string PlaceCategoryName { get; set; }
        public string PlaceCategoryType { get; set; }
    }

Yukarıdaki Örnek Yer ve Kategori iki farklı varlıktır ve PlaceCategory viewmodel, View üzerinde kullanabileceğimiz ViewModel'dir.


Örnekleriniz o kadar net değil. Yukarıda belirtilenler ViewModel'in verileri görünümüne bağlamasıdır. BlipAjax'taki ViewModels'e bakarsanız, onun için mükemmel olan sınıfları görürsünüz.
Herman Van Der Blom

0

ViewModels ile bir "Baseline" web uygulamasını nasıl kuracağınızı öğrenmek istiyorsanız, bu kodu GitHub'a indirmenizi tavsiye edebilirim: https://github.com/ajsaulsberry/BlipAjax . Büyük kurumsal uygulamalar geliştirdim. Bunu yaptığınızda, tüm bu "ViewModel" işlevlerini işleyen iyi bir mimari kurmak sorunludur. Bence BlipAjax ile başlamak için çok iyi bir "temel" olacak. Sadece basit bir web sitesi, ama sadeliği harika. Uygulamada gerçekten neye ihtiyaç duyulduğunu göstermek için İngilizce dilini kullanma şeklini seviyorum.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.