Пишем код

Заметки о .net разработке

ModelUnbinder в T4MVC — работа со сложными моделями

without comments

В рамках ModelUnbinder, об основном сценарии использования которого я уже писал, была решена еще одна немаловажная проблема — работа со «сложными» моделями.
Рассмотрим пример: допустим, у нас на сайте есть форма поиска, и есть экшен, который показывает результаты:

<br />
        public class SearchModel<br />
        {<br />
            public string SearchString { get; set; }<br />
            public bool InLocalArea { get; set; }<br />
            public int Page { get; set; }<br />
            public int PerPage { get; set; }<br />
        }</p>
<p>        public virtual ActionResult Search(SearchModel searchModel)<br />
        {<br />
            return Json(searchModel, JsonRequestBehavior.AllowGet);<br />
        }<br />

Допустим, мы хотим дать ссылку на результаты какого-то поиска и хотим воспользоваться для этого T4MVC. Попробуем так:
<br />
<a href="@Url.Action(MVC.Home.Search(new HomeController.SearchModel()
             {
                 SearchString = "qweasd",
             }))">Предзабитый поиск1</a><br />

В результате у нас получится URL вроде: http://localhost:30729/Home/Search?searchModel=MvcApplication2.Controllers.HomeController.SearchModel. Это, конечно, не совсем то, что нужно :) Для решения проблемы воспользуемся ModelUnbinder’ом:
<br />
        protected void Application_Start()<br />
        {<br />
            //blablabla<br />
            ModelUnbinderHelpers.ModelUnbinders.Add(typeof(HomeController.SearchModel), new PropertiesUnbinder());<br />
        }<br />

PropertiesUnbinder — это анбайндер, поставляемый в комплекте с T4MVC. Собственно, с его помощью в данном случае мы и получаем требуемый результат, ссылка теперь выглядит таким образом: http://localhost:30729/Home/Search?searchModel.SearchString=qweasd&searchModel.InLocalArea=False&searchModel.Page=0&searchModel.PerPage=0. Конечно, и этот URL можно чуть-чуть улучшить (например, не писать дефолтные значения value-type’ов), но по крайней мере эта ссылка вполне корректно работает, а в исходном коде нам пришлось поменять всего одну строчку — добавление анбайндера.

В реальной жизни в таких случаях я предпочитаю создавать пустой интерфейс IComplexModel, который реализуют все подобные модельки, и добавлять анбайндер уже только для этого интерфейса. Таким образом код выглядит как-то так:

<br />
        public interface IComplexModel { }<br />
        public class SearchModel : IComplexModel<br />
        {<br />
            public string SearchString { get; set; }<br />
            /* ... */<br />
        }</p>
<p>        protected void Application_Start()<br />
        {<br />
            //blablabla<br />
            ModelUnbinderHelpers.ModelUnbinders.Add(typeof(IComplexModel), new PropertiesUnbinder());<br />
        }<br />

Вот и всё! Можно лишь добавить, что PropertiesUnbinder отлично работает и с массивами внутри модели, то есть модель вида:

<br />
        public class SearchModel : IComplexModel<br />
        {<br />
            public int[] Numbers { get; set; }<br />
        }<br />

так же будет вполне адекватно преобразована в соответствующий URL.

Как обычно, тестовый проект с примером можно скачать и полюбопытствовать. Буду рад, если это кому-нибудь пригодиться.

Опубликовать в Facebook
Опубликовать в Google Plus

Written by Shaddix

Июль 5th, 2012 at 10:56 дп

Posted in .net,agile,MVC,t4mvc,web

Leave a Reply