2010-07-12 4 views
0

Dans mon projet, j'ai mon fichier Linb To SQL dbml, Un Couche Repository pour chaque Table DB et un Couche Service pour chaque Repository.Question à propos de ASP.NET MVC 2 Custom ViewModels

Dans mon service, j'ai des méta-données pour la validation et j'étends chaque classe (table) pour ajouter des informations personnalisées à l'objet (vous le verrez dans le code ci-dessous).

Ma question est: Dois-je envisager de créer un ViewModal personnalisé pour chaque classe (table) au lieu d'utiliser la classe étendue dans la couche de service?

Voici un exemple de ce que j'ai maintenant.

dépôt

Namespace Domain 
#Region "Interface" 
    Public Interface IUserRepository 
     Sub AddUser(ByVal openid As OpenID) 
     Function GetUsers() As IQueryable(Of User) 
     Sub UpdateUser(ByVal user As User) 
     Sub SubmitChanges() 
    End Interface 
#End Region 
#Region "Repository" 
    Public Class UserRepository : Implements IUserRepository 
     Private dc As MyDatabaseDataContext 
     Public Sub New() 
      dc = New MyDatabaseDataContext 
     End Sub 

     Public Sub AddUser(ByVal openid As OpenID) Implements IUserRepository.AddUser 
      Dim user As New User 
      user.MemberSince = DateTime.Now 
      openid.User = user 

      dc.OpenIDs.InsertOnSubmit(openid) 
     End Sub 

     Public Function GetUsers() As IQueryable(Of User) Implements IUserRepository.GetUsers 
      Dim users = (From u In dc.Users 
         Select u) 
      Return users.AsQueryable 
     End Function 

     Public Sub UpdateUser(ByVal user As User) Implements IUserRepository.UpdateUser 
      Dim _user = (From u In dc.Users 
       Where u.ID = user.ID 
       Select u).Single 

      With _user 
       .About = user.About 
       .BirthDate = user.BirthDate 
       .Email = user.Email 
       .isClosed = user.isClosed 
       .isProfileComplete = user.isProfileComplete 
       .RegionID = user.RegionID 
       .Reputation = user.Reputation 
       .UserName = user.UserName 
       .WebSite = user.WebSite 
      End With 

     End Sub 

     Public Sub SubmitChanges() Implements IUserRepository.SubmitChanges 
      dc.SubmitChanges() 
     End Sub 
    End Class 
#End Region 
End Namespace 

service

Imports System.ComponentModel.DataAnnotations 

Namespace Domain 
#Region "Validation" 
    <MetadataType(GetType(UserMetaData))> _ 
    Partial Public Class User 
     Public Property UserRegion As String 
     Public Property LastSeen As DateTime 
     Public ReadOnly Property Slug(ByVal user As User) As String 
      Get 
       Return Replace(user.UserName, " ", "-") 
      End Get 
     End Property 
    End Class 


    ''' <summary> 
    ''' Validation for all User data. 
    ''' </summary> 
    ''' <remarks>All validation is done at the Service Layer</remarks> 
    Public Class UserMetaData 

     <DisplayName("name")> _ 
     <Required(ErrorMessage:="Username is required.")> _ 
     <StringLength(30, ErrorMessage:="Username cannot exceed 30 characters.")> _ 
     <RegularExpression("^\w{3,30}$", ErrorMessage:="Not a valid username.")> _ 
     Public Property UserName As String 

     <DisplayName("email")> _ 
     <StringLength(50, ErrorMessage:="Email Address cannot exceed 50 characters.")> _ 
     <RegularExpression("^([a-zA-Z0-9_\-\.]+)@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.)|(([a-zA-Z0-9\-]+\.)+))([a-zA-Z]{2,4}|[0-9]{1,3})$", ErrorMessage:="Not a valid email address.")> _ 
     Public Property Email As String 

     <DisplayName("website")> _ 
     <StringLength(256, ErrorMessage:="Web Address cannot exceed 256 characters.")> _ 
     <RegularExpression("^http(s?)\://[a-zA-Z0-9\-\.]+\.[a-zA-Z]{2,3}(/\S*)?$", ErrorMessage:="Not a valid website address.")> _ 
     Public Property WebSite As String 

     <DisplayName("about")> _ 
     <StringLength(2000, ErrorMessage:="Profile cannot exceed 2000 characters.")> _ 
     Public Property About As String 

     <DisplayName("region")> _ 
     <Required(ErrorMessage:="Region is required.")> _ 
     Public Property UserRegion As Integer 

     <DisplayName("birthdate")> _ 
     <DisplayFormat(ApplyFormatInEditMode:=True, ConvertEmptyStringToNull:=True, DataFormatString:="{0:MM/dd/yyyy}")> _ 
     Public Property BirthDate As DateTime 

    End Class 
#End Region 
#Region "Interface" 
    Public Interface IUserService 
     Sub AddUser(ByVal claimedidentifier As String, ByVal notes As String) 
     Function GetAllUsers() As IList(Of User) 
     Function GetUserByID(ByVal id As Integer) As User 
     Sub UpdateUser(ByVal user As User) 
     Sub SubmitChanges() 
    End Interface 
#End Region 
#Region "Service" 
    Public Class UserService : Implements IUserService 
     Private _UserRepository As IUserRepository 
     Public Sub New(ByVal UserRepository As IUserRepository) 
      _UserRepository = UserRepository 
     End Sub 

     Public Sub AddUser(ByVal claimedidentifier As String, ByVal notes As String) Implements IUserService.AddUser 
      Dim openid As New OpenID 
      openid.ClaimedIdentifier = claimedidentifier 
      openid.UserNotes = notes 
      _UserRepository.AddUser(openid) 
     End Sub 

     Public Function GetAllUsers() As System.Collections.Generic.IList(Of User) Implements IUserService.GetAllUsers 
      Return _UserRepository.GetUsers().Where(Function(u) (Not u.isClosed)).ToList 
     End Function 

     Public Function GetUserByID(ByVal id As Integer) As User Implements IUserService.GetUserByID 
      Return _UserRepository.GetUsers().Where(Function(u) (Not u.isClosed And u.ID = id)).SingleOrDefault 
     End Function 

     Public Sub UpdateUser(ByVal user As User) Implements IUserService.UpdateUser 
      _UserRepository.UpdateUser(user) 
     End Sub 

     Public Sub SubmitChanges() Implements IUserService.SubmitChanges 
      _UserRepository.SubmitChanges() 
     End Sub 

    End Class 
#End Region 

End Namespace 

Et actuellement dans mon contrôleur j'envoie Modal données à mon avis comme celui-ci

Dim user As Domain.User = UserService.GetUserByID(id) 
    Return View(user) 

Maintenant une chose que j'ai courir en est la nécessité envoyer l'objet utilisateur à la propriété Slug chaque fois que je dois utiliser le Slug

Dim user As Domain.User = UserService.GetUserByID(id) 
    user.Slug = user.Slug(user) ''# this seems like a bit of a pain in the ass 
    Return View(user) 

donc à cause de cela, est-il préférable pour moi de créer un ViewModal de commande pour chaque (tableau) de classe et tout simplement faire le suivant

Dim user As Domain.UserViewModal = New Domain.UserViewModal(UserService.GetUserByID(id)) 
    ''# The UserViewModal will automatically do all the work to create the 
    ''# Slug as well as other pertinent information 
    Return View(user) 

Il me semble que la séparation est une bonne chose, mais nécessite encore une charge de temps pour construire. Je me demandais juste à propos du compromis ou s'il y a une meilleure façon d'accomplir la même chose?

+0

désolé pour la question à long terme. –

Répondre

1

Vous allez probablement trouver que vos classes de modèles ne correspondent pas toujours 1: 1 avec les vues. Pour cette seule raison, il est logique de créer des objets ViewModel et de les utiliser pour interagir avec vos vues, car un objet viewmodel peut être un composite de diverses informations de modèle. Cela a l'avantage supplémentaire de s'assurer que vos objets viewmodel sont spécifiquement adaptés à l'interface utilisateur et peuvent contenir des listes spécifiques à l'écran ou d'autres propriétés qui n'ont rien à voir avec un objet modèle normal. Cela vous permet de réaliser des avantages inversement, car vos objets viewmodel ne doivent pas être encombrés/gonflés avec quoi que ce soit, sauf leur but dans la vie. (Les objets Linq to SQL doivent suivre l'état et accomplir toute une série de choses complètement indépendantes de l'interface utilisateur.)

Bien que la séparation soit une bonne pratique, elle peut être une "douleur dans la crosse" comme vous le dites. Pour faciliter le transfert d'informations entre les instances de votre classe, regardez Automapper, ce qui fait très bien et vous permet d'éliminer d'innombrables lignes de code fastidieux mais nécessaire.

Bonne codification!

+0

merci pour les idées. Utilisez-vous également ViewModal pour vos vues Insérer et Modifier? –

+0

Oui, j'utilise un viewmodel dans presque tous les cas. Je n'ai généralement pas de vue dédiée à l'insertion ou à l'édition, mais quand je le fais, il y a généralement au moins une liste déroulante que je voudrais remplir en passant une List comme propriété du ViewModel au Voir afin de peupler le dd dans la vue.(Je préfère utiliser mes objets ViewModel à ViewData [] dans la plupart des cas.) – Tahbaza

Questions connexes