2012-11-11 44 views
1

我花了一些時間研究在我的ASP.Net MVC站點中實現驗證的策略。冒着過度工程的風險,我試圖開發一個鬆散的情侶實現,可以持續推出我的任何項目。考慮到所有的移動部分,我想我會問這些SO的人看看他們是否有任何改進的意見或想法。代碼顯然是人爲設計的,我只是想了解一切事物是如何掛在一起的。ASP.Net中的驗證策略MVC

感興趣的運動部件:

  • 庫層與EF數據訪問
  • 模型數據批註輸入驗證
  • 業務規則驗證
  • 團結的DI
  • 服務層

    鑑於我想在單個控制器操作期間使用相同的EF上下文,我正在使用工作模式的單元注入相同DataContect到多個服務控制器內:

    public class OrderController : Controller 
    { 
        private IUnitOfWork _unitOfWork; 
        private IOrderService _recipeService; 
        private IInventoryService _inventoryService; 
    
        public OrderController(IUnitOfWork unitOfWork, IOrderService orderService, IInventoryService inventoryService) 
        { 
         _unitOfWork = unitOfWork; 
         _orderService = orderService; 
         _inventoryService = inventoryService 
         //Use property injection to apply the Unit of Work context and validation state to our services 
         _orderService.Context = _unitOfWork; 
         _orderService.ValidationState = new ModelStateWrapper(this.ModelState); 
         _inventoryService.Context = _unitOfWork; 
         _inventoryService.ValidationState = new ModelStateWrapper(this.ModelState); 
        } 
    

    多用一些做作碼繼續,讓我們在我創建行動說,我想創建一個產品訂單,並且還刪除從庫存產品:

    public ActionResult Create(CreateEditOrderViewModel model) 
        { 
         try 
         { 
    
          Product product = Mapper.Map<ProductDTO, Product>(model.ProductDTO); 
    
          if(_orderService.Insert(product) && 
           _inventoryService.Remove(product) && 
           ModelState.IsValid) 
          { 
           _unitOfWork.Save(); 
           return RedirectToAction("Index"); 
          } 
         } 
         catch (DataException exc) 
         { 
          //Log the error (add a variable name after DataException) 
          ModelState.AddModelError("", "Unable to save changes, please check the log for errors."); 
         } 
         return View(model); 
        } 
    

    在我的服務,我做每http://www.asp.net/mvc/tutorials/older-versions/models-(data)/validating-with-a-service-layer-cs一些業務規則驗證:

    public class OrderService : IOrderService 
    { 
    
        public bool Insert(Recipe orderToCreate) 
        { 
         // Validation logic 
         if (!ValidateOrder(orderToCreate)) 
          return false; 
    
         // Database logic 
         try 
         { 
          _context.OrderRepository.Insert(orderToCreate); 
         } 
         catch 
         { 
          return false; 
         } 
         return true; 
        } 
    
        protected bool ValidateOrder(Order orderToValidate) 
        { 
         Product p = orderToValidate.Product; 
         //Ensure inventory has product before creating order 
         if (_context.InventoryRepository.HasProduct(p) 
          _validationState.AddError("Product", "That product cannot be added to the order as we don't have it in stock"); 
    
         return _validationState.IsValid; 
        } 
    
    
        public IUnitOfWork Context 
        { 
         get 
         { 
          return _context; 
         } 
         set 
         { 
          _context = value; 
         } 
        } 
    
        public IValidationDictionary ValidationState 
        { 
         get 
         { 
          return _validationState; 
         } 
         set 
         { 
          _validationState = value; 
         } 
        } 
    } 
    

    而一個SIMPL E產品的訂購模式是這樣的:

    public class Order: IModel 
    { 
        [Key] 
        public int ID { get; set; } 
        [Required(ErrorMessage="A buyer is required.")] 
        public string Buyer { get; set; } 
        public virtual ICollection<Product> Products{ get; set; } 
    } 
    

    所以,因爲它的立場,對數據的註釋驗證模型綁定期間發生,並調用該服務的CRUD方法時出現的業務規則驗證。這些服務使用包含對存儲庫的引用的相同的工作單元對象,因此所有服務CRUD方法都在相同的EF上下文中執行,這爲我提供了諸如事務和併發的好處。

    在我的控制器中,我正在對Create操作中的多個服務進行調用。最好是對OrderService進行一次調用,然後調用InventoryService本身?

    有沒有辦法將工作單元對象通過Unity附加到服務中,因爲我需要每個服務都使用相同的UoA對象?我想不出一種方式來做到這一點,它不會結束每個服務的不同實例。

    如果有人有任何想法或建議,我很樂意聽到他們!

    謝謝!

    克里斯

  • 回答

    0

    在我的控制,我正在做我的創建操作中調用多個服務。是否最好改爲撥打 OrderService,然後調用InventoryService本身?

    是。最好將商業交易封裝在服務方法中。這可以讓以後更容易重用其他地方的邏輯。

    是否有辦法將工作單元對象通過Unity附加到服務中,因爲我需要爲每個服務使用相同的UoA對象?

    使用Unity的生命週期管理器,每個請求使用一個上下文,例如, PerHttpRequestLifetime並讓Unity將上下文/ UoW注入到服務中,而不是在控制器的構造函數中手動設置它。

    +0

    一生的經理很有趣!將UoA實例的生命週期映射到HTTP請求正是所期望的。在對UoA調用Dispose()之後,是否需要採取進一步的操作?我需要自己調用RemoveValue()嗎? –

    +0

    PerHttpRequestLifetime是一個例子,顯示它是如何工作的。其實我建議你使用http://unitymvc3.codeplex.com 'unityContainer.RegisterType (新的PerThreadLifetimeManager()); unityContainer.RegisterControllers(); DependencyResolver.SetResolver(new UnityDependencyResolver(unityContainer));' – Martin4ndersen

    +0

    如果我開始使用異步方法,我應該緊張嗎? –