在搜索结果页面中保留表单帖子(视图模型)结果的最佳方法是什么?
我有一个包含复选框的搜索表单。使用像
这样的视图模型构建此表单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
答案 0 :(得分:2)
我为这样的案例做了些什么,我发现它很简单但功能强大,将我的视图模型对象序列化为JSON(在您的情况下为SearchViewModel
),使用类似NewtonSoft JSON.net的内容然后使用生成的JSON字符串,通过zlib.net Zlib.DeflateStream
类对字符串进行简单压缩(您也可以使用类似AES Rijndael的内容,但无疑会慢一点,您首先需要速度然后在QueryString中传递生成的Base64字符串。
然后,当您准备再次使用它(它实际上是一个视图状态)时,只需解压缩JSON字符串并将其从JSON反序列化为相应的.NET对象(在您的情况下再次SearchViewModel
)。
为我做了一个款待,你不会得到一个无法管理的URL或任何真正可衡量的性能影响,我只看到少数几个表单字段被序列化。
我将尽快详细说明代码示例。
更新:代码示例......
这就是我在你的特定情况下会做的事情:
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
数组,但请确保您的视图模型设置正确。 See this Haacked article for model binding to lists
答案 1 :(得分:1)
我有同样的问题,但有搜索参数。我们有一个颜色参数,它是搜索引擎正在使用的颜色名称列表。所以你可以勾选黑色和蓝色,结果包含黑色和蓝色产品。
我最终使用了Unbound。
using Unbound;
Unbinder u = new Unbinder();
@Url.Action("Index", new RouteValueDictionary(u.Unbind(SearchParams)))
这会产生如下链接:
/MyRoute?color[0]=black&color[1]=blue