Not
Bu sayfaya erişim yetkilendirme gerektiriyor. Oturum açmayı veya dizinleri değiştirmeyi deneyebilirsiniz.
Bu sayfaya erişim yetkilendirme gerektiriyor. Dizinleri değiştirmeyi deneyebilirsiniz.
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.