Web Q&A

Visual Studio 2005, HTC Memory Problems, and More

Edited by Nancy Michell

Q In Visual Studio® 2005, when I create a new Visual C# Project from the File menu, I don't see the template ASP.NET Web Application in the template window. If I choose to create a new Web site following the menu path Files | New | Website | General C# and I choose the template ASP.NET Web site, I'm missing many files such as Webform1.aspx.cs, Global.asax, Web.config, AssemblyInfo.cs, and so forth. Why is this happening?

Q In Visual Studio® 2005, when I create a new Visual C# Project from the File menu, I don't see the template ASP.NET Web Application in the template window. If I choose to create a new Web site following the menu path Files | New | Website | General C# and I choose the template ASP.NET Web site, I'm missing many files such as Webform1.aspx.cs, Global.asax, Web.config, AssemblyInfo.cs, and so forth. Why is this happening?

A In Visual Studio 2005 the project model has changed quite a bit (for the better). Now you start with a simplified Web Application into which you can add the things that you really need. In the past, many users didn't even know what Global.asax and web.config were used for.

A In Visual Studio 2005 the project model has changed quite a bit (for the better). Now you start with a simplified Web Application into which you can add the things that you really need. In the past, many users didn't even know what Global.asax and web.config were used for.

The codebehind model has also been enhanced to support a better model—code-beside—that uses new features in Visual Studio 2005 such as partial classes to create pages. By default, depending on the build you have, Visual Studio 2005 will add the pages using this new model. Incidentally, you will also notice that Visual Studio 2005 no longer requires IIS to be installed on the developer machine to create Web sites as its own built-in ASP.NET-enabled Web server is included.

Q Where can I find ASP.NET 2.0 tutorials and samples?

Q Where can I find ASP.NET 2.0 tutorials and samples?

A Take a look at https://www.asp.net/whidbey/pdc.aspx. You'll find information on building server controls, data controls, Master Pages, themes, and more. Also, see the various articles in this issue (June 2004) which discuss developing in ASP.NET 2.0.

A Take a look at https://www.asp.net/whidbey/pdc.aspx. You'll find information on building server controls, data controls, Master Pages, themes, and more. Also, see the various articles in this issue (June 2004) which discuss developing in ASP.NET 2.0.

Q Removing an HTML Component (HTC) from an HTML page does not seem to release memory. I tested this using two functions. The first adds an HTC component to a page 1000 times. The second removes the added components one by one. Adding the components to the page increased Microsoft® Internet Explorer memory usage, but removing the component did not bring down the memory usage. However, whenever I minimize the browser, memory usage comes down. What am I doing wrong?

Q Removing an HTML Component (HTC) from an HTML page does not seem to release memory. I tested this using two functions. The first adds an HTC component to a page 1000 times. The second removes the added components one by one. Adding the components to the page increased Microsoft® Internet Explorer memory usage, but removing the component did not bring down the memory usage. However, whenever I minimize the browser, memory usage comes down. What am I doing wrong?

A According to the Knowledge Base article "Memory Leak Occurs When Behaviors Are Dynamically Removed," your problem is caused by a synchronization issue between Internet Explorer and the script engine.

A According to the Knowledge Base article "Memory Leak Occurs When Behaviors Are Dynamically Removed," your problem is caused by a synchronization issue between Internet Explorer and the script engine.

This fix is included in Internet Explorer 6.0 SP1, but it is turned off by default. To turn on this fix, set the following registry value to either a string value of yes or a binary value of 1:

HKEY_CURRENT_USER\Software\Microsoft\Internet Explorer\Main\Cleanup HTCs

If that doesn't help, you could have a different problem, which is not fixed. According to the Knowledge Base article "Memory Leak Occurs When You Remove Behaviors", a solution is to programmatically refresh the page or browse to another page.

Q How can I lock the Internet Explorer home page seen by my field sales force so that if people change it, it will revert back to the original home page? The guys in the field are running Windows® XP Professional. Can this be done by administering Group Policy locally and over the network when they log on? My users have full administrator rights.

Q How can I lock the Internet Explorer home page seen by my field sales force so that if people change it, it will revert back to the original home page? The guys in the field are running Windows® XP Professional. Can this be done by administering Group Policy locally and over the network when they log on? My users have full administrator rights.

A This option is configurable via the Internet Explorer Administration Kit (IEAK) or Group Policy. The registry setting is:

HKCU,"Software\Policies\Microsoft\Internet Explorer\Control   
    Panel","HomePage",0x10001,1,0,0,0

A This option is configurable via the Internet Explorer Administration Kit (IEAK) or Group Policy. The registry setting is:

HKCU,"Software\Policies\Microsoft\Internet Explorer\Control   
    Panel","HomePage",0x10001,1,0,0,0

For more information check out Knowledge Base article 320159, "Home Page Setting Changes Unexpectedly, or You Cannot Change Your Home Page Setting".

One way to set the Group Policy is to first set the home page using Group Policy through User Configuration | Windows Settings | Internet Explorer Maintenance | URLs | Important URLs | Homepage. Then set the Group Policy so that it cannot be changed using the GUI (as just described) by selecting User Configuration | Admin. Templates | IE. Since the users are administrators (and might be clever), they could change the settings back after the Group Policy is applied because by default as long as the Group Policy doesn't change afterward it won't be applied again.

To remedy this, activate the policy for Internet Explorer Maintenance (Computer Configuration | Admin. Templates | System | Group Policy) and set it so that it will be applied even if the Group Policy did not change. This way the next time the user logs on, the Group Policy check will be performed and the settings will be reapplied, reverting the user's settings to the required settings.

Q Can I attach more than one event to window.onload in JScript®?

Q Can I attach more than one event to window.onload in JScript®?

A Yes. You can fake multicasting by calling any number of methods from your one event handler. To allow the UI to continue processing, you can use setTimeout:

<script language="jscript">
    // you should do this on multiple lines 

    function handleOnLoad() { handlerOne(); handlerTwo(); handlerThree(); }
</script>
<body onLoad="handleOnLoad()" ... />

A Yes. You can fake multicasting by calling any number of methods from your one event handler. To allow the UI to continue processing, you can use setTimeout:

<script language="jscript">
    // you should do this on multiple lines 

    function handleOnLoad() { handlerOne(); handlerTwo(); handlerThree(); }
</script>
<body onLoad="handleOnLoad()" ... />

Also, it is worth noting that there are good and bad ways to fake dynamic multicasting. For a look at some bad ways, see Eric Lippert's article "Multicast Delegates The Evil Way".

Note that this kind of fake multicasting can be done entirely with Internet Explorer-style event handlers. Also note that the comments in that article point out a number of good alternatives, including the use of "attachEvent" in Internet Explorer.

Q I'm trying to run the following snippet in an ASP page:

<%
Set Parent = GetObject("IIS://localhost/W3SVC")
 
For Each Child In Parent
  If IsNumeric(Child.Name) Then
     Response.Write "ProgrammticID: " & Child.Name & "Friendly Name: " & 
         Child.ServerComment & "<BR>"

   End If
Next
%>

Q I'm trying to run the following snippet in an ASP page:

<%
Set Parent = GetObject("IIS://localhost/W3SVC")
 
For Each Child In Parent
  If IsNumeric(Child.Name) Then
     Response.Write "ProgrammticID: " & Child.Name & "Friendly Name: " & 
         Child.ServerComment & "<BR>"

   End If
Next
%>

I keep getting an access denied error on the GetObject request. The page currently runs under the context of an anonymous user who has very little access. What is the minimum amount of security I can apply in order to get this working?

A You have to be at least in the Server Operators group, perhaps even in the Administrators group, to get GetObject to work. Do not add your anonymous user to these groups. Place Access Control Lists on the file so that only administrators of the system can access the file. When an administrator requests the file, it will then be running in the correct security context to complete the task (as long as you are connecting to the local machine). You can then configure the custom error for the HTTP 401 error for this page (or application, as appropriate) to relay to the user that they don't actually have permission to perform the operation, or whatever message is appropriate. You could also do all of this in ASP by using "On Error Resume Next," adding various error checking statements around the GetObject command.

A You have to be at least in the Server Operators group, perhaps even in the Administrators group, to get GetObject to work. Do not add your anonymous user to these groups. Place Access Control Lists on the file so that only administrators of the system can access the file. When an administrator requests the file, it will then be running in the correct security context to complete the task (as long as you are connecting to the local machine). You can then configure the custom error for the HTTP 401 error for this page (or application, as appropriate) to relay to the user that they don't actually have permission to perform the operation, or whatever message is appropriate. You could also do all of this in ASP by using "On Error Resume Next," adding various error checking statements around the GetObject command.

Q I'm looking for some best practices regarding JavaScript and ASP.NET development. For example, what should I be concerned about to ensure proper functioning in multiple browsers? When should I use JavaScript for validation? Do you recommend using validators in all situations?

Q I'm looking for some best practices regarding JavaScript and ASP.NET development. For example, what should I be concerned about to ensure proper functioning in multiple browsers? When should I use JavaScript for validation? Do you recommend using validators in all situations?

A If you want to perform validation and you're using ASP.NET, you can use custom validator controls on the server side. Thus, you can avoid client-side validation, which should never replace actual server-side validation, as the client could be spoofed.

A If you want to perform validation and you're using ASP.NET, you can use custom validator controls on the server side. Thus, you can avoid client-side validation, which should never replace actual server-side validation, as the client could be spoofed.

On the client side, even if you're using Internet Explorer, you may run into JavaScript compatability issues if you are creating any app targeted at multiple browsers and languages. However, some important recommendations and best practices include:

  • Using the least amount of script code possible
  • Placing JavaScript code in a .js file and using <script src="myfile.js" /> tags so the scripts can be cached and the code separated from the UI
  • Avoiding the generation of HTML from your script
  • Using semicolons
  • Deciding on a browser test matrix ahead of time, and using that to test your app
  • If at any point you think you've found a clever trick to exploit, think again

But what you should care about in the JavaScript to support multiple browsers is the wrong question to ask. Eric Lippert wrote about why this is the wrong question in a recent blog entry.

Having a big list of browser differences isn't going to help much. What you need is a method that lets you write portable software. One possibility is to get machines that can run all the browsers you want to support. Then write a little bit of HTML and script, and test it in every browser. If something breaks in one place but not in another, congratulations—you've found a browser incompatibility. Work around it. That is much better than listing every known difference between every version of every browser, comparing every line of code against that list, and hoping for the best. You're going to have to test at some point—so test early and test often.

As far as using JavaScript for validation, that's a good question. For performance you should validate on the client. For security, you should validate on the server.

Since security is more important than performance, you first need to get the server validation right. To reduce the load on the server and decrease the time between when the user enters bad data and when you catch it, adding client-side validation might be a good idea. Before making performance improvements, you need to have measurable goals. See How Bad Is Good Enough? for more guidance on this.

Q I'm using forms authentication, and when the user's session times out, he is sent back to the login.aspx page. At that point, if the user reenters his login information, he is taken back via FormsAuthentication.RedirectFromLoginPage to the page he was last viewing. How can I put a message on the login page to tell them that their session has timed out and they must log in again?

Q I'm using forms authentication, and when the user's session times out, he is sent back to the login.aspx page. At that point, if the user reenters his login information, he is taken back via FormsAuthentication.RedirectFromLoginPage to the page he was last viewing. How can I put a message on the login page to tell them that their session has timed out and they must log in again?

A Two distinct concepts are actually at play here: session state and forms authentication. When using in-process session state, Session_End does not map to your forms authentication session timing out. Session_End will fire silently on the server side x minutes after the last request to an ASPX page in the application (x being the session state timeout). Based on the description you've provided, what seems to be happening is that the authentication ticket embedded within the forms authentication cookie is expiring. Once that happens, the user will be redirected to the login page, but Session_End will not fire.

A Two distinct concepts are actually at play here: session state and forms authentication. When using in-process session state, Session_End does not map to your forms authentication session timing out. Session_End will fire silently on the server side x minutes after the last request to an ASPX page in the application (x being the session state timeout). Based on the description you've provided, what seems to be happening is that the authentication ticket embedded within the forms authentication cookie is expiring. Once that happens, the user will be redirected to the login page, but Session_End will not fire.

You really can't do a Response.Redirect or similar command in Session_End for the simple reason that this happens totally on the server side (without any HttpContext, since no request really caused the session to end).

If you're using in-memory nonpersistent cookies, you could try using something like this in Page_Load of your Login.aspx.cs file:

if(Request.Cookies["SyprosCom"]!=null)
{
    Response.Write("Redirected due to forms. Auth. timeout");
}

However, this logic will fail if you are using persistent cookies and the cookie timeout is equal to the forms authentication ticket timeout. For more information on ASP.NET session state take a look at Understanding session state modes + FAQ, ASP.NET Session State, and Using ASP.NET Session State in a Web Service.

Q I am using session variables to display a navigation bar on a Web page. When I create a child window (Ctrl-N), the session variables are passed on as well. So, on both the pages, the same navigation bar appears. Is there a way to restrict the session variables or figure out if this is a new browser instance or not?

Q I am using session variables to display a navigation bar on a Web page. When I create a child window (Ctrl-N), the session variables are passed on as well. So, on both the pages, the same navigation bar appears. Is there a way to restrict the session variables or figure out if this is a new browser instance or not?

A A child window of Internet Explorer (Ctrl-N) will always use the same session because it is from the same Internet Explorer process. You can't restrict the session variables; you'll have to partition them in your own logic. So taking the second part of your question (figuring out if this is a new browser instance or not), it depends how your navigation works. If it's postback-driven from standard controls you could do the following:

  1. When you paint your page the first time (not a postback), put a unique key (a GUID would do it) into either a hidden form field or ViewState, and put the same key into your session state; call this your "subsession ID."
  2. Check for this key whenever you get a postback. If it's not a match for the one in the session, don't allow access to the session variables you want to restrict to the first subsession, and plop a new GUID into the Viewstate/hidden form field and session state for matching.

A A child window of Internet Explorer (Ctrl-N) will always use the same session because it is from the same Internet Explorer process. You can't restrict the session variables; you'll have to partition them in your own logic. So taking the second part of your question (figuring out if this is a new browser instance or not), it depends how your navigation works. If it's postback-driven from standard controls you could do the following:

  1. When you paint your page the first time (not a postback), put a unique key (a GUID would do it) into either a hidden form field or ViewState, and put the same key into your session state; call this your "subsession ID."
  2. Check for this key whenever you get a postback. If it's not a match for the one in the session, don't allow access to the session variables you want to restrict to the first subsession, and plop a new GUID into the Viewstate/hidden form field and session state for matching.

To make this work you need some sort of hashtable-style data structure stored in session that maps variables associated with this new "subsession ID." Then you can write a simple class that wraps access to session variables so that it keys off that structure, allowing or denying access as appropriate.

Q I'm new to the .NET Framework and I've found that code in the InitializeComponent function is deleted when I change the EnableViewState property value of a page. Why is this happening?

Q I'm new to the .NET Framework and I've found that code in the InitializeComponent function is deleted when I change the EnableViewState property value of a page. Why is this happening?

A If your .aspx/.ascx page stops working for no apparent reason and you've pored over your code, and everything looks exactly as you left it the night before, check the hidden "Web Form Designer generated code" block at the bottom of the codebehind file. Make sure the InitializeComponent method looks like this:

private void InitializeComponent()
{
    this.Load += new System.EventHandler(this.Page_Load);
}

If it doesn't, Visual Studio .NET 2003 may have deleted this code. See the Knowledge Base article "FIX: Code in the InitializeComponent Function Is Deleted When You Change the EnableViewState Property Value of a Page".

A If your .aspx/.ascx page stops working for no apparent reason and you've pored over your code, and everything looks exactly as you left it the night before, check the hidden "Web Form Designer generated code" block at the bottom of the codebehind file. Make sure the InitializeComponent method looks like this:

private void InitializeComponent()
{
    this.Load += new System.EventHandler(this.Page_Load);
}

If it doesn't, Visual Studio .NET 2003 may have deleted this code. See the Knowledge Base article "FIX: Code in the InitializeComponent Function Is Deleted When You Change the EnableViewState Property Value of a Page".

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

Thanks to the following Microsoft developers for their technical expertise: Greg Bybee, Hitesh Chaudhary, Sachin Goregaoker, Mark Ingalls, Andre Kronmaier, Dan Liebling, Eric Lippert, Nathan Manis, Carlos Aguilar Mares, Benjamin Moules, Patrick Ng, Kalmadi Santhosh Rao, Dan Reynolds (Excell Data Corporation), Darren Ross (ConsultNet), Carol Roy, Spyros Sakellariadis, Peter Scheuermann, Dan Sellers, Sean Sutherland, Anurag Vyas, Mark Wilson-Thomas, and Jon Wong.