Главная страница   /   17.4. Создание пользовательского средства вызова метода действия (action invoker) (ASP.NET MVC 4

ASP.NET MVC 4

ASP.NET MVC 4

Адам Фриман

17.4. Создание пользовательского средства вызова метода действия (action invoker)

Когда фабрика контроллеров создала экземпляр класса, платформе нужно вызвать действие в этом экземпляре. Если ваши контроллеры наследуют от класса Controller, то этим будет заниматься механизм вызова действий, который и является темой этого раздела.

Подсказка

Если вы создаете контроллер непосредственно из интерфейса IController, то вы сами должны будете позаботиться о выполнении действий. В главе 15 дана подробная информация об обоих подходах к созданию контроллеров. Механизмы вызова действий являются частью функциональности, которая включена в класс Controller.

Механизм вызова действий реализует интерфейс IActionInvoker, который показан в листинге 17-12.

Листинг 17-12: Интерфейс IActionInvoker
namespace System.Web.Mvc
{
	public interface IActionInvoker
	{
		bool InvokeAction(ControllerContext controllerContext, string actionName);
	}
}

В интерфейсе есть только один член: InvokeAction. Параметрами являются объект ControllerContext (о котором мы рассказывали в главе 15) и string, который содержит имя вызываемого действия. Он возвращает логическое значение: true означает, что действие был найдено и вызвано, а false - что в контроллере нет соответствующего действия.

Обратите внимание, что в этом описании мы не использовали слово метод. Связь между действиями и методами является чисто опциональной. Хотя описанному выше подходу следует встроенный механизм вызова действий, вы можете обрабатывать действия любым способом, который выберете. В листинге 17-13 показана реализация интерфейса IActionInvoker, которая использует другой подход.

Листинг 17-13: Пользовательский механизм вызова действий
using System.Web.Mvc;
namespace ControllerExtensibility.Infrastructure
{
	public class CustomActionInvoker : IActionInvoker
	{
		public bool InvokeAction(ControllerContext controllerContext, string actionName)
		{
			if (actionName == "Index")
			{
				controllerContext.HttpContext.
					Response.Write("This is output from the Index action");
				return true;
			}
			else
			{
				return false;
			}
		}
	}
}

Этот механизм вызова действий не затрагивает методы в классе контроллера. Фактически он работает с самими действиями. Если поступает запрос к действию Index, то он запишет сообщение непосредственно в Response. Если поступит запрос к любому другому действию, то он вернет false, после чего пользователю будет показана ошибка 404 — Not found.

Связь механизма вызова действий с контроллером устанавливается с помощью свойства Controller.ActionInvoker. Это означает, что разные контроллеры в одном приложении могут использовать разные механизмы вызова. Чтобы это продемонстрировать, мы добавили в проект новый контроллер под названием ActionInvoker, определение которого вы можете увидеть в листинге 17-14.

Листинг 17-14: Используем пользовательский механизм вызова действий в контроллере
using ControllerExtensibility.Infrastructure;
using System.Web.Mvc;
namespace ControllerExtensibility.Controllers
{
	public class ActionInvokerController : Controller
	{
		public ActionInvokerController()
		{
			this.ActionInvoker = new CustomActionInvoker();
		}
	}
}

В этом контроллере нет методов действий, и запросы обрабатывает механизм вызова действий. Вы можете увидеть, как он работает, запустив приложение и перейдя по ссылке /ActionInvoker/Index.

Пользовательский механизм вызова будет генерировать ответ, показанный на рисунке 17-4. Если перейдете по ссылке, ведущей к какому-либо другому действию этого контроллера, вы увидите страницу с ошибкой 404.

Рисунок 17-4: Эффект применения пользовательского механизма вызова действий

Мы не думаем, что вы будете создавать собственные механизмы вызова действий, но если вы все же захотите это сделать, мы не советуем использовать этот подход. Почему? Во-первых, во встроенной поддержке есть некоторые очень полезные функции, в чем вы убедитесь в ближайшее время. Во-вторых, в нашем примере есть проблемы: плохая расширяемость, недостаточное разделение обязанностей и отсутствие поддержки представлений. Пример только демонстрирует, как работает MVC Framework и еще раз доказывает, что почти каждый элемент конвейера обработки запроса можно изменить или заменить полностью.