My webpage lets a user select one or more tools from a list of available tools (by dragging from the "available" list to the "selected" list). There is a HiddenTools
hidden field that is updated every time the two lists change- the <li>
in the ToolsActive
list are stored as a comma separated list of ids in the HiddenTools
. When the user clicks "Save", the value in the HiddenTools
is stored in the database.
aspx page:
<asp:HiddenField runat="server" ID="HiddenTools"/>
/*<li> can be dragged from one list to the other. Every time the lists
change, HiddenTools gets updated with the contents of ToolsSelected
list, formatted as a comma separated string */
<ul id="ToolsAvailable">
<%foreach (KeyValuePair<int,string> tool in unusedTools){ %>
<li id='<%= tool.Key %>'> <%= tool.Value %> </li>
<% } %>
</ul>
<ul id="ToolsActive">
<%foreach (KeyValuePair<int,string> aTool in selectedTools){ %>
<li id='<%= aTool.Key %>'> <%= tool.Value %> </li>
<% } %>
</ul>
<asp:Button ID="btnSave" OnClick="btnSave_Click" runat="server" Text="Save"/>
code-behind:
public partial class Settings
{
protected ToolPreferences prefs;
protected Dictionary<int, string> tools;
protected Dictionary<int, string> unusedTools;
protected Dictionary<int, string> selectedTools;
protected void Page_Load(object sender, EventArgs e)
{
int AccountId = getAccountId();
if(!Page.IsPostBack){
prefs = new ToolPreferences(AccountId);
PopulateTools();
}
}
private void PopulateTools()
{
tools = getPossibleTools();
unusedTools = new Dictionary<int, string>();
selectedTools = new Dictionary<int, string>();
List<int> selectedList = new List<int>();
if (!string.IsNullOrEmpty(prefs.Tools))
{
selectedList = prefs.Tools.Split(',').Select(int.Parse).ToList();
}
foreach (KeyValuePair<int, string> aTool in tools)
{
if (selectedList.Contains(aTool.Key))
{
selectedTools.Add(aTool.Key, aTool.Value);
}
else
{
unusedTools.Add(aTool.Key, aTool.Value);
}
}
}
protected void btnSavePreferences_Click(object sender, EventArgs e)
{
ToolPreferences tp = ToolPreferences (AccountId);
tp.Update(HiddenTools.Value);
}
}
The issue is that after PostBack, the following error appears:
Object reference not set to an instance of an object.
with the following line highlighted:
<%foreach (KeyValuePair<int,string> tool in unusedTools){ %>
If I move the following two lines out of the !PageIsPostBack
check, I don't get that error when the page reloads after postback, but I also don't see the changes the user made to the tools lists until the page is reloaded another time.
prefs = new ToolPreferences(AccountId);
PopulateTools();
Where can I set the tools variables so that the "Object reference not set" error doesn't occur?
Every request is handled by a fresh instance of your page-class, so all instance variables are reset (as you found out).
Values you want to keep over requests should be stored in ViewState (to store values between postbacks in this page) or Session (to keep values between multiple pages).
NB: do not store those values in static variables. They do keep their values between postbacks, but are also shared between all visitors.