ASP.NET MVC RouteValueDictionary and Complex Object

What is the best way to save the results of the publication of the form (view the model) on the search results page?

I have a search form containing checkboxes. This form is created using a view model, for example

public class SearchViewModel { public string Name { get; set; } public string[] Colors { get; set; } } 

When this view model is sent back, I use the values ​​to build the query (using EF). The results turn into a 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)); } } 

Now that the results are displayed, I would like to use Html.PagedListPager and RouteValueDictionary to create the paging.

 @Html.PagedListPager((IPagedList)Model, page => Url.Action("Results", new RouteValueDictionary(ViewBag.SearchViewModel))) 

Nonetheless; the generated url looks like this:

 http://localhost:5139/search?Name=test&Colors=System.String[]&PageIndex=0 

Values ​​for colors become a non-value type. I was hoping the URL looked more like:

  http://localhost:5139/search?Name=test&Colors=[Blue,Pink,Yellow]&PageIndex=0 
  • What is the best way to save the results of the publication of the form (view the model) on the search results page?
  • Can a RouteValueDictionary support complex objects?
  • Should I use something like unbinder
  • Would it be better to use ViewData or Session?
+6
source share
2 answers

What I did for such cases, which I find simple but powerful, serializes my view model object for JSON (in your case, SearchViewModel ) using something like NewtonSoft JSON.net , then with the resulting JSON string, do a simple string compression using zlib.net Zlib.DeflateStream (you can also use something like AES Rijndael , but you will no doubt be slower and you want speed in the first place) and then pass the resulting Base64 string to your QueryString.

Then, when you are ready to use it again (it is effectively a viewstate), just unzip the JSON string and deserialize it from JSON to the appropriate .NET object (again in your case, SearchViewModel ).

Worked for me, and you are not getting a URL that is an unmanaged or some real measurable performance impact that I saw when only a few form fields were serialized.

I will develop the code soon.

UPDATE: code examples ...

This is what I would do in your specific scenario:

In Results(string, SearchViewModel) action:

 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)); } 

In sight:

 @Html.PagedListPager((IPagedList)Model, page => Url.Action("Results", new { encryptedUrlViewModel = ViewBag.EncryptedUrlViewModel })) 

The code may require some tweaks not verified in your script, but it will be something like this, good luck :)

You really have to keep in mind that if you want to carry a custom request in a URL through paging, then you might think why the form was not made as a GET request, and not a POST request in the first place. Any reason you especially wanted this POST ? I think GET will correctly migrate your Colors array, but make sure your view model is set up correctly. See the Haacked article for linking a model to lists .

+2
source

I had the same problem, but with search options. We had a color parameter, which was a list of color names used by the search engine. So you can mark black and blue, and the result is black as well as blue.

I ended up using Unbound .

 using Unbound; Unbinder u = new Unbinder(); @Url.Action("Index", new RouteValueDictionary(u.Unbind(SearchParams))) 

The result is a link like:

 /MyRoute?color[0]=black&color[1]=blue 
+1
source

Source: https://habr.com/ru/post/904180/


All Articles