【问题标题】:ASP.NET MVC Controller Logic - Is this too much?ASP.NET MVC 控制器逻辑 - 这太多了吗?
【发布时间】:2011-04-18 05:33:16
【问题描述】:

我只是想知道您在控制器中添加了多少逻辑?我知道它们应该很苗条,但似乎你必须放一些。

请看看我的控制器,让我知道你会做些什么来折射它。谢谢!!

Namespace Controllers
    Public Class ShopController
        Inherits ControllerBase

#Region "Members/Properties"

        Private ProductService As IProductService
        Private UnitOfWork As IUnitOfWork

#End Region

#Region "Constructor(s)"

        Public Sub New(ProductService As IProductService, UnitOfWork As IUnitOfWork)
            Me.ProductService = ProductService
            Me.UnitOfWork = UnitOfWork

        End Sub

#End Region

#Region "Methods"

        <HttpGet()>
        Function Index() As ActionResult
            Return View(New ShopViewModel With {
                        .Categories = Mapper.Map(Of IEnumerable(Of Category), IEnumerable(Of CategoryViewModel))(ProductService.GetCategories)
                    })

        End Function

        <HttpGet()>
        Function ListProducts(ID As String, CatID As Integer) As ActionResult
            Return View(New ShopViewModel With {
                        .Products = Mapper.Map(Of IEnumerable(Of Product), IEnumerable(Of ProductViewModel))(ProductService.GetProductsByCategoryID(CatID))
                    })

        End Function

        <HttpPost()>
        Function GetCartAsJson() As ActionResult
            Return New JsonResult With {.Data = ShoppingCart}

        End Function

        <HttpPost()>
        Function AddItemToCart(Model As ShoppingCartItemViewModel) As ActionResult
            Dim Item As ShoppingCartItem

            Item = ShoppingCart.GetItemBySku(Model.Sku)

            If (Item IsNot Nothing) Then
                Item.Quantity += Model.Quantity
                UpdateCartItemPricing(Item)
            Else
                Dim Product = ProductService.GetProductDetailBySku(Model.Sku)

                Item = New ShoppingCartItem With {
                    .ProductID = Product.ID,
                    .Sku = Model.Sku,
                    .Name = Product.Name,
                    .Description = Product.ChildProducts(0).Name,
                    .Price = 0D,
                    .Quantity = Model.Quantity
                }

                ShoppingCart.AddItem(Item)
                UpdateCartItemPricing(Item)

            End If

            Return New JsonResult With {.Data = ShoppingCart}

        End Function

        <HttpPost()>
        Function UpdateCartItem(Model As ShoppingCartItemViewModel) As ActionResult
            Dim Item = ShoppingCart.GetItemBySku(Model.Sku)

            If (Item IsNot Nothing) Then
                If (Model.Quantity < 1) Then
                    ShoppingCart.DeleteItem(Item)
                Else
                    Item.Quantity = Model.Quantity
                    UpdateCartItemPricing(Item)
                End If
            End If

            Return New JsonResult With {.Data = ShoppingCart}

        End Function

        Private Sub UpdateCartPricing()
            For Each Item In ShoppingCart.Items
                UpdateCartItemPricing(Item)
            Next
        End Sub

        Private Sub UpdateCartItemPricing(Item As ShoppingCartItem)
            Item.Price = ProductService.GetPriceForSkuByQuantity(Item.Sku, Item.Quantity)
        End Sub

#End Region

    End Class
End Namespace

更新

所以我重构了一些建议(谢谢大家!)。这是我想出的:

Namespace Controllers
    Public Class ShopController
        Inherits ControllerBase

#Region "Members/Properties"

        Private ProductService As IProductService
        Private ShoppingCartService As IShoppingCartService
        Private UnitOfWork As IUnitOfWork

#End Region

#Region "Constructor(s)"

        Public Sub New(ProductService As IProductService, ShoppingCartService As IShoppingCartService, UnitOfWork As IUnitOfWork)
            Me.ProductService = ProductService
            Me.ShoppingCartService = ShoppingCartService
            Me.UnitOfWork = UnitOfWork

        End Sub

#End Region

#Region "Methods"

        <HttpGet()>
        Function Index() As ActionResult
            Return View(New ShopViewModel With {
                        .Categories = Mapper.Map(Of IEnumerable(Of Category), IEnumerable(Of CategoryViewModel))(ProductService.GetCategories)
                    })

        End Function

        <HttpGet()>
        Function ListProducts(ID As String, CatID As Integer) As ActionResult
            Return View(New ShopViewModel With {
                        .Products = Mapper.Map(Of IEnumerable(Of Product), IEnumerable(Of ProductViewModel))(ProductService.GetProductsByCategoryID(CatID))
                    })

        End Function

        <HttpPost()>
        Function GetCartAsJson() As ActionResult
            Return New JsonResult With {.Data = ShoppingCart}

        End Function

        <HttpPost()>
        Function AddItemToCart(Model As ShoppingCartItemViewModel) As ActionResult
            ShoppingCartService.AddItem(ShoppingCart, Model.Sku, Model.Quantity)
            Return New JsonResult With {.Data = ShoppingCart}

        End Function

        <HttpPost()>
        Function UpdateCartItem(Model As ShoppingCartItemViewModel) As ActionResult
            ShoppingCartService.UpdateItemQuantity(ShoppingCart, Model.Sku, Model.Quantity)
            Return New JsonResult With {.Data = ShoppingCart}

        End Function

#End Region

    End Class
End Namespace

【问题讨论】:

    标签: asp.net-mvc


    【解决方案1】:

    只有AddItemToCartUpdateCartItem 操作需要重构。我会将这两种方法包含的业务逻辑移动到服务层中。控制器中的私有方法也总是很臭。

    【讨论】:

    • 您能看到我上面对 Achim 的回答的评论吗?
    • @Sam Striano,你可以在IProductService 上定义一个方法来处理这个业务逻辑。然后只需在控制器操作中调用它们。
    • 好的。我的ShoppingCart 是 MVC 应用程序中的一个类,它可能应该在我的域模型中,以便所有层都可以访问它?问题是,在我的ControllerBase 中,我有一个属性ShoppingCart 被填充到OnActionExecuting 中(我将它塞进会话中并把它放回那里)所以每个继承ControllerBase 的控制器都可以访问这个购物车,所以我可以在ProductService 上有一个方法,比如AddItemToCart(Cart As ShoppingCart, Item As ShoppingCartItem),然后从ShopController 传递这些方法?
    • @Sam Striano,是的,在您的服务层上有一个 AddItemToCart 方法,该方法将购物车作为参数是重构此控制器操作的一种方法。
    【解决方案2】:

    苗条不等于空! ;-) 在我看来,以下部分有点“味道”:

    Dim Item = ShoppingCart.GetItemBySku(Model.Sku)
    
    If (Item IsNot Nothing) Then
      If (Model.Quantity < 1) Then
        ShoppingCart.DeleteItem(Item)
      Else
        Item.Quantity = Model.Quantity
        UpdateCartItemPricing(Item)
      End If
    End If
    

    我可能会将其移至 ShoppingCard。看起来违反了“告诉不要问”。

    【讨论】:

    • 我正在使用依赖注入(新手),所以这个控制器使用ProductService 来获取有关项目及其定价等的信息。所以我认为ShoppingCart 应该有一个@ 的实现987654325@,但是你知道如何让构造函数注入在这样的项目上工作吗?也许我跑题了??我正在使用 Ninject 进行 DI。
    • 我不明白你的问题!?为什么要更改构造函数?引用的代码根据一些 sku(它是模型的一部分)向 ShoppingCart 询问一些信息。然后它做出一些决定并在 ShoppingCard 上工作。该逻辑应移至 ShoppingCard。该方法可能被称为“UpdateQuantity”并且可能需要模型。因此,您无需向 ShoppingCard 询问信息,而是告诉它要做什么。这是个好主意:pragprog.com/articles/tell-dont-ask
    猜你喜欢
    • 2010-09-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-06-03
    • 2011-04-28
    • 1970-01-01
    相关资源
    最近更新 更多