Как поделиться представлением унаследованного контроллера

#c# #asp.net-mvc

#c# #asp.net-mvc

Вопрос:

У меня есть базовый контроллер:

 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/In или Out он выдает исключение:

 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» неправильно?

Комментарии:

1. Спасибо за ответ. Но некоторые действия (например, index) будут одинаковыми, но изменят только одну вещь, так что … не неправильно ли повторять код в двух контроллерах и представлениях? Каков способ добиться этого?

Ответ №1:

Как я могу поделиться представлением унаследованного контроллера, не передавая представление в качестве параметра? Я делаю что-то «mvc» неправильно?

Да, вы не используете MVC, как предполагалось. Поэтому вместо того, чтобы отвечать, как вы можете это сделать, я отвечу, почему вы не должны этого делать.

Если вы посмотрите на определение для MVC, одним из основных преимуществ является слабая связь. Идея заключается в том, что вы можете изменить любой контроллер, модель или представление, и вы знаете, какое влияние это окажет (именно там, где вы вносите изменения). В этом смысле наличие базового контроллера или базовой модели — плохая идея, поскольку в итоге вы получаете тесную связь.

Кажется, вы беспокоитесь о дублировании кода, и это совершенно нормально. Однако не все дублирование кода является плохим дублированием. Есть полезное дублирование (например, здесь, где вы упрощаете последующее изменение кода) и бесполезное дублирование (например, использование некоторого метода дважды, когда это может быть один метод и параметр). В какой-то момент у вас будет так много разных проверок, чтобы увидеть, является ли это одним из дочерних элементов или другим, что никто не захочет изменять этот код, даже вы.
Если вам нужно совместно использовать бизнес-логику, способ сделать это в MVC — это создать другой уровень, с которым взаимодействуют ваши контроллеры, а именно уровень сервисов.

Кроме того, почти никогда нет веских причин для подобных действий:

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

Предполагается, что представление даже не знает, какой контроллер его использует (однако это ViewContext.Controller свойство необходимо фреймворку). Если вы хотите поделиться данными из контроллера с представлением, используйте:

 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
}
  

Комментарии:

1. @rasputino В дополнение к тому, что уже заявил Камило, я бы посоветовал посмотреть на другие компоненты, которые являются частью ASP.NET MVC — это не только контроллеры, модели и представления. Повторное использование может быть достигнуто с помощью таких средств, как частичные представления, шаблоны отображения и редактирования, а также фильтры различных типов (действие, исключение и авторизация). Потратьте некоторое время на реализацию каждого из них, и вы получите гораздо лучшее представление о том, как создать слабосвязанное MVC-приложение, которое легко поддерживать и расширять.