Asp.net mvc 2 关于ASP.NET MVC 2自定义视图模型的问题

Asp.net mvc 2 关于ASP.NET MVC 2自定义视图模型的问题,asp.net-mvc-2,viewmodel,service-layer,Asp.net Mvc 2,Viewmodel,Service Layer,在我的项目中,我有我的Linq到SQL dbml文件,每个DB表有一个存储库层,每个存储库有一个服务层 在我的服务中,我有一些用于验证的元数据,并且我扩展了每个(表)类以向对象添加一些自定义信息(您将在下面的代码中看到这一点) 我的问题是,我是否应该考虑为每个(表)类建立一个自定义的VIEW模式,而不是在服务层使用扩展类?< /P> 下面是我现在拥有的一个例子 存储库 Namespace Domain #Region "Interface" Public Interface IUse

在我的项目中,我有我的Linq到SQL dbml文件,每个DB表有一个存储库层,每个存储库有一个服务层

在我的服务中,我有一些用于验证的元数据,并且我扩展了每个(表)类以向对象添加一些自定义信息(您将在下面的代码中看到这一点)

我的问题是,我是否应该考虑为每个(表)类建立一个自定义的VIEW模式,而不是在服务层使用扩展类?< /P> 下面是我现在拥有的一个例子

存储库

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 
服务

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 
现在我遇到的一件事是,每当我需要使用Slug时,都需要将user对象发送到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) 
因此,对于我来说,为每个(表)类创建一个自定义ViewModal并简单地执行以下操作是否更好

    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) 

在我看来,分离是件好事,但仍然需要大量的时间来构建。只是想知道权衡的好处,或者是否有更好的方法来完成同样的事情?

您可能会发现您的模型类并不总是与视图1:1对应。仅出于这个原因,创建ViewModel对象并使用它们与视图交互是有意义的,因为ViewModel对象可以是各种模型信息的组合

这样做的另一个好处是确保viewmodel对象特别适合用户界面,并且可能包含屏幕特定列表或其他与普通模型对象无关的属性。这允许您反过来实现好处,因为您的viewmodel对象不需要被任何东西弄乱/膨胀,除了它们在生活中的用途。(Linq到SQL对象必须跟踪状态,并完成与UI完全无关的大量工作。)

虽然分离是一种很好的做法,但正如你所说,它可能是一种“屁股痛”。为了使在类实例之间传输信息变得更容易,请查看哪种方法可以很好地实现这一点,并允许您消除无数行繁琐但必要的代码


快乐编码

很抱歉这个冗长的问题。谢谢你的见解。插入和编辑视图是否也使用ViewModal?是的,我几乎在所有情况下都使用viewmodel。我通常没有专门用于插入或编辑的视图,但当我这样做时,通常至少有一个下拉列表,我希望通过将列表作为ViewModel的属性传递给视图来填充该列表,以便在视图中填充dd。(在大多数情况下,我更喜欢使用我的ViewModel对象而不是ViewData[]
    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)