Web Q&A

ASP.NET Session State, Validation, DataGrids, and More

Edited by Nancy Michell

Q If I have an ASP.NET application using session state and I launch a new browser window from one of my pages, is there a way to force a new session? I need to have two unique sessions for a user, one for the original browser window and one for the new browser window.

Q If I have an ASP.NET application using session state and I launch a new browser window from one of my pages, is there a way to force a new session? I need to have two unique sessions for a user, one for the original browser window and one for the new browser window.

A If you are using a cookie-based session and you just open a new window inside the same Microsoft® Internet Explorer process, you'll share cookies, including the SessionID cookie and thus the same session. If you launch this new window in a separate Internet Explorer process, then you will have a new session even for the same application.

A If you are using a cookie-based session and you just open a new window inside the same Microsoft® Internet Explorer process, you'll share cookies, including the SessionID cookie and thus the same session. If you launch this new window in a separate Internet Explorer process, then you will have a new session even for the same application.

If you're using cookieless session state, the server appends the ID to the URL. According to Knowledge Base article 307598, "INFO: ASP.NET State Management Overview,": "When a session is initiated on first request, the server issues a unique session ID to the user. To persist the session ID, store it in an in-memory cookie (which is the default), or embed it within the request URL after the application name. To switch between cookie and cookieless session state, set the value of the cookieless parameter in the Web.config file to true or false. In cookieless mode, the server automatically inserts the session ID in the relative URLs only. An absolute URL is not modified, even if it points to the same ASP.NET application, which can cause the loss of session variables."

Therefore, you could accomplish what you're looking for by launching a new window using an absolute URL to the same app.

Q I have an ASP.NET page with multiple validator controls. Is it possible to control the order in which the validation rules are executed, client side and server side? Do I need to somehow add an "If field is not null" to the validation to avoid a runtime error? For example, if Field A is required and used in a formula for another field's validator (C > A*B) would that generate an error if the formula happened to be evaluated first and Field A happened to be empty?

Q I have an ASP.NET page with multiple validator controls. Is it possible to control the order in which the validation rules are executed, client side and server side? Do I need to somehow add an "If field is not null" to the validation to avoid a runtime error? For example, if Field A is required and used in a formula for another field's validator (C > A*B) would that generate an error if the formula happened to be evaluated first and Field A happened to be empty?

A You cannot control the order of the validation rules, but if you have a RequiredFieldValidator and a RegularExpressionValidator, the RequiredFieldValidator must fire first before it can check if the data in the control matches the expression.

A You cannot control the order of the validation rules, but if you have a RequiredFieldValidator and a RegularExpressionValidator, the RequiredFieldValidator must fire first before it can check if the data in the control matches the expression.

With regard to validation controls, if you set a RequiredFieldValidator on Field A and a RegularExpressionValidator on the same field, then the RequiredFieldValidator will execute first. But in your scenario, the order of the fields will be important depending on when the validation takes place. If it happens after tabbing out of the control, then the order is definitely important. Plus, client-side validations will execute before the server-side validation.

The firing will happen automatically for all controls with a validation in place, whenever a postback is triggered. The RequiredFieldValidator goes first as no other validation can be done without data in the control.

You do not need additional code to fire a validator or suppress it. The beauty of ASP.NET is that it handles these for you. You can, however, cancel the validation and move on by adding additional code in your application. This is because the validation occurs before the server processes the page and a user could get trapped by validation unless you have a way to cancel the validation without posting back.

Client-side validation is handled by JScript® and will work only on Internet Explorer 4.0 or later, as they support the Document Object Model required to perform client-side validation.

Q My ASP.NET app generates pages dynamically. I don't want the pages cached, so I've added the following code:

Response.Cache.SetCacheability(System.Web.HttpCacheability.NoCache);

This sets the Cache-Control: no-cache header. However, how can I cache static .css and .png files?

Q My ASP.NET app generates pages dynamically. I don't want the pages cached, so I've added the following code:

Response.Cache.SetCacheability(System.Web.HttpCacheability.NoCache);

This sets the Cache-Control: no-cache header. However, how can I cache static .css and .png files?

A It all depends on whether you want the caching to occur in usermode or you want to take it to the next level and cache in the kernel (http.sys). Either way, you should look at the OutputCache info at @ OutputCache. There is also a TechNet IIS Insider article about kernel mode caching and ASP.NET that might be of interest. You can read that at Troubleshooting ASP.NET Page Output Caching.

A It all depends on whether you want the caching to occur in usermode or you want to take it to the next level and cache in the kernel (http.sys). Either way, you should look at the OutputCache info at @ OutputCache. There is also a TechNet IIS Insider article about kernel mode caching and ASP.NET that might be of interest. You can read that at Troubleshooting ASP.NET Page Output Caching.

One solution is to put all static content in a folder (or folders) separate from the active content folders. In IIS, you should explicitly set the time-to-live (TTL) expiration for these folders to a reasonable amount of time—for example, 12 hours. You'll get good performance improvement.

Q I'm getting strange error messages from time to time in my ASP.NET 2.0 Beta 2 application:

Error Message: This is an invalid webresource request.

I have no references to Webresource.axd in my code. I have an error logger in Global.asax that sends me an e-mail when an error occurs, but I don't know what the user did to trigger this. What could cause it?

Q I'm getting strange error messages from time to time in my ASP.NET 2.0 Beta 2 application:

Error Message: This is an invalid webresource request.

I have no references to Webresource.axd in my code. I have an error logger in Global.asax that sends me an e-mail when an error occurs, but I don't know what the user did to trigger this. What could cause it?

A You may have an ill-formed WebResource URL. There should be a couple of query string parameters following every WebResource URL. If that's not the case, then your code may be emitting invalid requests. ASP.NET uses WebResource.axd too, so there may be requests to it even if you don't have code that uses it. Or, you might be using a third-party control that uses this feature.

A You may have an ill-formed WebResource URL. There should be a couple of query string parameters following every WebResource URL. If that's not the case, then your code may be emitting invalid requests. ASP.NET uses WebResource.axd too, so there may be requests to it even if you don't have code that uses it. Or, you might be using a third-party control that uses this feature.

If you can reproduce this, you could take a look at the rendered source of the page that when requested throws the error, and check every WebResource URL to see if any are invalid. Taking a look at IIS logs may also shed some light on the subject. Read the MSDN® online article by Victor Garcia Aprea at Handling Client Files in ASP.NET Whidbey.

Also you might run into issues if you have a Web farm and the machine keys are not identical. Note that if you're using ASP.NET 2.0 Beta 2, it might be double-encoding URLs that reference WebResource.axd, which would obviously generate invalid URLs. This problem will be fixed in the final version of ASP.NET 2.0.

Q I have a DataGrid linked to SQL Server™ in which the first column is a checkbox. The user can select multiple values in the grid. When he retrieves this list, how can I make the page indicate which items were originally checkmarked? Here's a sample:

<asp:TemplateColumn> 
<ItemTemplate> 
<asp:CheckBox id="chkThis" DataField="Choice" SortExpression="Choice" runat="server"/> 
</ItemTemplate> 
</asp:TemplateColumn>

Q I have a DataGrid linked to SQL Server™ in which the first column is a checkbox. The user can select multiple values in the grid. When he retrieves this list, how can I make the page indicate which items were originally checkmarked? Here's a sample:

<asp:TemplateColumn> 
<ItemTemplate> 
<asp:CheckBox id="chkThis" DataField="Choice" SortExpression="Choice" runat="server"/> 
</ItemTemplate> 
</asp:TemplateColumn>

A To get the functionality you're looking for, your TemplateColumn should look like this:

<asp:TemplateColumn SortExpression="Choice"> 
<ItemTemplate> 
<asp:CheckBox runat=server Checked='<%# DataBinder.Eval(Container.DataItem, "Choice") %>' /> 
</ItemTemplate> 
</asp:TemplateColumn>

When your DataGrid is sorted by the Choice field, you should handle the OnSort event, sort your resultset, and rebind the grid.

A To get the functionality you're looking for, your TemplateColumn should look like this:

<asp:TemplateColumn SortExpression="Choice"> 
<ItemTemplate> 
<asp:CheckBox runat=server Checked='<%# DataBinder.Eval(Container.DataItem, "Choice") %>' /> 
</ItemTemplate> 
</asp:TemplateColumn>

When your DataGrid is sorted by the Choice field, you should handle the OnSort event, sort your resultset, and rebind the grid.

Q I have a DataGrid with a templated column that hosts a DropDownList control. How do I get the underlying grid row from within the dropdown's SelectedIndexChanged event?

Q I have a DataGrid with a templated column that hosts a DropDownList control. How do I get the underlying grid row from within the dropdown's SelectedIndexChanged event?

A To get to the DataGrid's row, you need to traverse up the control tree. The DropDownList is contained inside a TableCell, which is contained inside the TableRow you're looking for. The TableRow is strongly typed as a DataGridItem, which inherits from TableRow. To get to the DataGridItem, you need to get the parent (the DataGridItem) of the parent (the TableCell) of the DropDownList control, as shown here:

DataGridItem gridItem = (DataGridItem)ddl.Parent.Parent;

A more general approach would be to use:

DataGridItem gridItem = (DataGridItem)ddl.Container;

This will work no matter how deep in your control tree your sender control is, as long as it's not inside another INamingContainer.

A To get to the DataGrid's row, you need to traverse up the control tree. The DropDownList is contained inside a TableCell, which is contained inside the TableRow you're looking for. The TableRow is strongly typed as a DataGridItem, which inherits from TableRow. To get to the DataGridItem, you need to get the parent (the DataGridItem) of the parent (the TableCell) of the DropDownList control, as shown here:

DataGridItem gridItem = (DataGridItem)ddl.Parent.Parent;

A more general approach would be to use:

DataGridItem gridItem = (DataGridItem)ddl.Container;

This will work no matter how deep in your control tree your sender control is, as long as it's not inside another INamingContainer.

Q I have a situation that demands that a DataGrid (or some other data viewer) opens in updatable mode with all the rows updatable at the same time. I want some of them to be textboxes, some dropdowns, and some non-updatable columns. I know how to do it using an edit column in a DataGrid, but how can I do this for multiple rows?

Q I have a situation that demands that a DataGrid (or some other data viewer) opens in updatable mode with all the rows updatable at the same time. I want some of them to be textboxes, some dropdowns, and some non-updatable columns. I know how to do it using an edit column in a DataGrid, but how can I do this for multiple rows?

A Set up template columns and in the ItemTemplate, add the editable controls you want to use. You'll need to add a control for an explicit user gesture to perform the save. An example is documented here: Top Questions about the DataGrid Web Server Control.

A Set up template columns and in the ItemTemplate, add the editable controls you want to use. You'll need to add a control for an explicit user gesture to perform the save. An example is documented here: Top Questions about the DataGrid Web Server Control.

Q What is the best practice for persisting a recordset in ASP.NET? I have a query that, depending upon which items are selected in the dropdown lists, returns specific data to a DataGrid which the user can then page through.

Q What is the best practice for persisting a recordset in ASP.NET? I have a query that, depending upon which items are selected in the dropdown lists, returns specific data to a DataGrid which the user can then page through.

A The best way to deal with multiple queries to the same data is to cache the DataSet in the ASP.NET cache. You can set the cache expiration policy so that it's appropriate for your data (short expiration if your data changes a lot, long or non-expiring if your data rarely changes). Then when you need to bind your data to the DataGrid, you can retrieve the DataSet from the cache if it's present (memory pressure can expire data from cache) or requery your data if it's not present. You can see a good example under "Cache arbitrary objects in server memory".

A The best way to deal with multiple queries to the same data is to cache the DataSet in the ASP.NET cache. You can set the cache expiration policy so that it's appropriate for your data (short expiration if your data changes a lot, long or non-expiring if your data rarely changes). Then when you need to bind your data to the DataGrid, you can retrieve the DataSet from the cache if it's present (memory pressure can expire data from cache) or requery your data if it's not present. You can see a good example under "Cache arbitrary objects in server memory".

Q I am using EditCommandColumn in a DataGrid and I have created an event handler that handles the update event. I have also added OnUpdateCommand="DataGrid1_Update" in the DataGrid tag in the HTML. I know that this event handler is executing on the update event, but the values I'm getting are the old values. Why is this happening?

Q I am using EditCommandColumn in a DataGrid and I have created an event handler that handles the update event. I have also added OnUpdateCommand="DataGrid1_Update" in the DataGrid tag in the HTML. I know that this event handler is executing on the update event, but the values I'm getting are the old values. Why is this happening?

A How are you data binding on page load? Make sure you're only binding the first time the page is loaded, like this:

Sub Page_Load(sender As Object, e As EventArgs) If Not IsPostBack Then BindGrid() End Sub

When you click on the Update button, the page gets posted to the server. If you don't add the "Not IsPostBack" condition, the DataGrid gets re-bound to the original data every time the page is loaded, which overwrites the new values entered by the user.

A How are you data binding on page load? Make sure you're only binding the first time the page is loaded, like this:

Sub Page_Load(sender As Object, e As EventArgs) If Not IsPostBack Then BindGrid() End Sub

When you click on the Update button, the page gets posted to the server. If you don't add the "Not IsPostBack" condition, the DataGrid gets re-bound to the original data every time the page is loaded, which overwrites the new values entered by the user.

Q I've heard that there are many changes in Web.config in ASP.NET 2.0. What are they?

Q I've heard that there are many changes in Web.config in ASP.NET 2.0. What are they?

A There are actually quite a few: for example, there's IntelliSense®, new sections for providers, and the connectionStrings section. There's the new Configuration API that can read and write both Web.config and Machine.config files that reside on the same server, as well as on different servers via DCOM (the ASP.NET admin site is written on top of these new APIs). Certain sections of the Web.config file can be protected (encrypted using either DPAPI or RSA algorithms). This can be done via the configuration APIs or the enhanced ASPNET_REGIIS tool. See Walkthrough: Encrypting Configuration Information Using Protected Configuration for more information.

A There are actually quite a few: for example, there's IntelliSense®, new sections for providers, and the connectionStrings section. There's the new Configuration API that can read and write both Web.config and Machine.config files that reside on the same server, as well as on different servers via DCOM (the ASP.NET admin site is written on top of these new APIs). Certain sections of the Web.config file can be protected (encrypted using either DPAPI or RSA algorithms). This can be done via the configuration APIs or the enhanced ASPNET_REGIIS tool. See Walkthrough: Encrypting Configuration Information Using Protected Configuration for more information.

Send your questions and comments to  webqa@microsoft.com.

Thanks to  the following Microsoft developers for their technical expertise: Jeff Abrams, Chris Adams, Victor Aprea, Gaurav Bansal, Matthew Barbour, Stephane Bouillon, Michael Bundschuh, Rob Cameron, David Corbin, Andrew Duthie, Sudeep Gopalakrishnan, Tim Heuer, Gurpal Hundal, Ajoy Krishnamoorthy, Eilon Lipton, Alexander Louie, Jakub Oleksy, Markus Oswald, Polita Paulus, Minh Pham, Mike Pope, G. Joel Reyes, Rahul Sachdeva, Mohamed Sharaf, Srinivasa Sivakumar, Olav Tollefsen, and Radomir Zaric.