Как мне реализовать промежуточную страницу “загрузка ...” в ASP.NET MVC?

StackOverflow https://stackoverflow.com/questions/1650776

Вопрос

У меня есть Поисковый контроллер с действием, которое может выполнить несколько длительных поисковых запросов и вернуть страницу результатов.Поиск может занять от 1 до 60 секунд.URL-адрес для поиска - это HTTP-запрос GET формы: http://localhost/Search?my=query&is=fancy

Опыт, который я ищу, похож на множество туристических сайтов, которые есть в мире.Я хотел бы показать промежуточную страницу "Загрузка ...", где, в идеале:

  1. Пользователь может перезагрузить страницу, не перезапуская поиск
  2. Как только внутренний поиск завершен, пользователь перенаправляется к результатам
  3. Работа с браузерами с отключенным JavaScript ухудшается
  4. Кнопка "Назад" / история браузера не должны включать эту промежуточную страницу.
  5. В случае короткого поиска (1 секунда) это не оказывает существенного влияния ни на время получения результатов, НИ на впечатления (значительно уродливые страницы мигают, что угодно).

Это те, которые приятно иметь.Я открыт для любых идей!Спасибо.

Это было полезно?

Решение

Вы могли бы сделать это следующим образом:

  • выполните поисковый запрос (GET URL) с помощью AJAX
  • URL-адрес поиска не возвращает результаты, но возвращает некоторый контент в формате Json или XML с URL-адресом фактических результатов
  • на странице клиента отображается сообщение "загрузка ..." в ожидании завершения вызова AJAX
  • по завершении страница клиента перенаправляется на страницу результатов.

Пример использования 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>

(редактировать:)

Контроллер был бы чем-то вроде:

public class SearchController 
{
  public ActionResult Query(string q) 
  {
    Session("searchresults") = performSearch();
    return Json(new { ResultsUrl = 'Results'});
  }

  public ActionResult Results()
  {
    return View(Session("searchresults"));
  }
}

Считайте это псевдокодом:на самом деле я это не тестировал.

Другие советы

Чтобы сохранить его без использования javascript, вы можете разбить поиск на несколько действий.

Первое действие (/Поиск/?q=whodunit) просто выполняет некоторую проверку ваших параметров (чтобы вы знали, нужно ли вам повторно отобразить форму), а затем возвращает представление, которое использует мета-обновление, чтобы вернуть браузер к "реальному" поисковому действию.

Вы можете реализовать это с помощью двух отдельных действий контроллера (скажем, поиска и результатов).:

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

Но это дает вам некоторые неудобства в том, что касается освежения.Таким образом, вы можете повторно объединить их обратно в единое действие, которое может само сигнализировать о двухфазном процессе, используя 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(...);
    }
}

Это касается пунктов 2, 3, 4 и, возможно, 5.

Включение поддержки # 1 подразумевает, что вы собираетесь сохранять результаты поиска либо в сеансе, либо в базе данных и т.д..

В этом случае просто добавьте желаемую реализацию кэша как часть бита "Выполнить фактический поиск здесь" и добавьте проверку кэшированного результата, чтобы обойти страницу загрузки.например ,

if (TempData[SearchLoadingPageSentKey]==null)

становится

if (TempData[SearchLeadingPageSentKey]==null && !SearchCache.ContainsKey(q))

Хороший вопрос.Возможно, вскоре мне самому придется реализовать аналогичное решение в asp.net mvc, но я не думаю, что для этого потребуется принципиально иная реализация, чем решение на основе webforms, в сети есть различные примеры:

Ранее я создал реализацию, основанную на первой ссылке выше, с веб-формами.Основным процессом является:

  1. Запрашивается начальная страница с параметрами поиска
  2. Эта страница запускает новый поток, который выполняет длительную задачу
  3. Эта страница перенаправляет пользователя на страницу "в процессе", заголовок http refresh которой настроен на перезагрузку каждые пару секунд
  4. Поток, выполняющий поиск, обновляет "глобальный" статический объект выполнения поиска, указывающий % завершения, и страница в разделе "Процесс" считывает данные из него, отображая прогресс.(каждый поиск хранится по идентификатору GUID в хэш-таблице, поэтому поддерживается несколько одновременных поисков)
  5. После завершения поток обновляет ход поиска как таковой, и когда страница в разделе "Процесс" обнаруживает это, он перенаправляет на конечную страницу "результат".

(Обязательно проверьте вторую ссылку из MSDN, это совсем другое решение, но не то, которое я только просмотрел.)

Преимущество этого в том, что для него вообще не требуется Javascript.Самый большой недостаток, о котором я могу подумать (с точки зрения пользователя), заключается в том, что это не совсем "Веб 2.0", и пользователям придется ждать серии обновлений браузера.

Что-то, основанное на предложении @Jan Willem B на основе AJAX, должно быть жизнеспособной альтернативой этому многопоточному шаблону состояния ожидания.То, что наилучшим образом соответствует вашим требованиям, - это то, что вам придется решать самостоятельно.Пример из aspfree.com, который я опубликовал, должен соответствовать большинству ваших требований и работать с MVC так же хорошо, как и с веб-формами.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top