如何在控制器之间重用NonAction方法

时间:2011-07-27 18:47:39

标签: asp.net-mvc controller

假设我有一个像这样的控制器类。

public class InStorePickupController : Controller
{
    private readonly IToppingService _toppingService;
    public InStorePickupController(IToppingService toppingService)
    {
        this._toppingService = toppingService;
    }

    public ActionResult GetPizza()
    {
        var pizzaModel = new PizzaModel();
        pizzaModel = MakePizza(pizzaModel);
        return View(pizzaModel);
    }

    [NonAction]
    public PizzaModel MakePizza(PizzaModel pm)
    {
        var toppings = _toppingService.GetAllToppings();
        //roll out dough
        //put toppings on pizza
        //bake pizza
        return pm;
    }

}

但我还有另一个控制器类,我想使用相同的'Make Pizza'非动作。

public class DeliveryController : Controller
        {
            private readonly IToppingService _toppingService;
            public DeliveryController(IToppingService toppingService)
            {
                this._toppingService = toppingService;
            }

            public ActionResult GetPizza()
            {
                var pizzaModel = new PizzaModel();
                pizzaModel = MakePizza(pizzaModel);
                return View(pizzaModel);
            }
    }

这是一个简单的例子,但它非常符合我的实际情况。唯一的区别是:

  1. 我有几种非动作方法,它们相当复杂(大量计算)。
  2. 我有很多需要访问这些非操作的控制器。这不是控制器蠕变,因此合并它们将无法工作。
  3. 每个控制器在构造函数中都有相当多的必要服务。
  4. 我可以让每个控制器继承一个基本控制器类,但我一直抱怨没有参数的构造函数。

    静态类怎么样?

    我只需要一点指导。感谢。

5 个答案:

答案 0 :(得分:4)

[NonAction]属性对我来说是一种代码味道。这意味着你将一些代码放入控制器,但对我来说,控制器中不应该存在任何其他代码而不是简单的操作。并且尝试在控制器之间重用NonAction可以确认您做错了什么。这就是为什么你有服务层,存储库,模型,...这么多地方重构这个代码和put your controllers on a diet

答案 1 :(得分:2)

基类可能是最佳选择,您可以执行以下操作:

public class PizzaControllerBase : Controller
{
  protected readonly IToppingService ToppingService;

  protected PizzaControllerBase(IToppingService toppingService)
  {
    ToppingService = toppingService;
  }

  public PizzaModel MakePizza(PizzaModel model)
  {
    // Stuff
  }
}

public DeliveryController : PizzaControllerBase
{
  public DeliveryController(IToppingService toppingService)
    : base(toppingService) { }

  public ActionResult GetPizza()
  {
    var pizzaModel = MakePizza(new PizzaModel());
    return View(pizzaModel);
  }
}

或者,引入一项新服务IPizzaService

public interface IPizzaService
{
  PizzaModel MakePizza(PizzaModel model);
}

public class PizzaService : IPizzaService
{
  private readonly IToppingService ToppingService;

  public PizzaService(IToppingService toppingService)
  {
    ToppingService = toppingService;
  }

  public PizzaModel CreatePizza(PizzaModel model)
  {
    // Stuff
  }
}

您可以将其注入控制器。

答案 2 :(得分:1)

为什么不创建一个新的IPizzaService来处理披萨问题并注入? IPizzaService也可以采用IToppingService依赖关系,以便获取已注入控制器类的顶级服务。

当然,服务应该根据以下评论对域模型对象(而不是视图模型对象)起作用。使用Automapper在它们之间进行映射。

答案 3 :(得分:0)

将方法添加到PizzaModel课程。

public class PizzaModel
{
    public static PizzaModel MakePizza(PizzaModel pm)
    {
        var toppings = _toppingService.GetAllToppings();
        //roll out dough
        //put toppings on pizza
        //bake pizza
        return pm;
    }
}

答案 4 :(得分:0)

您可以创建一个辅助类并调用要在两个控制器中使用的方法。