如何共享继承的控制器的视图

问题描述

我有一个基本控制器:

using System.Web.Mvc;

namespace SharedViewExample.Controllers
{
    public class InOutController : Controller
    {
        public string InOut { get; }

        public InOutController(string inOut)
        {
            InOut = inOut;
        }

        public ActionResult Index()
        {
            //return View("~/Views/InOut/Index.cshtml");//Way to solve the problem
            return View();
        }
    }
}

和两个继承的控制器:

namespace SharedViewExample.Controllers
{
    public class OutController : InOutController
    {
        public OutController():base("Out")
        {

        }
    }
}

namespace SharedViewExample.Controllers
{
    public class InController : InOutController
    {
        public InController() : base("In")
        {
        }
    }
}

~/Views/InOut/Index.cshtml中也有一个视图文件

<!DOCTYPE html>

<html>
<head>
    <Meta name="viewport" content="width=device-width" />
    <title>Index</title>
</head>
<body>
    <div>hey! I'm @Html.Raw(((SharedViewExample.Controllers.InOutController)ViewContext.Controller).InOut)</div>
</body>
</html>

但是当我浏览到http://website/InOut时会抛出异常:

The view 'Index' or its master was not found or no view engine supports the searched locations. The following locations were searched:
~/Views/In/Index.aspx
~/Views/In/Index.ascx
~/Views/Shared/Index.aspx
~/Views/Shared/Index.ascx
~/Views/In/Index.cshtml
~/Views/In/Index.vbhtml
~/Views/Shared/Index.cshtml
~/Views/Shared/Index.vbhtml

我认为也许使用return View("~/Views/InOut/Index.cshtml");有点怪异,这应该是此控制器中的认路径之一。如何在不将视图作为参数传递的情况下共享继承的控制器的视图?我在做“ mvc”错误吗?

解决方法

如何在不将视图作为参数传递的情况下共享继承的控制器的视图?我在做“ mvc”错误吗?

是的,您没有按照预期使用MVC。因此,除了回答如何您可以做到这一点之外,我还会回答为什么您不应该这样做。

如果您查看definition for MVC,则主要优点之一就是松耦合。这个想法是,您可以更改任何Controller,Model或View,并且知道影响在哪里(确切地说是在哪里进行更改)。从这个意义上讲,拥有基础控制器或基础模型是一个坏主意,因为最终会导致紧密耦合。

似乎您担心代码重复,这很好。但是,并非所有代码重复都是不好的重复。有有用的重复(如此处,您以后可以在其中轻松更改代码)和无用的重复(如,某种方法可能是一个方法和一个参数时,两次使用某种方法)。在某个时候,您将进行许多不同的检查,以查看它是孩子还是其他孩子,甚至没有人愿意修改该代码。
如果您需要共享业务逻辑,则在MVC中实现此目的的方法是让控制器与之交谈的另一层即服务层。

此外,几乎没有理由做这样的事情:

((SharedViewExample.Controllers.InOutController)ViewContext.Controller)

该视图甚至应该不知道哪个控制器正在使用它(但是框架需要ViewContext.Controller属性)。如果要将数据从Controller共享到View,请使用:

public ActionResult Index()
{
    ViewBag.Foo = "bar"; // ViewBag is a dynamic type
    var model = new SomeModel { Foo = "bar" };

    return View(model); // the model is strongly typed
}