I have a repeater that displays financial data and prices for various stocks.
On this page, I also have an "export" button that needs to take the data ~on the screen~ and convert it into a CSV for the user.
The problem is, after I databind my list of "Stock" entities:
List<Stock> stocks = GetStocks()
rptStockList.DataSource = stocks;
rptStockList.DataBind();
The data is not persisted on postback.
Also, the data on this page is constantly being updated via an UpdatePanel and a Timer control (being re-databound each time). Every 30 seconds the prices displayed for the various stocks in the repeater control change.
Now, I have a linkbutton that has a click event method in the code-behind that is supposed to export the ~data on the screen~ for the user. I need to grab the current values for the list of stocks last databound to the repeater. I can't simply go grab the latest values from the database because those will have been changed in the time between the last refresh.
protected void lbtnExportStocks_Click(object sender, EventArgs e)
{
// No longer have the stock data used in the repeater control
ExportStocksToExcel();
}
I know that ASP.NET doesn't persist the datasource for the repeater on post-back but I need to still be able to either re-construct this list of Stock entities so I can send them the CSV or I need persist it in some way.
I don't want to do anything that is too heavy handed in terms of performance because during certain days of the week this application can have some heavy usage.
What is the proper solution to this type of situation? Should I iterate through the Repeater's "Items" collection and reconstruct the Stock entities?
Could you store stocks
in Viewstate, or in 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"];
...
}
Session state may actually be the better choice for storing Stocks
since that won't get transmitted to the client in the page (with all the possibilities for 'creative editing' that could entail) - that's probably quite important in an application like this. (Yes, you could encrypt the Viewstate but with an eye on those peak times that's an overhead you might not want.)
A simple method is to render the values as input controls (as opposed to, say, <span>
or bare <td>
elements) - the browser sends input values back to the server when the user posts.
For example:
<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>
The client sends every input value named "Symbol" in an array (and likewise the input values named "Quote"), which you can access in your code-behind like this:
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
}
Of course, at the bottom, this technique is basically writing whatever the client sends you to an Excel file, so you might want to secure or limit the input in some way. That might involve authenticating users and/or throttling the amount of data your method will export. If this is a serious concern in your environment or you can't afford to give it much attention, consider serializing the original data in the user's session instead.
Similarly, if you're intentionally transmitting a large amount of data, you should consider using other approaches for performance reasons. You might use session instead, or or transmit a small key that you can use to reconstruct the data used to build the repeater (for example, if the repeater was bound to the results of a query that doesn't change given its inputs, you can just serialize the input(s) between calls).
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