Сохранение значения js из 1 ActionResult для использования в другом ActionResult

У меня есть контроллер, и в одном из ActionResults, есть возвращаемое значение javascript, к которому я могу получить доступ через:

Request.QueryString["frequency"]

Но мне нужно использовать эту же переменную в другом ActionResult, Как я могу это сделать?

Я знаю, что не могу установить

string frequency = "";

в верхней части контроллера, а затем просто установите в 1-м ActionResult,

2 ответа

Решение

HTTP не имеет состояния, каждый запрос имеет свое собственное состояние и экземпляр контроллера.

Ты можешь использовать TempData которые используют Session но удалите значение после прочтения.

Когда ты сказал ActionResult Я полагаю, вы имеете в виду ваши методы действий в контроллере, которые возвращают Actionresult s? например:

public class HomeController : Controller {
    // GET: /Home/
    public ActionResult Index() {
        var freq = Request.QueryString["frequency"];
        // ** Want to persist freq here **
        HomeIndexViewModel model = FooLogic.BarIndex();
        return View();
    }
    // GET: /Home/Detail
    public ActionResult Detail() {
        var freq = **Want to access freq here**;
        HomeDetailViewModel model = FooLogic.BarDetail(freq);
        return View();
    }
}

Поскольку ваш вопрос относится к ActionResult, это может быть любой вид ActionResult - без точного знания того, что вы делаете, этот ответ описывает общий подход к выбору хранилища состояний.

Ключевые вопросы, которые следует задать себе:

  • кому нужно будет увидеть это значение - только тот пользователь, который запросил это значение, или другие пользователи,
    • если пользователь специфичен, они вошли в систему, есть ли у них сеанс?
  • как долго им нужно будет его увидеть (только следующий запрос или, возможно, следующий день)
  • где они ожидают увидеть его (только в текущем браузере или в другом сеансе)

Варианты сохранения данных многочисленны и разнообразны, каждый из них выполняет несколько иную роль, хотя многие из них совпадают с другими в своем потенциальном использовании (например, Session а также TempData). Я перечислил многие из них ниже, и все они могут решить вашу проблему в зависимости от конкретного сценария. Первые два (View-persisted data или TempData), скорее всего, будут полезны для вас, но при отсутствии дополнительной информации вам могут понадобиться другие.

Когда-то в ASP.NET было по крайней мере девять параметров для управления постоянным состоянием пользователя, и многие из них по-прежнему применяются в MVC.


ViewData и ViewBag

  • Доступно: текущему пользователю в текущем запросе, но вы можете использовать его для "сохранения состояния" в сгенерированном html, готовом для передачи в будущие запросы
  • Уместно только в том случае, если ваш ActionResult на самом деле является представлением (а не перенаправлением или другим ActionResult, например FileStreamResult)
  • Позволяет передавать данные из текущего действия контроллера в генерируемое текущее представление, что означает, что вы можете вставить их в объекты на стороне клиента, которые могут отправить их обратно в следующем запросе, например:
    • скрытые поля формы;
    • параметры строки запроса для следующего запроса; или же
    • Переменные javascript для запросов ajax.

Примером этого может быть передача вашего freq переменная в метод просмотра для индекса (например, с помощью ViewBag.Frequency = freq;, а затем использовать его с @Html.ActionLink, Например:

@Html.ActionLink("Click for the Next Action", "Detail", "Home", 
  new { frequency = ViewBag.Frequency }, null)

Ваше действие Подробности становится:

    public ActionResult Detail(int frequency) { ...

Подобные подходы позволят вам использовать значение в скрытых полях формы или в javascript для будущих запросов AJAX, установив переменную javascript с помощью var freq = @Html.Raw(Viewbag.Frequency);, например.

Примечание: есть школа мысли (которую я считаю хорошей), которую вы не должны использовать, вместо этого вы должны создать строго типизированный класс (такой как приведенный выше). HomeIndexViewModel) для модели для каждого представления, чтобы вы могли лучше протестировать действия и представления контроллера.

Преимущества ViewData / ViewBag:

  • Он поддерживает состояние без сохранения состояния на вашем сервере, поэтому вам не нужно беспокоиться о том, что рабочие процессы будут перезагружены, следующий запрос будет отправлен на другой сервер в вашей веб-ферме и т. Д.
  • Это потенциально "доказательство кнопки назад", так как ваше "состояние" находится на странице, которая была отображена

Недостатки:

  • Только полезные действия, которые делают HTML
  • Не все данные должны быть подтверждены кнопкой назад, некоторые данные должны постоянно развиваться и поэтому храниться как состояние на стороне сервера (например, число посещений страницы)

TempData

  • Доступно: текущему пользователю, в этом и следующем запросе
  • По умолчанию (в MVC 4) это реализуется SessionStateTempDataProvider (см. документацию)
  • Он действительно предназначен для использования, когда ваш ActionResult представляет собой перенаправление на другое действие, таким образом вы знаете точную область действия и время жизни сохраненных вами данных.

Якобы это сделано для того, чтобы делать именно то, что вы хотите, но есть соображения.

  • Он зависит от состояния сеанса, поэтому работает для сценариев веб-фермы и веб-сада, только если вы правильно настроили состояние сеанса.
  • Состояние сеанса также может не сохраняться между циклами рабочих процессов в зависимости от вашей настройки.
  • Вам также нужно беспокоиться о том, что происходит в "кнопке назад" или в сценарии F5, поскольку данные могут быть недоступны во второй раз.

сессия

  • Доступно для: текущего пользователя, в рамках текущего сеанса для них. Область также зависит от того, как вы настроили состояние сеанса (например, чтобы быть локальным по отношению к домену приложения или к базе данных, поддерживаемой и доступной через веб-ферму)

Это имеет все те же соображения, что и TempData, но вы выбираете, когда удалять значение из Session, Он действительно предназначен для общей информации, относящейся к текущему сеансу (например, простая корзина покупок, которую пользователь не ожидал бы увидеть, если он закроет и снова откроет браузер или посетит сайт на своем мобильном телефоне позже).


кэш

  • Доступно для: всех пользователей, но только в пределах текущего домена приложения (так что будьте осторожны с утилизацией рабочих процессов, веб-ферм, веб-садов и т. Д.)

Вы можете получить к нему доступ через свойство HttpContext вашего контроллера. Например:

HttpContext.Cache["Frequency"] = freq;

Печенье

  • Доступно: текущему пользователю, но только из браузера, который использовался для исходного запроса

Файлы cookie часто игнорируются как постоянные состояния, но они очень полезны для некоторых видов данных. Помните, что если пользователь ожидает увидеть данные, связанные с идентификатором пользователя, то cookie не поможет, если они войдут на другой компьютер, используют сеанс браузера Incognito/Private и т. Д.


База данных

  • Доступно: всем пользователям, или только текущему пользователю, так долго или коротко, как вам нравится - вы сами выбираете.

Базы данных - папа государственной настойчивости. Код вашего приложения должен рассматриваться как изменчивый и способный справляться с перезапусками, сценариями веб-фермы и т. Д. И т. Д. Если вы хотите хранить данные, используйте базу данных. Под "базой данных" я подразумеваю среду хранения данных в любой форме, от SQL Server до Redis, файловое хранилище Azure, табличное хранилище Azure, Amazon S3 и т. Д.


Другие опции

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

Статические или одиночные классы

  • Доступно: всем пользователям, все запросы к этому рабочему процессу на этом сервере
  • Данные будут сохраняться только в рамках одного рабочего процесса (поэтому это имеет значение для веб-ферм и веб-садов) и только до перезапуска рабочего процесса asp.
  • Безопасность потока все еще остается проблемой, но, по крайней мере, вы можете инкапсулировать логику безопасности потока в этом классе
  • Очень редко полезно из-за связи с временем жизни рабочего процесса и с одним сервером

Что не использовать

Поля класса контроллера (экземпляр)

  • Доступно: текущему пользователю, только текущему запросу (Отказ от ответственности: я считаю, что новый контроллер создается для каждого запроса во всех версиях MVC, но если это не так, то вы никогда не будете использовать их для сохранения состояния)

Теоретически вы никогда не будете использовать их (если это не 10-минутное приложение для демонстрации для ваших коллег):

  • Поскольку поля экземпляра в классе сохраняются только на время класса (следовательно, на длительность текущего запроса), если вы хотите сохранить состояние (данные) для запроса, вы должны использовать переменные в вашем методе Action, чтобы лучше передать намерение / управлять объем объектов / ценностей.
  • Поэтому, если вы используете поля экземпляра в вашем контроллере, вы, вероятно, делитесь данными для методов контроллера, которые вы вызываете из своего действия.
  • Это означает, что вы, вероятно, используете свой контроллер для реализации бизнес-логики.
  • В соответствии с современной практикой, контроллеры должны представлять собой набор действий, которые вызывают бизнес-логику (включая модели поколений любого поколения) (тонкие, а не жирные контроллеры).
  • Ergo: Поля экземпляра класса контроллера указывают, что вы должны реструктурировать свой код

Времена, когда вам нужны поля экземпляра на контроллере, это когда вы предоставляете общие сервисы для всех действий, таких как интерфейсы IoC, но они не сохраняют состояние внутри или между запросами.


Поля класса контроллера (статические)

  • Доступно: всем пользователям, все запросы к этому рабочему процессу на этом сервере
  • Не очень хорошая идея - статические поля будут доступны всем пользователям во всех потоках, так что вам нужно беспокоиться о безопасности потоков. Существуют лучшие хранилища состояний, доступные из коробки, если вы хотите обмениваться данными между всеми пользователями, такими как Cache
Другие вопросы по тегам