Web Q&A

Page Ready State, DataGrid Row Deletion, and More

Edited by Nancy Michell

Q JScript® seems to automatically add serializable to classes. When I compile the class shown in Figure 1, it becomes serializable although it is not declared to be so. Why is this?

Q JScript® seems to automatically add serializable to classes. When I compile the class shown in Figure 1, it becomes serializable although it is not declared to be so. Why is this?

Figure 1 Serializable

//@cc_on 
//@set @debug(off) 

package tempuriorg.Test 
{ 
     public class JSTest 
     {
           private var aField : int; 
          public final function get a() : int 
          { 
               return this.aField; 
          } 

          public final function set a(value : int) 
          {
                this.aField = value; 
          } 
     }
}

A You're right, JScript automatically adds serializable to classes. It's by design. In JScript, unlike in C#, a class is serializable by default. If you don't want your class to be serializable, then do this:

public System.NotSerialized class JSTest {...}

A You're right, JScript automatically adds serializable to classes. It's by design. In JScript, unlike in C#, a class is serializable by default. If you don't want your class to be serializable, then do this:

public System.NotSerialized class JSTest {...}

Q When I use window.open to open a new HTML page and then try to access the frameset defined in the new page, the frameset may be unavailable right after window.open is called. As a result, I get a script error at that time. The problem does not occur if setTimeout is used to access the frames collection at a later time:

<html>
<Body> 
<script language='javascript'> 
function test() 
{ 
var a; 
a = window.open('main1.htm', ''); 
a.frames[0].location = 'frame3.htm'; 
} 
</script> 
<a href="https://javascript:void(0);" onclick="test();"> TEST</a> 
</Body>
</html>

Q When I use window.open to open a new HTML page and then try to access the frameset defined in the new page, the frameset may be unavailable right after window.open is called. As a result, I get a script error at that time. The problem does not occur if setTimeout is used to access the frames collection at a later time:

<html>
<Body> 
<script language='javascript'> 
function test() 
{ 
var a; a = window.open('main1.htm', ''); 
a.frames[0].location = 'frame3.htm'; 
} 
</script> 
<a href="https://javascript:void(0);" onclick="test();"> TEST</a> 
</Body>
</html>

A This code is vulnerable to a timing problem because the script code attempts to access the object model of the page in the new window immediately after the window.open call. That forms collection doesn't exist until main1.htm has been parsed, so a script error could occur. The problem can be reproduced by replacing main1.htm with an ASPX page that has a built-in delay.

A This code is vulnerable to a timing problem because the script code attempts to access the object model of the page in the new window immediately after the window.open call. That forms collection doesn't exist until main1.htm has been parsed, so a script error could occur. The problem can be reproduced by replacing main1.htm with an ASPX page that has a built-in delay.

It would be better to check readyState or wait for an event so you know the page is ready to script against. Figure 2 shows one way.

Figure 2 Is the Page Ready?

<script language='javascript'> 
var a; function test() 
{ 
a = window.open('main1.htm', ''); 
     a.document.attachEvent("onreadystatechange", changeFrame0 ); 
     changeFrame0(); 
} 
function changeFrame0() 
{ 
     var state = a.document.readyState; 
     if (state == "complete") 
     { 
     a.frames[0].location = 'frame3.htm'; 
     // debugOut.insertAdjacentText("BeforeEnd", "Complete\n"); 
     a.document.detachEvent(changeFrame0); 
     } 
     else 
     { 
     // debugOut.insertAdjacentText("BeforeEnd", "ReadyState "+state+"\n");
     } 
} 
</script>

Q I have a DataGrid that looks like this:

<asp:datagrid id="dgHome" runat="server" Width="248px" CssClass="taskItem" AutoGenerateColumns="False"> 
<Columns> 
<asp:BoundColumn DataField="task_Text" HeaderText="Task"> 
<HeaderStyle CssClass="dgHead" BackColor="#FFFFCC">
</HeaderStyle> 
</asp:BoundColumn> 
<asp:TemplateColumn HeaderText="Done"> 
<HeaderStyle CssClass="dgHead" BackColor="#FFFFCC"></HeaderStyle> 
<ItemStyle Width="15%"></ItemStyle> 
<ItemTemplate> 
<asp:CheckBox id="Checkbox1" runat="server" />
 ••• 
 </asp:datagrid>

Q I have a DataGrid that looks like this:

<asp:datagrid id="dgHome" runat="server" Width="248px" CssClass="taskItem" AutoGenerateColumns="False"> 
<Columns> 
<asp:BoundColumn DataField="task_Text" HeaderText="Task"> 
<HeaderStyle CssClass="dgHead" BackColor="#FFFFCC"></HeaderStyle> 
</asp:BoundColumn> <asp:TemplateColumn HeaderText="Done"> 
<HeaderStyle CssClass="dgHead" BackColor="#FFFFCC"></HeaderStyle> 
<ItemStyle Width="15%"></ItemStyle> 
<ItemTemplate> 
<asp:CheckBox id="Checkbox1" runat="server" />
 ••• 
 </asp:datagrid>

When a user selects the checkbox in the row and clicks a button, I want to delete the node in the source XML file to which the grid is bound. What is the best way to accomplish this in C#?

A On the postback, you can easily delete the row by importing the XML file to a DataSet and then deleting the row from the table in the DataSet. You can then rebind the grid to the updated data source and serialize the remaining rows to the source file.

A On the postback, you can easily delete the row by importing the XML file to a DataSet and then deleting the row from the table in the DataSet. You can then rebind the grid to the updated data source and serialize the remaining rows to the source file.

Q Are there any new data-bound controls in Visual Studio® 2005? In particular I am interested in a full-featured grid control. I have heard about the GridView but need more info. Will there be an XSL designer for the XML control or will you need to link to existing XSL? What about a data-bound version of the XML control?

Q Are there any new data-bound controls in Visual Studio® 2005? In particular I am interested in a full-featured grid control. I have heard about the GridView but need more info. Will there be an XSL designer for the XML control or will you need to link to existing XSL? What about a data-bound version of the XML control?

A There are tons of new controls including Menu, TreeView, Wizard, DynamicImage, FileUpload, Login, LoginView, LoginStatus, PasswordRecovery, ChangePassword, CreateUserWizard, SiteMap, WebParts, just to mention a few. In this issue of MSDN®Magazine, Dino Esposito devotes a whole article to the GridView.

A There are tons of new controls including Menu, TreeView, Wizard, DynamicImage, FileUpload, Login, LoginView, LoginStatus, PasswordRecovery, ChangePassword, CreateUserWizard, SiteMap, WebParts, just to mention a few. In this issue of MSDN®Magazine, Dino Esposito devotes a whole article to the GridView.

A new version of the XML Designer is scheduled to be shipped with Visual Studio 2005 (not specific to ASP.NET) which is supposed to support XSLT debugging and many new features. If you're looking for a full-featured grid control, GridView is what you want. Other controls include: GridView (the successor to DataGrid), DataList, Repeater, DetailsView (which gets one record at a time and is displayed in a standard layout), and FormView (which gets one record at a time and uses templates).

For data binding, you can use data source controls (see Figure 3). They perform the actual data read/write and expose an interface that data-bound controls can bind to.

Figure 3 Data Source Controls

Control Description
SqlDataSource Performs SQL queries
AccessDataSource Access-specific
ObjectDataSource Middle-tier object; invokes methods
XmlDataSource Reads XML; exposes as a hierarchy
DataSetDataSource Reads XML; exposes as a DataSet
SiteMapDataSource Used with navigation controls

 

To implement a data-bound version of the XML control you don't need a special control. You can use the DataSetDataSource control, which reads an XML file and exposes it as a DataSet; you can then bind any data control to it.

Q How can I log HTTP header sizes for all incoming Web requests?

Q How can I log HTTP header sizes for all incoming Web requests?

A It depends on what you're trying to log. Do you want one number that represents the total size of all headers? Do you want multiple numbers per request with one for each header? If you want the former, then in an ISAPI filter just call GetHeader in PREPROC_HEADERS for ALL_RAW. Call it with a zero size buffer and it will fail with ERROR_INSUFFICIENT_BUFFER and return the size to you (the size will represent the names and values for all headers, as well as the delimiters between them). If you want multiple numbers, then do the same thing, but pass a buffer sufficient for the call to succeed and then parse it for each header.

A It depends on what you're trying to log. Do you want one number that represents the total size of all headers? Do you want multiple numbers per request with one for each header? If you want the former, then in an ISAPI filter just call GetHeader in PREPROC_HEADERS for ALL_RAW. Call it with a zero size buffer and it will fail with ERROR_INSUFFICIENT_BUFFER and return the size to you (the size will represent the names and values for all headers, as well as the delimiters between them). If you want multiple numbers, then do the same thing, but pass a buffer sufficient for the call to succeed and then parse it for each header.

Q I have a hidden field containing some XML data. When the user clicks a button, I want to display this data in a new window with the default XML formatting provided by Microsoft® Internet Explorer. With the following code, I just get the text, but no formatting. I see the XML in the source of the document, so how can I get it to display properly in the new window?

function DisplayXML() 
{ 
     newWin = window.open("",""); 
     if( newWin != null ) 
     { 
          newWin.document.write( document.all["subsXMLDiv"].innerHTML); 
     } 
}

Q I have a hidden field containing some XML data. When the user clicks a button, I want to display this data in a new window with the default XML formatting provided by Microsoft® Internet Explorer. With the following code, I just get the text, but no formatting. I see the XML in the source of the document, so how can I get it to display properly in the new window?

function DisplayXML() 
{ 
     newWin = window.open("",""); 
     if( newWin != null ) 
     { 
          newWin.document.write( document.all["subsXMLDiv"].innerHTML); 
     } 
}

A Try something like the code in Figure 4, which explicitly uses the XSL that Internet Explorer uses to display XML.

A Try something like the code in Figure 4, which explicitly uses the XSL that Internet Explorer uses to display XML.

Figure 4 Using the Internet Explorer XML Stylesheet

function DisplayXML() 
{ 
     newWin = window.open("",""); 
     if( newWin != null ) 
     { 
          var oStyle = new ActiveXObject( "Msxml2.DOMDocument.3.0" ); 
          var oXmlDoc = new ActiveXObject( "Msxml2.DOMDocument.3.0" ); 
          oStyle.async = true; oXmlDoc.loadXML( subsXMLDiv.innerText ); 
          //load the stylesheet that Internet Explorer uses... oStyle.load( "res://msxml3.dll/defaultss.xsl" ); 
          newWin.document.write( oXmlDoc.transformNode( oStyle ) ); 
     } 
}

Q I have hundreds of classic ASP applications joined together in a portal fashion that use an older custom ISAPI filter for authentication. It's a familiar scenario—hundreds of virtual apps running under a single root and sharing a common authentication filter.

Q I have hundreds of classic ASP applications joined together in a portal fashion that use an older custom ISAPI filter for authentication. It's a familiar scenario—hundreds of virtual apps running under a single root and sharing a common authentication filter.

I need to move the applications over to use ASP.NET with forms authentication. I would like to be able to use the ASP.NET session created on login on the old ASP site to keep users from having to log in twice based on the app used in the portal.

So my question is, can I use the ASP.NET session (and session cookie) or do I need to create a new custom authentication provider that's shared across ASP.NET and ASP apps?

A You could use a custom ISAPI filter that would check for the custom authentication cookie. If the cookie is there, it lets the request go through; if not, it sends the user to a logon page. That will keep you from having to modify any of the other apps. Create an HttpModule in .NET (see How To Create an ASP.NET HTTP Module Using Visual C# .NET), set ASP.NET authentication to "None", and do your own cookie encryption and session timeouts in the module. See "Implement Forms-Based Authentication in Your ASP.NET Application by Using C# .NET".

A You could use a custom ISAPI filter that would check for the custom authentication cookie. If the cookie is there, it lets the request go through; if not, it sends the user to a logon page. That will keep you from having to modify any of the other apps. Create an HttpModule in .NET (see How To Create an ASP.NET HTTP Module Using Visual C# .NET), set ASP.NET authentication to "None", and do your own cookie encryption and session timeouts in the module. See "Implement Forms-Based Authentication in Your ASP.NET Application by Using C# .NET".

Q I'm having trouble with Response.Redirect. Here's my code:

Try
      ... 
      Response.Redirect("somepage.aspx") 
      Catch ex As Exception 
      Response.Redirect("error.aspx?ErrMsg=" & ex.Message) 
EndTry

The code goes through the first Response.Redirect line, then hesitates for a second or two, then goes to the Catch block and generates an error that reads "Thread was aborted". As soon as I remove the second Response.Redirect in the Catch area, the error goes away.

Q I'm having trouble with Response.Redirect. Here's my code:

Try 
     ... 
     Response.Redirect("somepage.aspx") 
     Catch ex As Exception 
     Response.Redirect("error.aspx?ErrMsg=" & ex.Message) 
EndTry

The code goes through the first Response.Redirect line, then hesitates for a second or two, then goes to the Catch block and generates an error that reads "Thread was aborted". As soon as I remove the second Response.Redirect in the Catch area, the error goes away.

A By design, Response.Redirect generates a ThreadAbortException. If your redirect is not at the end of an execution flow (more code could be executed after), you should return right away.

A By design, Response.Redirect generates a ThreadAbortException. If your redirect is not at the end of an execution flow (more code could be executed after), you should return right away.

So the correct pattern should be:

Try 
     targetURL = "somepage.aspx" 
     ••• 
Catch ex As Exception 
     Session("errormesage") = ex.message 
     targetURL = "errorpage.aspx" 
Finally 
     ' clean up 
End Try 
Response.Redirect(targetURL)

That would be the best solution, if there is such a thing in this situation. If you have any code after the Response.Redirect, though, you'll still have to put in a return statement. You could also specify a second Boolean parameter to Response.Redirect:

Response.Redirect(targetURL, False)

This prevents Redirect from calling Response.End and throwing an exception.

Got a question? Send questions and comments to  webqa@microsoft.com.

Thanks to the following Microsoft developers for their technical expertise: Bret Bentzinger, Leon Braginski, Jonah Burke, Brian Combs, Silvano Coriani, Steve Dunker, Ravi Gopinath, Geoff Gray, Anand Hegde, Michael Hestness (Volt), Wade Hilmo, Zhisheng Huang, Polita Huff, Duy Le, Drew Leaumont, Igor Leybovich, Eric Lippert, Carlos Aguilar Mares, Richie Meyer, Matt Neerincx, Mike Pope, Angel Saenz-Badillos, Derek R. Smith, Charles Torre, Mark Townsend, Stefan Waldenburger, Michael Whalen, Simon Wu, and Jinsong Yu.