Чем дальше в «лес», тем толще MVC framework. Вот на днях вышел preview второй версии. Бегло ознакомившись с возможностями, сильно порадовался. Но затем вспомнил о простой и очень интересной возможности RoR, которой пока нет (даже в планах) в MS MVC.
Речь идёт о возможности указать «расширение» для Action метода и, тем самым, определить тип View.
Для начала, рассмотрим пример. Запрос ht_p://localhost/Blog/Comments/0 возвращает html страницу, содержащую список коментариев к статье номер 0 в блоге. В данном случае Blog — это имя контроллера, Comments — название метода, 0 — идентификатор записи.
Код контроллера будет выглядеть примерно так:
Тут всё просто!
А как поступить, если нам необходимо в добавок к странице html получить список коментариев сериализованный в json? Самый простой способ, это создать ещё один метод, назвать его, скажем, CommentsJson, и явно вызвать метод Json(). Например, так:
Теперь мы можем получить json список по адресу ht_p://localhost/Blog/CommentsJson/0.
Задача решена, расходимся? Скажу прямо, меня такой код не устраивает. Во первых, дублирование, во вторых, мне не нравится url, который придётся использовать в последствии, в третьих, нет возможности использовать схему в других методах.
В таком случае, нам на помощь придёт возможность создать свой собственный ActionResult. Постараемся решить задачу «в лоб». Изменим метод Comments следующим образом:
Как видно, класс ComplexResult должен быть унаследован от ActionResult.
Попробуем реализовать его так:
Здесь надо объяснить: при обработке результата мы проверяем наличие строки «result» в списке значений, полученных при разборе запроса. Убеждаемся, что пользователь отправил строчку «json» и запускаем JsonResult, заранее определённый пользователем. Если строка не найдена или она не равна «json», запускаем ViewResult. Логика довольно проста.
Параллельно с этим добавим строки в настройку routes:
Теперь мы имеем возможность получить объект json явно указав это в строке запроса ht_p://localhost/Blog/Comments.json/0. Или ht_p://localhost/Blog/Comments/0 — когда нам нужен html. И самое главное, можем легко использовать ComplexResult в других методах, не засоряя код повторяющимися методами.
Фантазия подсказывает, что подобным образом можно добавить в ComplexResult другие стандартные или нестандартные (XmlResult, RssResult и пр.) ActionResults. Возможно, нас ждёт это в следующих версиях ASP.NET MVC.
Код написан, теперь оправдания: рекомендую использовать код, написанный в этой заметке только для ознакомления с возможностями MVC framework, очевидно — он не безопасен, для упрощения опущены некоторые проверки и условия.
Спасибо за внимание.
Речь идёт о возможности указать «расширение» для Action метода и, тем самым, определить тип View.
Для начала, рассмотрим пример. Запрос ht_p://localhost/Blog/Comments/0 возвращает html страницу, содержащую список коментариев к статье номер 0 в блоге. В данном случае Blog — это имя контроллера, Comments — название метода, 0 — идентификатор записи.
Код контроллера будет выглядеть примерно так:
public class BlogController : Controller
{
public ActionResult Comments(int id)
{
var strings = new[] { "Один", "Два", "Три" }; // Представим, что это комментарии
return View(strings);
}
}
* This source code was highlighted with Source Code Highlighter.
Тут всё просто!
А как поступить, если нам необходимо в добавок к странице html получить список коментариев сериализованный в json? Самый простой способ, это создать ещё один метод, назвать его, скажем, CommentsJson, и явно вызвать метод Json(). Например, так:
public ActionResult CommentsJson(int id)
{
var strings = new[] { "Один", "Два", "Три" }; // Представим, что это комментарии
return Json(strings);
}
* This source code was highlighted with Source Code Highlighter.
Теперь мы можем получить json список по адресу ht_p://localhost/Blog/CommentsJson/0.
Задача решена, расходимся? Скажу прямо, меня такой код не устраивает. Во первых, дублирование, во вторых, мне не нравится url, который придётся использовать в последствии, в третьих, нет возможности использовать схему в других методах.
В таком случае, нам на помощь придёт возможность создать свой собственный ActionResult. Постараемся решить задачу «в лоб». Изменим метод Comments следующим образом:
public class BlogController : Controller
{
public ActionResult Comments(int id)
{
var strings = new[] { "Один", "Два", "Три" }; // Представим, что это комментарии
return new ComplexResult
{
Json = () => Json(strings),
View = () => View(strings)
};
}
}
* This source code was highlighted with Source Code Highlighter.
Как видно, класс ComplexResult должен быть унаследован от ActionResult.
Попробуем реализовать его так:
public class ComplexResult : ActionResult
{
public override void ExecuteResult(ControllerContext context)
{
object value;
if (context.RouteData.Values.TryGetValue("result", out value))
{
var result = value.ToString();
if (result.Equals("json", StringComparison.InvariantCultureIgnoreCase))
{
Json().ExecuteResult(context);
return;
}
}
View().ExecuteResult(context);
}
public Func<JsonResult> Json { get; set; }
public Func<ViewResult> View { get; set; }
}
* This source code was highlighted with Source Code Highlighter.
Здесь надо объяснить: при обработке результата мы проверяем наличие строки «result» в списке значений, полученных при разборе запроса. Убеждаемся, что пользователь отправил строчку «json» и запускаем JsonResult, заранее определённый пользователем. Если строка не найдена или она не равна «json», запускаем ViewResult. Логика довольно проста.
Параллельно с этим добавим строки в настройку routes:
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
// Наш route должен стоять перед default
routes.MapRoute("Result", "{controller}/{action}.{result}/{id}",
new { controller = "Home", action = "Index", id = "", result = "view" });
routes.MapRoute("Default", "{controller}/{action}/{id}",
new { controller = "Home", action = "Index", id = "" });
}
* This source code was highlighted with Source Code Highlighter.
Теперь мы имеем возможность получить объект json явно указав это в строке запроса ht_p://localhost/Blog/Comments.json/0. Или ht_p://localhost/Blog/Comments/0 — когда нам нужен html. И самое главное, можем легко использовать ComplexResult в других методах, не засоряя код повторяющимися методами.
Фантазия подсказывает, что подобным образом можно добавить в ComplexResult другие стандартные или нестандартные (XmlResult, RssResult и пр.) ActionResults. Возможно, нас ждёт это в следующих версиях ASP.NET MVC.
Код написан, теперь оправдания: рекомендую использовать код, написанный в этой заметке только для ознакомления с возможностями MVC framework, очевидно — он не безопасен, для упрощения опущены некоторые проверки и условия.
Спасибо за внимание.