Aracılığıyla paylaş


Hizmet Katmanı ile Doğrulama (VB)

tarafından Stephen Walther

Doğrulama mantığınızı denetleyici eylemlerinizin dışına ve ayrı bir hizmet katmanına nasıl taşıyacağınızı öğrenin. Bu öğreticide Stephen Walther, hizmet katmanınızı denetleyici katmanınızdan yalıtarak endişeleri net bir şekilde ayırmayı nasıl sürdürebileceğinizi açıklamaktadır.

Bu öğreticinin amacı, bir ASP.NET MVC uygulamasında doğrulama gerçekleştirme yönteminden birini açıklamaktır. Bu öğreticide doğrulama mantığınızı denetleyicilerinizden dışarı ve ayrı bir hizmet katmanına taşımayı öğreneceksiniz.

Endişeleri Ayırma

bir ASP.NET MVC uygulaması oluşturduğunuzda, veritabanı mantığınızı denetleyici eylemlerinizin içine yerleştirmemelisiniz. Veritabanınızı ve denetleyici mantığınızı karıştırmak, uygulamanızın zaman içinde bakımının daha zor olmasını sağlar. Öneri, tüm veritabanı mantığınızı ayrı bir depo katmanına yerleştirmenizdir.

Örneğin, Liste 1, ProductRepository adlı basit bir depo içerir. Ürün deposu, uygulamanın tüm veri erişim kodunu içerir. Liste ayrıca ürün deposunun uyguladığı IProductRepository arabirimini de içerir.

Listeleme 1 - Models\ProductRepository.vb

Public Class ProductRepository
Implements IProductRepository

    Private _entities As New ProductDBEntities()


Public Function ListProducts() As IEnumerable(Of Product) Implements IProductRepository.ListProducts
    Return _entities.ProductSet.ToList()
End Function


Public Function CreateProduct(ByVal productToCreate As Product) As Boolean Implements IProductRepository.CreateProduct
    Try
        _entities.AddToProductSet(productToCreate)
        _entities.SaveChanges()
        Return True
    Catch
        Return False
    End Try
End Function

End Class

Public Interface IProductRepository
Function CreateProduct(ByVal productToCreate As Product) As Boolean
Function ListProducts() As IEnumerable(Of Product)
End Interface

Listeleme 2'deki denetleyici hem Index() hem de Create() eylemlerinde depo katmanını kullanır. Bu denetleyicinin herhangi bir veritabanı mantığı içermediğini fark edin. Depo katmanı oluşturmak, endişelerin temiz bir şekilde ayrılmasını sağlamanıza olanak tanır. Denetleyiciler uygulama akışı denetim mantığından, depo ise veri erişim mantığından sorumludur.

Liste 2 - Controllers\ProductController.vb

Public Class ProductController
Inherits Controller

    Private _repository As IProductRepository

Public Sub New()
    Me.New(New ProductRepository())
End Sub


Public Sub New(ByVal repository As IProductRepository)
    _repository = repository
End Sub


Public Function Index() As ActionResult
    Return View(_repository.ListProducts())
End Function


'
' GET: /Product/Create

Public Function Create() As ActionResult
    Return View()
End Function

'
' POST: /Product/Create

<AcceptVerbs(HttpVerbs.Post)> _
Public Function Create(<Bind(Exclude:="Id")> ByVal productToCreate As Product) As ActionResult
    _repository.CreateProduct(productToCreate)
    Return RedirectToAction("Index")
End Function

End Class

Hizmet Katmanı Oluşturma

Bu nedenle, uygulama akışı denetim mantığı bir denetleyiciye, veri erişim mantığı da bir depoya aittir. Bu durumda doğrulama mantığınızı nereye koyarsınız? Bir seçenek, doğrulama mantığınızı bir hizmet katmanına yerleştirmektir.

Hizmet katmanı, bir ASP.NET MVC uygulamasında denetleyici ile depo katmanı arasındaki iletişime aracılık eden ek bir katmandır. Hizmet katmanı iş mantığı içerir. Özellikle doğrulama mantığı içerir.

Örneğin, Liste 3'teki ürün hizmeti katmanında CreateProduct() yöntemi vardır. CreateProduct() yöntemi, ürünü ürün deposuna geçirmeden önce yeni bir ürünü doğrulamak için ValidateProduct() yöntemini çağırır.

Listeleme 3 - Models\ProductService.vb

Public Class ProductService
Implements IProductService

Private _modelState As ModelStateDictionary
Private _repository As IProductRepository

Public Sub New(ByVal modelState As ModelStateDictionary, ByVal repository As IProductRepository)
    _modelState = modelState
    _repository = repository
End Sub

Protected Function ValidateProduct(ByVal productToValidate As Product) As Boolean
    If productToValidate.Name.Trim().Length = 0 Then
        _modelState.AddModelError("Name", "Name is required.")
    End If
    If productToValidate.Description.Trim().Length = 0 Then
        _modelState.AddModelError("Description", "Description is required.")
    End If
    If productToValidate.UnitsInStock

Ürün denetleyicisi Liste 4'te depo katmanı yerine hizmet katmanını kullanacak şekilde güncelleştirildi. Denetleyici katmanı, hizmet katmanıyla konuşur. Hizmet katmanı, depo katmanıyla konuşur. Her katmanın ayrı bir sorumluluğu vardır.

Liste 4 - Controllers\ProductController.vb

Public Class ProductController
Inherits Controller

Private _service As IProductService

Public Sub New()
    _service = New ProductService(Me.ModelState, New ProductRepository())
End Sub

Public Sub New(ByVal service As IProductService)
    _service = service
End Sub


Public Function Index() As ActionResult
    Return View(_service.ListProducts())
End Function


'
' GET: /Product/Create

Public Function Create() As ActionResult
    Return View()
End Function

'
' POST: /Product/Create

<AcceptVerbs(HttpVerbs.Post)> _
Public Function Create(<Bind(Exclude := "Id")> ByVal productToCreate As Product) As ActionResult
    If Not _service.CreateProduct(productToCreate) Then
        Return View()
    End If
    Return RedirectToAction("Index")
End Function

End Class

Ürün hizmetinin ürün denetleyicisi oluşturucusunda oluşturulduğuna dikkat edin. Ürün hizmeti oluşturulduğunda, model durumu sözlüğü hizmete geçirilir. Ürün hizmeti, doğrulama hata iletilerini denetleyiciye geri geçirmek için model durumunu kullanır.

Hizmet Katmanını Ayırma

Denetleyici ve hizmet katmanlarını bir açıdan yalıtamadık. Denetleyici ve hizmet katmanları model durumu aracılığıyla iletişim kurar. Başka bir deyişle hizmet katmanı, ASP.NET MVC çerçevesinin belirli bir özelliğine bağımlıdır.

Hizmet katmanını denetleyici katmanımızdan mümkün olduğunca yalıtmak istiyoruz. Teoride, hizmet katmanını yalnızca ASP.NET bir MVC uygulamasıyla değil, her tür uygulamayla kullanabilmemiz gerekir. Örneğin, gelecekte uygulamamız için bir WPF ön ucu oluşturmak isteyebiliriz. hizmet katmanımızdan ASP.NET MVC model durumu bağımlılığını kaldırmanın bir yolunu bulmalıyız.

Liste 5'te, hizmet katmanı artık model durumunu kullanamayacak şekilde güncelleştirilmiştir. Bunun yerine, IValidationDictionary arabirimini uygulayan herhangi bir sınıfı kullanır.

Listeleme 5 - Models\ProductService.vb (ayrılmış)

Public Class ProductService
Implements IProductService

Private _validatonDictionary As IValidationDictionary
Private _repository As IProductRepository

Public Sub New(ByVal validationDictionary As IValidationDictionary, ByVal repository As IProductRepository)
    _validatonDictionary = validationDictionary
    _repository = repository
End Sub

Protected Function ValidateProduct(ByVal productToValidate As Product) As Boolean
    If productToValidate.Name.Trim().Length = 0 Then
        _validatonDictionary.AddError("Name", "Name is required.")
    End If
    If productToValidate.Description.Trim().Length = 0 Then
        _validatonDictionary.AddError("Description", "Description is required.")
    End If
    If productToValidate.UnitsInStock

IValidationDictionary arabirimi Listeleme 6'da tanımlanır. Bu basit arabirimin tek bir yöntemi ve tek bir özelliği vardır.

Listeleme 6 - Models\IValidationDictionary.cs

Public Interface IValidationDictionary
Sub AddError(ByVal key As String, ByVal errorMessage As String)
ReadOnly Property IsValid() As Boolean
End Interface

Listing 7'deki ModelStateWrapper sınıfı adlı sınıf, IValidationDictionary arabirimini uygular. Oluşturucuya bir model durum sözlüğü geçirerek ModelStateWrapper sınıfının örneğini oluşturabilirsiniz.

Listeleme 7 - Models\ModelStateWrapper.vb

Public Class ModelStateWrapper
Implements IValidationDictionary

Private _modelState As ModelStateDictionary

Public Sub New(ByVal modelState As ModelStateDictionary)
    _modelState = modelState
End Sub

#Region "IValidationDictionary Members"

Public Sub AddError(ByVal key As String, ByVal errorMessage As String) Implements IValidationDictionary.AddError
    _modelState.AddModelError(key, errorMessage)
End Sub

Public ReadOnly Property IsValid() As Boolean Implements IValidationDictionary.IsValid
    Get
        Return _modelState.IsValid
    End Get
End Property

#End Region

End Class

Son olarak, Liste 8'deki güncelleştirilmiş denetleyici, oluşturucusunda hizmet katmanını oluştururken ModelStateWrapper kullanır.

Liste 8 - Controllers\ProductController.vb

Public Class ProductController
Inherits Controller

Private _service As IProductService

Public Sub New()
    _service = New ProductService(New ModelStateWrapper(Me.ModelState), New ProductRepository())
End Sub

Public Sub New(ByVal service As IProductService)
    _service = service
End Sub


Public Function Index() As ActionResult
    Return View(_service.ListProducts())
End Function


'
' GET: /Product/Create

Public Function Create() As ActionResult
    Return View()
End Function

'
' POST: /Product/Create

<AcceptVerbs(HttpVerbs.Post)> _
Public Function Create(<Bind(Exclude := "Id")> ByVal productToCreate As Product) As ActionResult
    If Not _service.CreateProduct(productToCreate) Then
        Return View()
    End If
    Return RedirectToAction("Index")
End Function

End Class

IValidationDictionary arabirimini ve ModelStateWrapper sınıfını kullanmak, hizmet katmanımızı denetleyici katmanımızdan tamamen yalıtmamızı sağlar. Hizmet katmanı artık model durumuna bağımlı değildir. IValidationDictionary arabirimini uygulayan herhangi bir sınıfı hizmet katmanına geçirebilirsiniz. Örneğin, bir WPF uygulaması basit bir koleksiyon sınıfıyla IValidationDictionary arabirimini uygulayabilir.

Özet

Bu öğreticinin amacı, bir ASP.NET MVC uygulamasında doğrulama gerçekleştirmeye yönelik bir yaklaşımı tartışmaktı. Bu öğreticide, tüm doğrulama mantığınızı denetleyicilerinizin dışına ve ayrı bir hizmet katmanına nasıl taşıyabileceğinizi öğrendiniz. ModelStateWrapper sınıfı oluşturarak hizmet katmanınızı denetleyici katmanınızdan nasıl yalıtabileceğinizi de öğrendiniz.