Главная страница   /   16.6. Использование фильтров для результата (ASP.NET MVC 4

ASP.NET MVC 4

ASP.NET MVC 4

Адам Фриман

16.6. Использование фильтров для результата

Фильтры результатов – это фильтры общего назначения, которые обрабатывают результаты, произведенные методами действий. Фильтры результатов реализуют интерфейс IResultFilter, который показан в листинге 16-26.

Листинг 16-26: Интерфейс IResultFilter
namespace System.Web.Mvc
{
	public interface IResultFilter
	{
		void OnResultExecuting(ResultExecutingContext filterContext);
		void OnResultExecuted(ResultExecutedContext filterContext);
	}
}

Как мы узнали в главе 15, методы действий возвращают результаты действий, что позволяет нам отделять цель метода действия от его исполнения. Применение фильтра результатов к методу действия означает, что метод OnResultExecuting будет вызван после того, как метод действия вернет результат, но до того, как результат будет выполнен. Метод OnResultExecuted будет вызван после выполнения результата действия.

Параметрами для этих методов являются соответственно объекты ResultExecutingContext и ResultExecutedContext, и они очень похожи на аналогичные фильтры методов действий. Они определяют те же свойства, которые обладают теми же эффектами (см. таблицу 16-8).

Чтобы продемонстрировать простой фильтр результатов, мы создали новый файл класса под названием ProfileResultAttribute.cs в папке Infrastructure и определили в нем класс, показанный в листинге 16-27.

Листинг 16-27: Простой фильтр результатов
using System.Diagnostics;
using System.Web.Mvc;
namespace Filters.Infrastructure
{
	public class ProfileResultAttribute : FilterAttribute, IResultFilter
	{
		private Stopwatch timer;
		public void OnResultExecuting(ResultExecutingContext filterContext)
		{
			timer = Stopwatch.StartNew();
		}
		public void OnResultExecuted(ResultExecutedContext filterContext)
		{
			timer.Stop();
			filterContext.HttpContext.Response.Write(
				string.Format("<div>Result elapsed time: {0}</div>",
					timer.Elapsed.TotalSeconds));
		}
	}
}

Этот фильтр результатов является дополнением к фильтру действий, который мы создали в предыдущем разделе, и измеряет количество времени, необходимого для выполнения результата. В листинге 16-28 вы можете увидеть, как мы применили этот новый фильтр к контроллеру Home.

Листинг 16-28: Применяем фильтр результатов к контроллеру Home
[ProfileAction]
[ProfileResult]
public string FilterTest()
{
	return "This is the ActionFilterTest action";
}

На рисунке 16-9 показан результат запуска программы и перехода по ссылке /Home/FilterTest. Как видите, оба фильтра добавили данные в ответ браузеру - вывод из фильтра результата показан после результата от метода действия. Естественно, поскольку MVC Framework не может выполнить метод OnResultExecuted до обработки результата, строковое значение будет вставлено в результат.

Рисунок 16-9: Эффект применения фильтра результатов

Встроенный класс фильтра действий и результатов

MVC Framework включает в себя встроенный класс, который можно использовать для создания как фильтров действий, так и фильтров результатов. Этот класс, ActionFilterAttribute, показан в листинге 16-29.

Листинг 16-29: Класс ActionFilterAttribute
public abstract class ActionFilterAttribute : FilterAttribute, IActionFilter, IResultFilter
{
	public virtual void OnActionExecuting(ActionExecutingContext filterContext)
	{
	}
	public virtual void OnActionExecuted(ActionExecutedContext filterContext)
	{
	}
	public virtual void OnResultExecuting(ResultExecutingContext filterContext)
	{
	}
	public virtual void OnResultExecuted(ResultExecutedContext filterContext)
	{
	}
}

Единственное преимущество этого класса заключается в том, что вам не придется переопределять и реализовать методы, которые вы не собираетесь использовать. Никаких других преимуществ реализации интерфейсов фильтров напрямую нет.

Чтобы продемонстрировать работу класса ActionFilterAttribute, мы добавили новый файл под названием ProfileAllAttribute.cs в папку Infrastructure и определили в нем класс, показанный в листинге 16-30.

Листинг 16-30: Используем класс ActionFilterAttribute
using System.Diagnostics;
using System.Web.Mvc;
namespace Filters.Infrastructure
{
	public class ProfileAllAttribute : ActionFilterAttribute
	{
		private Stopwatch timer;
		public override void OnActionExecuting(ActionExecutingContext filterContext)
		{
			timer = Stopwatch.StartNew();
		}
		public override void OnResultExecuted(ResultExecutedContext filterContext)
		{
			timer.Stop();
			filterContext.HttpContext.Response.Write(
				string.Format("<div>Total elapsed time: {0}</div>",
					timer.Elapsed.TotalSeconds));
		}
	}
}

Класс ActionFilterAttribute реализует интерфейсы IActionFilter и IResultFilter, что означает, что MVC Framework будет считать производные классы фильтрами обоих типов, даже если не все методы переопределены. В нашем примере мы реализовали только метод OnActionExecuting из интерфейса IActionFilter и OnResultExecuted из интерфейса IResultFilter, что позволит нам продолжить анализ производительности и измерить количество времени, необходимое для выполнения метода действия и обработки результата, в едином блоке. В листинге 16-31 показано применение фильтра к контроллеру Home.

Листинг 16-31: Применяем фильтр к контроллеру Home
[ProfileAction]
[ProfileResult]
[ProfileAll]
public string FilterTest()
{
	return "This is the FilterTest action";
}

Вы можете увидеть эффект от всех этих фильтров, если запустите приложение и перейдите по ссылке /Home/FilterTest. Результат показан на рисунке 16-10.

Рисунок 16-10: Эффект добавления фильтра ProfileAll