В рамках ModelUnbinder, об основном сценарии использования которого я уже писал, была решена еще одна немаловажная проблема — работа со «сложными» моделями.
Рассмотрим пример: допустим, у нас на сайте есть форма поиска, и есть экшен, который показывает результаты:
public class SearchModel
{
public string SearchString { get; set; }
public bool InLocalArea { get; set; }
public int Page { get; set; }
public int PerPage { get; set; }
}
public virtual ActionResult Search(SearchModel searchModel)
{
return Json(searchModel, JsonRequestBehavior.AllowGet);
}
Допустим, мы хотим дать ссылку на результаты какого-то поиска и хотим воспользоваться для этого T4MVC. Попробуем так:
<a href="@Url.Action(MVC.Home.Search(new HomeController.SearchModel()
{
SearchString = "qweasd",
}))">Предзабитый поиск1</a>
В результате у нас получится URL вроде: http://localhost:30729/Home/Search?searchModel=MvcApplication2.Controllers.HomeController.SearchModel. Это, конечно, не совсем то, что нужно :) Для решения проблемы воспользуемся ModelUnbinder’ом:
protected void Application_Start()
{
//blablabla
ModelUnbinderHelpers.ModelUnbinders.Add(typeof(HomeController.SearchModel), new PropertiesUnbinder());
}
PropertiesUnbinder — это анбайндер, поставляемый в комплекте с T4MVC. Собственно, с его помощью в данном случае мы и получаем требуемый результат, ссылка теперь выглядит таким образом: http://localhost:30729/Home/Search?searchModel.SearchString=qweasd&searchModel.InLocalArea=False&searchModel.Page=0&searchModel.PerPage=0. Конечно, и этот URL можно чуть-чуть улучшить (например, не писать дефолтные значения value-type’ов), но по крайней мере эта ссылка вполне корректно работает, а в исходном коде нам пришлось поменять всего одну строчку — добавление анбайндера.
В реальной жизни в таких случаях я предпочитаю создавать пустой интерфейс IComplexModel, который реализуют все подобные модельки, и добавлять анбайндер уже только для этого интерфейса. Таким образом код выглядит как-то так:
public interface IComplexModel { }
public class SearchModel : IComplexModel
{
public string SearchString { get; set; }
/* ... */
}
protected void Application_Start()
{
//blablabla
ModelUnbinderHelpers.ModelUnbinders.Add(typeof(IComplexModel), new PropertiesUnbinder());
}
Вот и всё! Можно лишь добавить, что PropertiesUnbinder отлично работает и с массивами внутри модели, то есть модель вида:
public class SearchModel : IComplexModel
{
public int[] Numbers { get; set; }
}
так же будет вполне адекватно преобразована в соответствующий URL.
Как обычно, тестовый проект с примером можно скачать и полюбопытствовать. Буду рад, если это кому-нибудь пригодиться.