I have a SearchController with an action that can execute some long running searches and return a results page. The searches can take anywhere from 1 to 60 seconds. The URL for a search is an HTTP GET request of the form: http://localhost/Search?my=query&is=fancy
The experience I'm looking for is similar to the many travel sites that are out there. I would like to show an intermediate "Loading..." page where, ideally:
Those are nice-to-have's. I'm open to all ideas! Thanks.
Once controller is created, click on controller method and add view for your action method. Select view as partial view, template as list and use Product model beacuse here I am going to use partial view to render our lazy loading data which will come from ajax call response.
In order to keep it javascript-less, you can break the search into multiple actions.
The first action (/Search/?q=whodunit) just does some validation of your parameters (so you know if you need to re-display the form) and then returns a view which uses a meta-refresh to point the browser back to the "real" search action.
You can implement this with two separate controller actions (say Search and Results):
public ActionResult Search(string q)
{
if (Validate(q))
{
string resultsUrl = Url.Action("Results", new { q = q });
return View("ResultsLoading", new ResultsLoadingModel(resultsUrl));
}
else
{
return ShowSearchForm(...);
}
}
bool Validate(string q)
{
// Validate
}
public ActionResult Results(string q)
{
if (Validate(q))
{
// Do Search and return View
}
else
{
return ShowSearchForm(...);
}
}
But this gives you some snags as far as refreshing goes. So you can re-merge them back into a single action which can signal itself of the two-phase process using TempData.
static string SearchLoadingPageSentKey = "Look at me, I'm a magic string!";
public ActionResult Search(string q)
{
if (Validate(q))
{
if (TempData[SearchLoadingPageSentKey]==null)
{
TempData[SearchLoadingPageSentKey] = true;
string resultsUrl = Url.Action("Search", new { q = q });
return View("ResultsLoading", new ResultsLoadingModel(resultsUrl));
}
else
{
// Do actual search here
return View("SearchResults", model);
}
}
else
{
return ShowSearchForm(...);
}
}
This covers points 2, 3, 4 and arguably 5.
To include support for #1 implies that you're going to store the results of the search either in session, db, etc..
In this case, just add your desired cache implementatin as part of the "Do actual search here" bit, and add a check-for-cached-result to bypass the loading page. e.g.
if (TempData[SearchLoadingPageSentKey]==null)
becomes
if (TempData[SearchLeadingPageSentKey]==null && !SearchCache.ContainsKey(q))
You could do it the following way:
An example using jquery:
<div id="loading" style="display: none">
Loading...
</div>
<a href="javascript:void(0);"
onclick="searchFor('something')">Search for something</a>
<script type="text/javascript">
function searchFor(what) {
$('#loading').fadeIn();
$.ajax({
type: 'GET',
url: 'search?query=' + what,
success: function(data) {
location.href = data.ResultsUrl;
}
});
}
</script>
(edit:)
The controller would be something like:
public class SearchController
{
public ActionResult Query(string q)
{
Session("searchresults") = performSearch();
return Json(new { ResultsUrl = 'Results'});
}
public ActionResult Results()
{
return View(Session("searchresults"));
}
}
Consider it pseudo-code: i did not actually test it.
Good question. I may soon have to implement a similar solution in asp.net mvc myself, but I don't think it would require a fundamentally different implementation than a webforms-based solution, of which there are various examples on the net:
I've previously built an implementation based on the first link above with web forms. The basic process is:
(Definitely check the second link from MSDN, it's quite different solution, but not one I've only skimmed over.)
The benefit of this is that it doesn't require Javascript at all. The biggest drawback that I can think of (from a user's perspective) is that it's not entirely "Web 2.0" and users will have to wait through a series of browser refreshes.
Something based on @Jan Willem B's AJAX-based suggestion should be a viable alternative to this multi-threaded wait state pattern. Which best meets your requirements is something you'll have to decide on your own. The example from aspfree.com I posted should meet a majority of your requirements though and work just as well with MVC as Web forms.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With