ASP.NET MVC RouteValueDictionary и сложный объект
каков наилучший метод сохранения результатов записи формы (модели представления) на странице результатов поиска?
у меня есть форма поиска, которая содержит флажки. Эта форма создается с использованием модели представления, такой как
public class SearchViewModel
{
public string Name { get; set; }
public string[] Colors { get; set; }
}
когда эта модель представления возвращается, я использую значения для построения запроса (используя EF). Результаты превращаются в PagedList.
public class SearchController : Controller
{
public ActionResult Index()
{
//this displays the search form.
return View();
}
public ActionResult Results(string game, SearchViewModel vm)
{
//this displays the results
ViewBag.SearchViewModel = vm;
var matches = _repository.AsQueryable()
.ColorOr(vm.Colors)
.WhereIf(vm.Name.IsNotEmpty(), x => x.Name.Contains(vm.Name.Trim()));
return View(matches.ToPagedList(1, 10));
}
}
теперь, когда результаты отображаются, я хотел бы использовать Html.PagedListPager и RouteValueDictionary для создания подкачки.
@Html.PagedListPager((IPagedList)Model, page => Url.Action("Results", new RouteValueDictionary(ViewBag.SearchViewModel)))
однако; созданный URL выглядит следующим образом:
http://localhost:5139/search?Name=test&Colors=System.String[]&PageIndex=0
значения для цветов в конечном итоге являются типом, а не значениями. Я надеялся, что URL-адрес выглядит как:
http://localhost:5139/search?Name=test&Colors=[Blue,Pink,Yellow]&PageIndex=0
- каков наилучший метод сохранения результатов записи формы (модели представления) на странице результатов поиска?
- может ли RouteValueDictionary поддерживать сложные объекты?
- должен ли я использовать что-то вроде unbinder
- было бы лучше использовать ViewData или Session?
2 ответов
то, что я сделал для таких случаев, которые я нахожу простыми, но мощными, сериализуется мой объект модели представления в JSON (в вашем случае SearchViewModel
), используя что-то вроде Ньютонсофт JSON.net затем с полученной строкой JSON выполните простое сжатие строки черезzlib.netZlib.DeflateStream
класса (вы также можете использовать что-то вроде алгоритм AES Rijndael но, без сомнения, будет медленнее, и вы хотите скорость в первую очередь), а затем передать полученный Строка Base64 через строку запроса.
затем, когда вы будете готовы использовать его снова (это фактически viewstate), просто распакуйте строку JSON и десериализуйте ее из JSON в соответствующий объект .NET (снова в вашем случае SearchViewModel
).
работал удовольствие для меня, и вы не в конечном итоге с URL-адресом, который неуправляем или любые реальные измеримые воздействия производительности, которые я видел только с несколькими полями формы сериализованы.
Я уточнил с образцом кода в ближайшее время.
UPDATE: примеры кода...
вот что я сделал бы в вашем конкретном сценарии:
на Results(string, SearchViewModel)
действие:
public ActionResult Results(string encryptedUrlViewModel, string game, SearchViewModel vm)
{
SearchViewModel searchUrlViewModel = null;
if (!string.IsNullOrEmpty(searchUrl)) {
// only first submission, no url view model set yet, so compress it and store..
encryptedUrlViewModel = Convert.ToBase64String(
DeflateStream.CompressString(JsonConvert.SerializeObject(vm)));
ViewBag.EncryptedUrlViewModel = encryptedUrlViewModel;
}
else {
var jsonUrlViewModel = DeflateStream.UncompressString(Convert.FromBase64String(encryptedUrlViewModel));
searchUrlViewModel = JsonConvert.DeserializeObject(jsonUrlViewModel, typeof(SearchViewModel)) as SearchViewModel;
// at this point you should have a serialized 'SearchViewModel' object
// ready to use which you can then tweak your query below with.
}
var matches = _repository.AsQueryable()
.ColorOr(vm.Colors)
.WhereIf(vm.Name.IsNotEmpty(), x => x.Name.Contains(vm.Name.Trim()));
return View(matches.ToPagedList(1, 10));
}
в виде:
@Html.PagedListPager((IPagedList)Model, page => Url.Action("Results", new { encryptedUrlViewModel = ViewBag.EncryptedUrlViewModel }))
код может потребовать некоторых настроек, непроверенных в вашем сценарии, но это будет что-то вроде этого, удачи :)
вы должны действительно рассмотреть, хотя, если вы хотите выполнить запрос пользователя в URL-адрес через подкачку, то можно было бы рассмотреть, почему форма не была сделана как GET
запрос в отличие от POST
запрос в первую очередь. Любая причина, по которой вы особенно этого хотели POST
? Я думаю GET
вашим Colors
массив правильно, но убедитесь, что ваша модель представления настроена правильно. см. эту статью Haacked для привязки модели к спискам.
у меня была такая же проблема, но с параметрами поиска. У нас был параметр цвета, который был списком имен цветов, используемых поисковой системой. Таким образом, вы могли бы отметить черный и синий, и результат содержал черные, а также синие продукты.
Я закончил с помощью Unbound.
using Unbound;
Unbinder u = new Unbinder();
@Url.Action("Index", new RouteValueDictionary(u.Unbind(SearchParams)))
что приводит к ссылке, как:
/MyRoute?color[0]=black&color[1]=blue