如何在回发后保留转发器中的数据?

时间:2010-07-01 18:17:39

标签: asp.net ajax postback repeater

我有一个转发器,显示各种股票的财务数据和价格。

在这个页面上,我还有一个“导出”按钮,需要在屏幕上显示数据〜并将其转换为用户的CSV。

问题是,在我对“Stock”实体列表进行了数据绑定之后:

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

数据不会在回发中保留。

此外,此页面上的数据通过UpdatePanel和Timer控件(每次都重新数据绑定)不断更新。每隔30秒,转发器控件中各种股票显示的价格会发生变化。

现在,我有一个链接按钮,它在代码隐藏中有一个单击事件方法,可以在屏幕上为用户导出〜数据。我需要获取最后数据绑定到转发器的股票列表的当前值。我不能简单地从数据库中获取最新值,因为这些值将在上次刷新之间的时间内更改。

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

我知道ASP.NET不会在post-back上保留转发器的数据源,但是我仍然需要重新构建这个Stock实体列表,这样我就可以发送CSV或者我需要持久化它在某种程度上。

我不想做任何在性能方面过于繁重的事情,因为在一周的某些日子里,这个应用程序可能会有大量使用。

这种情况的正确解决方案是什么?我应该遍历Repeater的“Items”集合并重建Stock实体吗?

4 个答案:

答案 0 :(得分:1)

您可以将stocks存储在Viewstate或Session中吗? e.g。

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,但要关注那些您可能不想要的高峰时间。)

答案 1 :(得分:1)

一种简单的方法是将值呈现为输入控件(而不是<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>

客户端在数组中发送名为“Symbol”的每个输入值(以及名为“Quote”的输入值),您可以在代码隐藏中访问,如下所示:

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文件的任何内容,因此您可能希望以某种方式保护或限制输入。这可能涉及对用户进行身份验证和/或限制方法将导出的数据量。如果这是您环境中的一个严重问题,或者您无法给予太多关注,请考虑在用户会话中序列化原始数据。

同样,如果您故意传输大量数据,则出于性能原因应考虑使用其他方法。您可以使用会话,或者传输可用于重建用于构建转发器的数据的小键(例如,如果转发器绑定到查询的结果,而该查询的结果不会因为其输入而改变,则可以在调用之间序列化输入。)

答案 2 :(得分:0)

听起来像在你的Page_Load方法中,你正在对你的转发器进行某种绑定。出于您的目的,这很糟糕,正如您所看到的,它将在每次回发时将您的数据分开。你能确定你的Page_Load是这样的吗? :

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

    //stuff
    //databinding stuff
  }
}

答案 3 :(得分:0)

我要么接受Phil的答案并序列化整个数据集,要么创建某种标准对象,传递给GetStocks()以指定要获取的数据。然后在ViewState中序列化并存储条件对象,因此当用户单击“导出”时,您可以提取条件并检索相同的数据。

即,

[Serializable]
public class StockCriteria
{
    public DateTime DateFrom { get; set; }
    public DateTime DateTo { get; set; }
    public string[] Symbols { get; set; }
}

然后GetStocks()将StockCriteria作为参数并基于它创建查询。