如何与其他控制器共享控制器操作/视图

时间:2017-07-27 12:54:55

标签: c# asp.net-mvc

我想从一些不同的URL调用MainController.GetData()动作,而不需要一堆复制/粘贴的代码。有没有人们解决这个问题的首选方式?似乎我也可以通过路由来做到这一点。我只想重用视图和操作,因为如果我为GetMyData()操作制作了一个版本,所有代码都是一样的。

**Example urls**

*/main/getdata  
/other/getmydata  
/diffferent/getothersdata?userid=3



public ActionResult MainController::GetData()
{
    var data = GetData();
    return View(collection);
}

public ActionResult OtherController::GetMyData()
{
    var userId = GetCurrentUserId();
    var data = GetData(userId);
    return View("../main/getdata", collection);
}

1 个答案:

答案 0 :(得分:2)

尽管控制器看起来像简单类,但它们在MVC框架内的行为更加专业化。你不能,或者说你不应该更好,只是将一个动作中的一个动作称为另一个动作,就好像它只是任何旧的方法一样。大多数情况下,这是因为控制器具有上下文,您必须实例化它们并将它们设置得恰到好处,以便一切正常。在一个动作方法中做这件事是非常重要的,它会让你的代码变得丑陋。

你真的有两个选择。如果您只想要操作的结果,最好的方法是利用HttpClient并实际为其提交HTTP请求,就像激活它的任何其他请求一样。

但是,根据您的问题描述,选项二可能更合适。您可以创建一个基类,然后从中继承。例如,如果您知道两个控制器都需要GetData,您可以执行以下操作:

public abstract class BaseController : Controller
{
    protected IEnumerable<Data> QueryData(int? userId = null)
    {
        ...
    }
}

public class MainController : BaseController
{
    public ActionResult GetData()
    {
        var data = QueryData();
        return View(data);
    }
}

public class OtherController : BaseController
{
    public ActionResult GetMyData()
    {
        var userId = GetCurrentUserId();
        var data = QueryData(userId);
        return View(data);
    }
}

换句话说,您可以将常用功能分解为两个派生控制器上的操作都可以使用的内容。

这是此方案所需的全部内容,但您也可以在基本控制器上实施整个操作。例如,如果您向Foo添加了BaseController操作,则MainControllerOtherController都会响应Foo的请求,而无需实际明确定义那。如果需要,您也可以覆盖这些操作。