Важным свойством MVC Framework является возможность перенаправлять запрос на другие действия контроллеров либо другие URL-адреса. Для этого в MVC встроены механизмы RedirectResult и RedirectToRouteResult, которые наследуют от ActionResult и являются допустимыми результатами работы любого действия.
RedirectResult предназначен для того, чтобы возвратить результат пользователю в виде перенаправления на заданный адрес URL. У RedirectResult есть только одно свойство, которое инициализируется через конструктор, — Url, оно указывает строку адреса, на которую будет перенаправлен пользователь в ответ на запрос. Контроллеры MVC содержат стандартный метод Redirect, который формирует ответ в виде RedirectResult. В следующем фрагменте приведено действие, результатом которого является перенаправление пользователя на сайт http://www.asp.net/mvc/:
public ActionResult GetAspNetSite()
{
return Redirect("http://www.asp.net/mvc/");
}
RedirectToRouteResult выполняет схожую по смыслу с RedirectResult логику, но перенаправление вызова RedirectToRouteResult производится только на основании маршрутов таблицы маршрутизации. RedirectToRouteResult имеет два конструктора, с разным числом параметров, всего параметров два:
□ routeName — указывает наименование маршрута, на который нужно выполнить перенаправление запроса;
□ routeValues — указывает набор значений параметров маршрута типа RouteValueDictionary, с помощью которых производится поиск маршрута и выполняется перенаправление.
Для упрощения работы с RedirectToRouteResult механизм MVC реализует для контроллеров, наряду с методами RedirectToRoute, набор стандартных методов RedirectToAction, которые призваны облегчить формирование перенаправления вызова на другие действия или контроллеры. Например, следующий фрагмент кода перенаправляет вызов из текущего действия в действие Index текущего контроллера:
return RedirectToAction("Index");
При использовании RedirectToAction можно указывать и контроллер, в который требуется перенаправить вызов, кроме того, можно указать набор значений параметров маршрута типа RouteValueDictionary. Следующий пример кода перенаправит вызов на действие Index контроллера AccountController:
return RedirectToAction("Index", "Account");
ContentResult
ContentResult — это весьма простая реализация ActionResult, которая предназначена для того, чтобы в ответ на запрос передавать любой пользовательский строковый набор данных. Для реализации логики у ContentResult есть три свойства:
□ ContentType — MIME-тип передаваемых в ответ на запрос данных;
□ ContentEncoding — кодировка данных;
□ Content — строка данных для передачи в ответ на запрос.
Благодаря ContentResult разработчик получает возможность генерировать ответы на запросы в любом виде, который можно представить в виде строки текста. Этот тип ActionResult может быть полезен при работе с механизмом RenderAction. RenderAction — это часть библиотеки MVCContrib, которая содержит расширения MVC Framework, не вошедшие в основной функционал. RenderAction позволяет представлению вывести в месте вызова результат выполнения действия. При таком применении результат типа ContentResult подходит более всего. Для упрощения контроллеры содержат специальный метод Content, который возвращает значение типа ContentResult.
EmptyResult
Последний из рассмотренных стандартных вариантов ActionResult — это EmptyResult. Этот механизм предназначен для того, чтобы в ответ на запрос не возвращать ничего. Переопределенный в EmptyResult метод ExecuteResult не содержит ни строчки кода.
Создание своей реализации ActionResult
Важной особенностью механизма ActionResult является то, что вы можете создать свой собственный вариант, который будет формировать результат в том виде, который вам нужен. Например, вы можете разработать класс, наследующий ActionResult, который будет возвращать клиентам результаты запроса в виде XML-разметки. Классическим примером создания своего варианта ActionResult является реализация класса, который на запрос пользователя создает ответ в виде RSS-ленты. Продемонстрируем реализацию такого класса, добавив к нашему контроллеру AdminController действие Rss, которое будет возвращать пользователю RSS-ленту со списком зарегистрированных пользователей.
Первым делом создадим класс RssResult, который наследует ActionResult, как показано в листинге 4.6.
Листинг 4.6. Класс RssResult
namespace MVCBookProject {
using System.Web.Mvc; using System.Xml;
using System.ServiceModel.Syndication;
public class RssResult : ActionResult {
public SyndicationFeed Feed { get; set; }
public RssResult(SyndicationFeed feed)
{
Feed = feed;
}
public override void ExecuteResult(ControllerContext context)
{
context.HttpContext.Response.ContentType =
"application/rss+xml";
Rss20FeedFormatter formatter = new Rss20FeedFormatter(Feed);
using (XmlWriter writer =
XmlWriter.Create(context.HttpContext.Response.Output))
{
if (writer != null)
formatter.WriteTo(writer);
}
}
}
}
Обратите внимание, для реализации своего варианта ActionResult в классе RssResult мы перегружаем метод ExecuteResult, который и выполняет всю необходимую логику по формированию того результата, который получит клиент в своем браузере в ответ на запрос.
Использование класса RssResult ничем не отличается от применения других вариантов классов ActionResult. Добавим действие Rss в контроллер AdminControiier так, как показано во фрагменте:
[AcceptVerbs(HttpVerbs.Get)]
public RssResult Rss()
{
MembershipProvider mp = Membership.Provider;
int userCount;
var users = mp.GetAllUsers(0, Int32.MaxValue, out userCount);
List<SyndicationItem> items = new List<SyndicationItem>();
if (userCount > 0)
{
string bodyTemplate = @"email: {0}, comment: {1},
last activity: {2}, is locked: {3}, is approved: {4}";
foreach (MembershipUser item in users)
{
string body = String.Format(bodyTemplate, item.Email,
item. Comment, item. LastActivityDate,
item.IsLockedOut, item.IsApproved);
items.Add(new SyndicationItem(item.UserName, body, null));
}
}
SyndicationFeed feed = new SyndicationFeed("Cписок пользователей",
"http://localhost/rss", Request.Url, items);
return new RssResult(feed);
}
Обратите внимание, что это действие возвращает результат в виде экземпляра класса RssResult, которому передается сгенерированный RSS-поток. После того как мы реализовали RssResult и действие Rss, можно попытаться запросить результат этого действия через браузер, перейдя по относительной ссылке /Admin/Rss. В итоге вы должны получить результат в виде RSS-потока, похожий на тот, который изображен на рис. 4.11.