【问题标题】:ASP.NET MVC - Reusing Action BehaviorsASP.NET MVC - 重用动作行为
【发布时间】:2010-11-20 17:58:30
【问题描述】:

这个问题主要与良好的设计有关。

假设我有一个控制器动作,如 DeletePage,可以在同一控制器的两个单独视图中调用。假设删除逻辑不包含在操作本身中,而是一些条件检查等调用正确的业务逻辑,当我可以有一个私有方法时,复制删除操作的结构是没有意义的返回一个 ActionResult,我在这两个可能导致删除的操作中都调用了它。我的问题是在哪里放置这样的可重用操作方法的最佳位置?现在我只是将它们标记为私有并将它们粘贴在控制器类的一个区域中,但也许密封的内部类对于这种方法或完全在其他地方更有意义。

想法?

public ActionResult EditPage(int id, FormCollection formCollection)
{
    var page = _pagesRepository.GetPage(id);

    if (page == null)
        return View("NotFound");
    if (page.IsProtected)
        return View("IllegalOperation");

    if (formCollection["btnSave"] != null)
    {
        //...
    }
    else if (formCollection["btnDelete"] != null)
    {
        return DeletePage(page);
    }
    return RedirectToAction("Index");
}

public ActionResult DeletePage(int id)
{
    var page = _pagesRepository.GetPage(id);

    if (page == null)
        return View("NotFound");

    return DeletePage(page);
}

// Reusable Action
private RedirectToRouteResult DeletePage(Page page)
{
    if(page != null && !page.IsProtected)
    {
        _pagesRepository.Delete(page);
        _pagesRepository.Save();

        FlashMessage(string.Format(PageForms.PageDeleted, page.Name), MessageType.Success);

        return RedirectToAction("Index");
    }
    return RedirectToAction("Index");
}

【问题讨论】:

    标签: asp.net-mvc code-reuse


    【解决方案1】:

    我不明白为什么需要将可重用方法设置为操作方法。为什么不只是一个返回 void/bool/etc 指示保存结果的私有方法,并让您的公共操作方法返回 RedirectToAction()?实际上这是相同的结果,但我认为这是一种更清晰的方法。

    public ActionResult DeletePage(int id)
    {
            var page = _pagesRepository.GetPage(id);
    
            if (page == null)
                    return View("NotFound");
    
            DeletePage(page);
            return RedirectToAction("Index");
    }
    
    //reusable method
    private void DeletePage(Page page)
    {
        //your same validation/save logic here
    }
    

    将来您可能会考虑将此私有 DeletePage 方法移动到执行验证和/或保存的单独服务类中。在这种情况下,返回一个 ActionResult 肯定是没有意义的,所以我认为这个例子对你的场景来说是一个更合适的方法。

    【讨论】:

    • 您对将其粘贴在密封的内部类中以使其与其他操作方法的故意隔离对其他人来说是显而易见的有何看法?
    • @lakario,坦率地说,我认为如果你达到那种程度,我可能会感到困惑。如果我不想将该方法与所有控制器的操作方法直接内联,我会将验证和保存逻辑完全放在一个单独的类中。
    【解决方案2】:

    在我看来,您的可重用代码是一个 Action,因为它返回的是一个 ActionResult。所以你的使用没问题。 DeletePage(Page page) 可能会保持公开状态。

    我期待其他意见。

    【讨论】:

      【解决方案3】:

      我个人同意库尔特的观点。删除未受保护页面的概念应该与控制器应该执行的操作分离。其次,当页面受到保护时,代码会让人感到困惑。在一个动作中它重定向到索引,在第二个动作中它重定向到“IllegalOperation”视图。就我个人而言,我会做一些类似...

      public ActionResult DeletePage(int id) {
          var page = _pagesRepository.GetPage(id);
          if (!PageIsValidForDeletion(page)) {
               string invalidPageView = FindViewForInvalidPage(page);
               return View(invalidPageView);
          }
          DeletePage(page);
          return RedirectToAction("Index");
      }
      

      【讨论】:

      • 实际上在 formCollection["btnDelete"] != null 的 Edit 操作的子句中存在额外的逻辑,为简洁起见,我删除了这些逻辑,如果这增加了一些混乱,抱歉。不管怎样,很好的建议。
      猜你喜欢
      • 2011-07-15
      • 2013-06-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-09-24
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多