Как я могу сохранить данные из репитера после обратной передачи? - PullRequest
7 голосов
/ 01 июля 2010

У меня есть повторитель, который отображает финансовые данные и цены на различные акции.

На этой странице у меня также есть кнопка «Экспорт», которая должна взять данные ~ на экране ~ и преобразовать их в CSV для пользователя.

Проблема в том, что после того, как я свяжу свой список «фондовых» сущностей:

List<Stock> stocks = GetStocks()
rptStockList.DataSource = stocks;
rptStockList.DataBind();

Данные не сохраняются при обратной передаче.

Кроме того, данные на этой странице постоянно обновляются через UpdatePanel и элемент управления Timer (каждый раз повторно привязываются к данным). Каждые 30 секунд цены, отображаемые для различных акций в контроллере повторителя, меняются.

Теперь у меня есть кнопка ссылки, в коде которой есть метод события click, который должен экспортировать данные на экране для пользователя. Мне нужно захватить текущие значения для списка акций, последних привязанных к повторителю. Я не могу просто взять последние значения из базы данных, потому что они будут изменены во время между последним обновлением.

protected void lbtnExportStocks_Click(object sender, EventArgs e)
{
    // No longer have the stock data used in the repeater control
    ExportStocksToExcel();
}

Я знаю, что ASP.NET не сохраняет источник данных для повторителя на обратной передаче, но мне все еще нужно иметь возможность либо заново создать этот список объектов Stock, чтобы я мог отправить им CSV, либо мне нужно сохранить это в некотором роде.

Я не хочу делать что-то слишком сложное с точки зрения производительности, потому что в определенные дни недели это приложение может интенсивно использоваться.

Каково правильное решение ситуации такого типа? Должен ли я перебрать коллекцию «Предметов» Повторителя и реконструировать объекты Stock?

Ответы [ 4 ]

1 голос
/ 01 июля 2010

Простой метод - представить значения в качестве элементов управления вводом (в отличие, скажем, от <span> или голых <td> элементов) - браузер отправляет входные значения обратно на сервер, когда пользователь публикует сообщения.

Например:

<ItemTemplate>
    Symbol: <input type="text" readonly="readonly" name="Symbol" value="<%# Container.DataItem("Symbol") %> />
    Quote: <input type="text" readonly="readonly" name="Quote" value="<%# Container.DataItem("Quote") %> />
</ItemTemplate>

Клиент отправляет каждое входное значение с именем «Символ» в массиве (и аналогично входным значениям с именем «Цитата»), к которым вы можете получить доступ в коде, например так:

protected void lbtnExportStocks_Click(object sender, EventArgs e) {

    // They come out as comma-delimited strings
    string[] symbols = Request.Form["Symbol"].Split(',');
    string[] quotes  = Request.Form["Quote"].Split(',');

    // ... continue exporting stocks to Excel
}

Конечно, в нижней части этот метод в основном записывает все, что клиент отправляет вам в файл Excel, поэтому вы можете захотеть защитить или ограничить ввод каким-либо образом.Это может включать аутентификацию пользователей и / или регулирование объема данных, экспортируемых вашим методом.Если это серьезная проблема в вашей среде или вы не можете позволить себе уделять ей много внимания, рассмотрите возможность сериализации исходных данных в сеансе пользователя.

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

1 голос
/ 01 июля 2010

Не могли бы вы сохранить stocks в Viewstate или в сеансе? например,

List<Stock> stocks = GetStocks()
rptStockList.DataSource = stocks;
rptStockList.DataBind();

ViewState.Remove("stocks");
ViewState.Add("stocks", stocks);

private void ExportStocksToExcel
{
    List<Stock> persistedStocks;

    persistedStocks = (List<Stock>)Page.ViewState["stocks"];
    ...
}

Состояние сеанса на самом деле может быть лучшим выбором для хранения Stocks, поскольку оно не будет передано клиенту на странице (со всеми возможностями для «творческого редактирования», которые могут повлечь за собой) - это, вероятно, очень важно в приложение, как это. (Да, вы можете зашифровать Viewstate, но с учетом тех пиковых нагрузок, которые вам могут не понадобиться.)

0 голосов
/ 01 июля 2010

Я бы либо взял ответ Фила и сериализовал весь набор данных, ИЛИ создал бы какой-нибудь объект критерия, который передается в GetStocks (), чтобы указать, какие данные получить.Затем сериализуйте и сохраните объект критерия во ViewState, поэтому, когда пользователь нажимает кнопку «Экспорт», вы можете получить критерии и извлечь те же данные.() имеет StockCriteria в качестве параметра и создает запрос на его основе.

0 голосов
/ 01 июля 2010

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

Page_Load(...){
  if (! Page.IsPostBack){
    //first time page loads do this block

    //stuff
    //databinding stuff
  }
}
...