<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://blogs.msdn.com/utility/FeedStylesheets/atom.xsl" media="screen"?><feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en-US"><title type="html">Jerry Orman</title><subtitle type="html">New and improved! Now covering SharePoint</subtitle><id>http://blogs.msdn.com/jorman/atom.xml</id><link rel="alternate" type="text/html" href="http://blogs.msdn.com/jorman/default.aspx" /><link rel="self" type="application/atom+xml" href="http://blogs.msdn.com/jorman/atom.xml" /><generator uri="http://communityserver.org" version="2.1.61025.2">Community Server</generator><updated>2006-07-24T08:35:00Z</updated><entry><title>My SharePoint Sites displays a link that you no longer have access to</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/jorman/archive/2009/08/02/my-sharepoint-sites-displays-a-link-that-you-no-longer-have-access-to.aspx" /><id>http://blogs.msdn.com/jorman/archive/2009/08/02/my-sharepoint-sites-displays-a-link-that-you-no-longer-have-access-to.aspx</id><published>2009-08-03T01:09:00Z</published><updated>2009-08-03T01:09:00Z</updated><content type="html">Under My LInks, My SharePoint Sites, you see a link to a site, but when you click on the link, you are directed to the Access Denied page. It's possible, you may be running into this scenario: Sub site is setup to inherit permissions from the parent Users were in the Members group of the parent site. The Profile Synchronization job ran and added the link to the subsite in My SharePoint Sites. Break permissions inheritance on the sub site. This copies all the permissions into the sub site Remove all...(&lt;a href="http://blogs.msdn.com/jorman/archive/2009/08/02/my-sharepoint-sites-displays-a-link-that-you-no-longer-have-access-to.aspx"&gt;read more&lt;/a&gt;)&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9855782" width="1" height="1"&gt;</content><author><name>Jorman</name><uri>http://blogs.msdn.com/members/Jorman.aspx</uri></author><category term="MOSS" scheme="http://blogs.msdn.com/jorman/archive/tags/MOSS/default.aspx" /><category term="SharePoint 2007" scheme="http://blogs.msdn.com/jorman/archive/tags/SharePoint+2007/default.aspx" /><category term="My SharePoint Sites" scheme="http://blogs.msdn.com/jorman/archive/tags/My+SharePoint+Sites/default.aspx" /><category term="Memberships" scheme="http://blogs.msdn.com/jorman/archive/tags/Memberships/default.aspx" /></entry><entry><title>Overview of My SharePoint Sites and how the data is populated</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/jorman/archive/2009/07/30/my-sharepoint-sites-memberships-general-overview-on-how-this-functionality-works.aspx" /><id>http://blogs.msdn.com/jorman/archive/2009/07/30/my-sharepoint-sites-memberships-general-overview-on-how-this-functionality-works.aspx</id><published>2009-07-30T20:26:00Z</published><updated>2009-07-30T20:26:00Z</updated><content type="html">SharePoint gives you the ability to get a list of sites that your login account is explicitly a member of. This grouping of links is built on the server-side by the Profile Synchronization timer job that runs for each Web Application. The data is stored in the SSP database and is visible in the following locations: SharePoint Web UI Under your My Site by clicking the Memberships link From the My Links menu next to the "Welcome LoginName" link. Once you have informaiton in the Memberships view of...(&lt;a href="http://blogs.msdn.com/jorman/archive/2009/07/30/my-sharepoint-sites-memberships-general-overview-on-how-this-functionality-works.aspx"&gt;read more&lt;/a&gt;)&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9853572" width="1" height="1"&gt;</content><author><name>Jorman</name><uri>http://blogs.msdn.com/members/Jorman.aspx</uri></author><category term="MOSS" scheme="http://blogs.msdn.com/jorman/archive/tags/MOSS/default.aspx" /><category term="SharePoint 2007" scheme="http://blogs.msdn.com/jorman/archive/tags/SharePoint+2007/default.aspx" /><category term="My SharePoint Sites" scheme="http://blogs.msdn.com/jorman/archive/tags/My+SharePoint+Sites/default.aspx" /><category term="Memberships" scheme="http://blogs.msdn.com/jorman/archive/tags/Memberships/default.aspx" /></entry><entry><title>SharePoint My Site link stops redirecting users to their Personal Site</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/jorman/archive/2009/01/19/sharepoint-my-site-link-stops-redirecting-users-to-their-personal-site.aspx" /><id>http://blogs.msdn.com/jorman/archive/2009/01/19/sharepoint-my-site-link-stops-redirecting-users-to-their-personal-site.aspx</id><published>2009-01-19T23:55:00Z</published><updated>2009-01-19T23:55:00Z</updated><content type="html">&lt;P&gt;Hopefully this can save someone some time.&amp;nbsp; The symptoms are:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;Clicking the My Site link in a SharePoint site results in an IIS 404 File Not Found error page being returned.&amp;nbsp; However, you are able to browse directly to the users My Site by browsing &lt;A href="http://mysite/personal/user"&gt;http://mysite/personal/user&lt;/A&gt;.&amp;nbsp; [http://mysite is the URL to the web application hosting the Personal Sites].&amp;nbsp; &lt;/LI&gt;
&lt;LI&gt;Browsing anything in _layouts on this Web Application returns an IIS 404 File Not Found error page.&amp;nbsp; For example, the following URL would fail:&amp;nbsp; &lt;A href="http://mysite/personal/user/_layouts/settings.aspx"&gt;http://mysite/personal/user/_layouts/settings.aspx&lt;/A&gt;.&lt;/LI&gt;
&lt;LI&gt;IIS shows the _layouts directory and it is configured the way other working web applications are configured.&lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;After doing some troubleshooting, we found that IIS is not trying to load any files from the Web Application content path.&amp;nbsp; So the web.config is not even being looked for when browsing _layouts or the root of the My Site.&amp;nbsp; We were able to find that the site collection in the root of the Web Application was missing.&amp;nbsp; You can check for a Site Collection at "/" using "stsadm.exe -o enumsites -url http://mysite" or browsing Central Admin | Application Management&amp;nbsp;| Site Collection List.&lt;/P&gt;
&lt;P&gt;The root site collection in the My Site Web Application redirects users to their Personal Site.&amp;nbsp; If the user does not have a My Site, this Site Collection creates one for them.&amp;nbsp; It also displays the public information about users.&amp;nbsp;&amp;nbsp;&amp;nbsp;Since this site was missing, SharePoint returns a 404 File Not Found message and no one is redirected to their My Site.&lt;/P&gt;
&lt;P&gt;The reason the Site Collection was missing was because an admin tried to delete a user's My Site.&amp;nbsp; The tricky part in this situation is when a user browses another person's My Site, they get redirected to a page in the root site collection.&amp;nbsp; Here's the scenario:&lt;/P&gt;
&lt;OL&gt;
&lt;LI&gt;You need to delete user bobsmith's My Site and decide to do this by browsing the Site Collection, going into Site Settings and deleting the Site Collection.&lt;/LI&gt;
&lt;LI&gt;Open a browser and enter the URL to the&amp;nbsp;persons My Site:&amp;nbsp;&lt;A href="http://mysites/personal/bobsmith"&gt;http://mysites/personal/bobsmith&lt;/A&gt;&amp;nbsp;.&amp;nbsp; &lt;/LI&gt;
&lt;LI&gt;Since you are not logged in as bobsmith, you get redirected to &lt;A href="http://mysite/person.aspx?accountname"&gt;http://mysite/person.aspx?accountname&lt;/A&gt;...&lt;/LI&gt;
&lt;LI&gt;When you click on Site Actions | Site Settings, you are really doing this on the root Site Collection at "/" and not the one for bobsmith at /personal/bobsmith.&amp;nbsp; Deleting the Site Collection in this manner, will result in the root Site Collection being deleted.&lt;/LI&gt;
&lt;LI&gt;It is important to note that by default the SharePoint System account is the only account that can perform the delete action.&lt;/LI&gt;&lt;/OL&gt;
&lt;P&gt;In order to get the Site Collection back, you need to do the following:&lt;/P&gt;
&lt;OL&gt;
&lt;LI&gt;Browse Central Administration | Application Management&lt;/LI&gt;
&lt;LI&gt;Click Create Site Collection&lt;/LI&gt;
&lt;LI&gt;Select the My Site Web Application&lt;/LI&gt;
&lt;LI&gt;Set the Title to My Site&lt;/LI&gt;
&lt;LI&gt;For URL, select the "/" option for the root&amp;nbsp;&lt;/LI&gt;
&lt;LI&gt;Select the My Site Host site template on the Enterprise tab&lt;/LI&gt;
&lt;LI&gt;Set the SharePoint System account as the owner.&lt;/LI&gt;
&lt;LI&gt;Click OK&lt;/LI&gt;&lt;/OL&gt;
&lt;P&gt;&amp;nbsp;If you need to delete an individual's My Site, you need to use the Delete Site Collection option in Central Admin | Application Management, or the STSAdm.exe command-line (stsadm -o deletesite -url &lt;A href="http://mysite/personal/bobsmith"&gt;http://mysite/personal/bobsmith&lt;/A&gt;).&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9340849" width="1" height="1"&gt;</content><author><name>Jorman</name><uri>http://blogs.msdn.com/members/Jorman.aspx</uri></author><category term="MOSS" scheme="http://blogs.msdn.com/jorman/archive/tags/MOSS/default.aspx" /></entry><entry><title>Check if a Word doc is password protected prior to uploading it to a web site</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/jorman/archive/2008/11/24/check-if-a-word-doc-is-password-protected-prior-to-uploading-it-to-a-web-site.aspx" /><link rel="enclosure" type="application/x-zip-compressed" length="39556" href="http://blogs.msdn.com/jorman/attachment/9139188.ashx" /><id>http://blogs.msdn.com/jorman/archive/2008/11/24/check-if-a-word-doc-is-password-protected-prior-to-uploading-it-to-a-web-site.aspx</id><published>2008-11-25T00:42:00Z</published><updated>2008-11-25T00:42:00Z</updated><content type="html">&lt;P&gt;I apologize for the delay between blogs.&amp;nbsp; Switched jobs within Microsoft last December and moved from Texas to Southern California as part of that transfer.&amp;nbsp; Needless to say, I've been insanely busy :-)&lt;/P&gt;
&lt;P&gt;Anyway...this was an interesting question I received a couple months back and have been meaning to blog about it.&amp;nbsp; The problem:&amp;nbsp; How can you check if a Word document is password protected when uploading it to an ASP.Net based application?&amp;nbsp; &lt;/P&gt;
&lt;P&gt;This may not seem that complicated...you could upload the file to the server, then load the Word Object Model on the server and check some properties.&amp;nbsp; Not so fast there!&amp;nbsp; The problem with this approach is that leveraging the Office Object Model in a service based process [i.e. non-interactive] is not supported.&amp;nbsp; Someone wrote a Knowledge Base article on this, and if you call in to support for help with a hanging ASP.Net application and you are automating Office, this will likely be the link you will receive in the email explaining what's going on:&amp;nbsp;&lt;/P&gt;
&lt;P&gt;257757&amp;nbsp; Considerations for server-side Automation of Office&lt;BR&gt;&lt;A href="http://support.microsoft.com/default.aspx?scid=kb;EN-US;257757" mce_href="http://support.microsoft.com/default.aspx?scid=kb;EN-US;257757"&gt;http://support.microsoft.com/default.aspx?scid=kb;EN-US;257757&lt;/A&gt;&lt;BR&gt;&lt;/P&gt;
&lt;P&gt;Without being able to load the Office DLL's into the ASP.Net application pool, this leaves you with running some code on the client to perform the check.&amp;nbsp; I came up with a sample that leverages JavaScript, a .Net Winform control running in the browser, and a File Upload control to do this work.&amp;nbsp; The idea was to only leverage the .Net Winform control to check if the file was password protected.&amp;nbsp; The sample also shows how to handle events across the Winform control and JavaScript.&amp;nbsp; &lt;/P&gt;
&lt;P mce_keep="true"&gt;The general process is:&lt;/P&gt;
&lt;OL&gt;
&lt;LI&gt;
&lt;DIV mce_keep="true"&gt;User types in or selects a file by clicking the Browse button generated by the File Upload HTML control&lt;/DIV&gt;&lt;/LI&gt;
&lt;LI&gt;
&lt;DIV mce_keep="true"&gt;When the focus moves away from this control, JavaScript runs that sets a public property on the WinForm control to the FileName the person is uploading.&lt;/DIV&gt;&lt;/LI&gt;
&lt;LI&gt;
&lt;DIV mce_keep="true"&gt;When the user clicks Submit, which is the WinForm control, code runs to open the Word Document to determine that the file is password protected.&amp;nbsp; If the file is not password protected, the OnSubmitClick event is fired.&lt;/DIV&gt;&lt;/LI&gt;
&lt;LI&gt;
&lt;DIV mce_keep="true"&gt;There is JavaScript in the ASPX page that listens for the OnSubmitClick event and submits the form when this fires.&amp;nbsp; This posts the file to the server.&lt;/DIV&gt;&lt;/LI&gt;&lt;/OL&gt;
&lt;P mce_keep="true"&gt;The code is a sample, there could be more checks to ensure that Word is installed on the box and ensuring that they are selecting a supported file extension, but the idea is the same.&amp;nbsp; The Submit button or file upload control could use some look-and-feel changes to make them look the same.&amp;nbsp; There are two projects in the attached Zip file:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;
&lt;DIV mce_keep="true"&gt;Uploader – this is the WinForm project.&amp;nbsp; The .cs file is commented with the details.&lt;/DIV&gt;&lt;/LI&gt;
&lt;LI&gt;
&lt;DIV mce_keep="true"&gt;UploaderTest – this is an ASP.Net project.&amp;nbsp; Both the ASPX and the .cs file are fully commented.&lt;/DIV&gt;&lt;/LI&gt;&lt;/UL&gt;
&lt;P mce_keep="true"&gt;The only downside to having to run the .Net code on the client is client-side permissions.&amp;nbsp; By default, code running in the browser runs in one of 3 Code Access Security (CAS) groups that have varying levels of restriction (LocalIntranet, TrustedSites, and Internet).&amp;nbsp; None of which give access that you need to do what you want.&amp;nbsp; If the URL does not contain periods [typically only in an Intranet environment], give the LocalIntranet zone FullTrust to have your code run or you can create a custom security code group to fully trust your specific URL.&amp;nbsp; If the URL has periods, it will run in the InternetZone by default.&amp;nbsp; Here are the steps in case you are unfamiliar:&lt;/P&gt;
&lt;P mce_keep="true"&gt;1.&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; On the client machine&lt;BR&gt;2.&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Open Administrative Tools&lt;BR&gt;3.&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Open the latest .Net Configuration (1.1 or 2.0 Framework)&lt;BR&gt;4.&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Expand My Computer | Runtime Security Policy | Machine | Code Groups&lt;BR&gt;5.&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Right-click All_Code, select New…&lt;BR&gt;6.&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Fill in the Name and click Next&lt;BR&gt;7.&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; From the “Condition type” dropdown, select URL&lt;BR&gt;8.&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; For the URL, type in the path to the directory hosting the ASPX and DLL:&amp;nbsp; &lt;A href="http://web01/myapp/" mce_href="http://web01/myapp/"&gt;http://web01/myapp/&lt;/A&gt;*&lt;BR&gt;9.&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Click Next and use Full Trust and finish the wizard&lt;/P&gt;
&lt;P mce_keep="true"&gt;Good luck!&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9139188" width="1" height="1"&gt;</content><author><name>Jorman</name><uri>http://blogs.msdn.com/members/Jorman.aspx</uri></author></entry><entry><title>Loading C++ Assemblies in ASP.Net</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/jorman/archive/2007/08/31/loading-c-assemblies-in-asp-net.aspx" /><id>http://blogs.msdn.com/jorman/archive/2007/08/31/loading-c-assemblies-in-asp-net.aspx</id><published>2007-08-31T23:29:00Z</published><updated>2007-08-31T23:29:00Z</updated><content type="html">&lt;P&gt;When you reference a Native C++ assembly from ASP.Net you may run into the following error:&lt;/P&gt;
&lt;P&gt;System.IO.FileNotFoundException: The specified module could not be found. &lt;BR&gt;(Exception from HRESULT: 0x8007007E)&lt;/P&gt;
&lt;P&gt;[FileNotFoundException: The specified module could not be found. (Exception from HRESULT: 0x8007007E)]&lt;BR&gt;System.Reflection.Assembly.nLoad(AssemblyName fileName, String codeBase, Evidence assemblySecurity, Assembly locationHint, StackCrawlMark&amp;amp; stackMark, Boolean throwOnFileNotFound, Boolean forIntrospection) +0&lt;BR&gt;System.Reflection.Assembly.InternalLoad(AssemblyName assemblyRef, Evidence assemblySecurity, StackCrawlMark&amp;amp; stackMark, Boolean forIntrospection) +211&lt;BR&gt;System.Reflection.Assembly.InternalLoad(String assemblyString, Evidence assemblySecurity, StackCrawlMark&amp;amp; stackMark, Boolean forIntrospection) +141&lt;BR&gt;System.Reflection.Assembly.Load(String assemblyString) +25&lt;BR&gt;System.Web.Configuration.CompilationSection.LoadAssemblyHelper(String assemblyName, Boolean starDirective) +32&lt;/P&gt;
&lt;P&gt;[ConfigurationErrorsException: The specified module could not be found. (Exception from HRESULT: 0x8007007E)]&lt;BR&gt;System.Web.Configuration.CompilationSection.LoadAssemblyHelper(String assemblyName, Boolean starDirective) +596&lt;BR&gt;System.Web.Configuration.CompilationSection.LoadAllAssembliesFromAppDomainBinDirectory() +3591161&lt;BR&gt;System.Web.Configuration.CompilationSection.LoadAssembly(AssemblyInfo ai) +46&lt;BR&gt;System.Web.Compilation.BuildManager.GetReferencedAssemblies(CompilationSection compConfig) +177&lt;BR&gt;System.Web.Compilation.BuildProvidersCompiler..ctor(VirtualPath configPath, Boolean supportLocalization, String outputAssemblyName) +180&lt;BR&gt;System.Web.Compilation.ApplicationBuildProvider.GetGlobalAsaxBuildResult(Boolean isPrecompiledApp) +3558605&lt;BR&gt;System.Web.Compilation.BuildManager.CompileGlobalAsax() +51&lt;BR&gt;System.Web.Compilation.BuildManager.EnsureTopLevelFilesCompiled() +462&lt;/P&gt;
&lt;P&gt;[HttpException (0x80004005): The specified module could not be found. (Exception from HRESULT: 0x8007007E)]&lt;BR&gt;System.Web.Compilation.BuildManager.ReportTopLevelCompilationException() +57&lt;BR&gt;System.Web.Compilation.BuildManager.EnsureTopLevelFilesCompiled() +612&lt;BR&gt;System.Web.Hosting.HostingEnvironment.Initialize(ApplicationManager appManager, IApplicationHost appHost, IConfigMapPathFactory configMapPathFactory, HostingEnvironmentParameters hostingParameters) +642&lt;/P&gt;
&lt;P&gt;[HttpException (0x80004005): The specified module could not be found. (Exception from HRESULT: 0x8007007E)]&lt;BR&gt;System.Web.HttpRuntime.FirstRequestInit(HttpContext context) +3539851&lt;BR&gt;System.Web.HttpRuntime.EnsureFirstRequestInit(HttpContext context) +69&lt;BR&gt;System.Web.HttpRuntime.ProcessRequestInternal(HttpWorkerRequest wr) +252&lt;/P&gt;
&lt;P mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;The core cause to this problem is in the way the operating system loads native DLL's at runtime. Native DLL's are loaded using the following logic which does not include the Temporary ASP.net Files nor the applications /bin folder. This problem will also occur in any .Net application if the Native DLL is not included in the /bin folder with the .EXE file or if the DLL is not in the Path Environment Variable.&lt;BR&gt;&amp;nbsp;&lt;/P&gt;
&lt;OL&gt;
&lt;LI&gt;The directory from which the application loaded.&amp;nbsp; In the case of ASP.Net, this will resolve to %windir%\Microsoft.Net\Framework\v###\ or %windir%\system32\inetsrv for IIS 6.&amp;nbsp;&amp;nbsp;&lt;/LI&gt;
&lt;LI&gt;The current directory.&amp;nbsp; In the case of ASP.Net, this will resolve to %windir%\System32\inetsrv for IIS 6.&amp;nbsp; If using the built-in web server, this resolves to a path under C:\Program Files\Microsoft Visual Studio 8.&lt;/LI&gt;
&lt;LI&gt;The Windows system directory.&amp;nbsp; Use the GetSystemDirectory function to get the path of this directory.&amp;nbsp;&lt;/LI&gt;
&lt;LI&gt;The Windows directory. Use the GetWindowsDirectory function to get the path of this directory.&amp;nbsp;&lt;/LI&gt;
&lt;LI&gt;The directories that are listed in the PATH environment variable. &lt;/LI&gt;&lt;/OL&gt;
&lt;P&gt;&lt;BR&gt;============&lt;BR&gt;The options:&lt;BR&gt;============&lt;/P&gt;
&lt;OL&gt;
&lt;LI&gt;Use DLLImport to load the dll using a relative or absolute path at runtime.&lt;/LI&gt;
&lt;LI&gt;Set the PATH Environment Variable so the ASP.Net process can locate the C++ DLL.&amp;nbsp; You can set this property at runtime so that it only affects the process running your code.&amp;nbsp; You can also set this globally in the System Properties (Environment Variables | PATH property). Setting this programmatically does not require a reboot and you can point the PATH to the /bin folder of the web app if you want to be able to do XCopy deployments of your ASP.Net application.&amp;nbsp; Here are the steps to set the Path programmatically from ASP.Net.&lt;/LI&gt;&lt;/OL&gt;
&lt;P&gt;&amp;nbsp;Option 2.a - If you want your Native C++ DLL’s loaded from the /bin of the ASP.Net application.&amp;nbsp; &lt;/P&gt;
&lt;OL&gt;
&lt;LI&gt;Native C++ DLL project&lt;/LI&gt;
&lt;OL&gt;
&lt;LI&gt;Use al.exe to build a NativeWrapper for the Native C++ DLL.&amp;nbsp; This allows you to bring the Native C++ DLL along with the DLL that is referencing it.&amp;nbsp; You can add this in the Post Build Script of the Native C++ DLL Project to automate this.&lt;BR&gt;&lt;BR&gt;al.exe /link:"$(TargetPath)" /out:"$(TargetDir)$(TargetName).NW.dll" /platform:x86&lt;BR&gt;&lt;/LI&gt;
&lt;LI&gt;Managed C++ DLL Project&lt;/LI&gt;
&lt;OL&gt;
&lt;LI&gt;Reference the NativeWrapper DLL - when you build this project, the native wrapper and Native C++ DLL files are copied to the output directory along with the managed C++ DLL&lt;BR&gt;&lt;/LI&gt;
&lt;LI&gt;Set Delay Load DLLs to the Native DLL.&amp;nbsp; (C++ Project Properties, Expand Linker, select Input, Delay Loaded DLLs) - This prevents the Native DLL from loading when the process starts, giving you a chance to set the PATH Environment variable.&amp;nbsp; If you don’t set this property, moci.net and its dependencies (i.e. the Native DLL) will be loaded before any of your ASP.Net code can run and this will fail unless you have set the PATH environment variable on the machine level.&lt;BR&gt;&lt;/LI&gt;&lt;/OL&gt;
&lt;LI&gt;ASP.Net Project&lt;/LI&gt;
&lt;OL&gt;
&lt;LI&gt;Reference the managed C++ DLL - The managed C++ DLL, Native C++ DLL, and NativeWrapper DLL are moved into the applications /bin folder.&lt;BR&gt;&lt;/LI&gt;
&lt;LI&gt;Add a Global.asax with the following code.&amp;nbsp; (Right-click the Web Application, select Add, New Item, select Global Application Class).&amp;nbsp; You could also use an HTTPModule compiled into a DLL if you don’t want people to be able to change your code.&amp;nbsp; Application_Start runs one time when the application loads and this code will set the PATH environment variable for the process to include the /bin directory of the application.&lt;BR&gt;&lt;BR&gt;protected void Application_Start(object sender, EventArgs e){&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;String _path = String.Concat(System.Environment.GetEnvironmentVariable("PATH"), ";", System.AppDomain.CurrentDomain.RelativeSearchPath);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;System.Environment.SetEnvironmentVariable("PATH", _path, EnvironmentVariableTarget.Process);&lt;BR&gt;}&lt;/LI&gt;&lt;/OL&gt;&lt;/OL&gt;&lt;/OL&gt;
&lt;P&gt;&amp;nbsp;Option 2.b - If you want your Native C++ DLLs to load from an installation path outside of the web site you can avoid the AL command.&amp;nbsp; You would still need to set the Delay Load property on any Managed C++ DLL that loads the Native C++ DLL’s as well as set the Environment Variable.&amp;nbsp; If you choose to go this route, you can load the path to your Native C++ DLL’s dynamically from the web.config file at runtime:&lt;/P&gt;
&lt;OL&gt;
&lt;LI&gt;Native C++ DLL Project - don’t need to do anything in the Post Build Script&lt;BR&gt;&lt;/LI&gt;
&lt;LI&gt;Managed C++ DLL Project&lt;/LI&gt;
&lt;OL&gt;
&lt;LI&gt;Configure Delay Load DLL’s and specify the Native C++ DLL&lt;BR&gt;&lt;/LI&gt;&lt;/OL&gt;
&lt;LI&gt;ASP.Net Project&lt;/LI&gt;
&lt;OL&gt;
&lt;LI&gt;Reference the Managed C++ DLL - only Managed C++ DLL is in the /bin&lt;BR&gt;&lt;/LI&gt;
&lt;LI&gt;In web.config, add the following…use a path where the Native C++ DLL is located:&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;appSettings&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;add key="NativePath" value="C:\MyNativeDLLs"/&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;/appSettings&amp;gt;&lt;BR&gt;&lt;/LI&gt;
&lt;LI&gt;In global.asax, add the following:&lt;BR&gt;&lt;BR&gt;protected void Application_Start(object sender, EventArgs e){&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;String _path = String.Concat(System.Environment.GetEnvironmentVariable("PATH"), ";", ConfigurationSettings.AppSettings["NativePath"]);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;System.Environment.SetEnvironmentVariable("PATH", _path, EnvironmentVariableTarget.Process);&lt;BR&gt;}&lt;/LI&gt;&lt;/OL&gt;&lt;/OL&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=4675691" width="1" height="1"&gt;</content><author><name>Jorman</name><uri>http://blogs.msdn.com/members/Jorman.aspx</uri></author></entry><entry><title>Referencing .js files for the AJAX Control Toolkit</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/jorman/archive/2007/05/18/referencing-js-files-for-the-ajax-control-toolkit.aspx" /><id>http://blogs.msdn.com/jorman/archive/2007/05/18/referencing-js-files-for-the-ajax-control-toolkit.aspx</id><published>2007-05-19T00:02:00Z</published><updated>2007-05-19T00:02:00Z</updated><content type="html">&lt;P&gt;I was recently working with someone that was leveraging the AJAX Extension and the Control Toolkit and they were running into an issue where a customer's environment was causing issues making requests to ScriptResource.axd.&amp;nbsp; Since they couldn't change the environment, they needed to reference the .js files directly.&amp;nbsp; Here's a rundown of the steps in case anyone needs to do this in the future:&lt;/P&gt;
&lt;P&gt;1. Create a folder to hold the .js files in your site.&amp;nbsp; In my case I created a "Scripts" folder on the root of my app.&lt;/P&gt;
&lt;P&gt;2. Create the following folder structure under the folder from Step 1.&amp;nbsp; The folder that is a version number should match the version of the control toolkit.&amp;nbsp; This can be found on the &lt;A class="" title="AJAX Control Toolkit Releases Page" href="http://www.codeplex.com/AtlasControlToolkit/Release/ProjectReleases.aspx?ReleaseId=1425" mce_href="  http://www.codeplex.com/AtlasControlToolkit/Release/ProjectReleases.aspx?ReleaseId=1425"&gt;Releases page&lt;/A&gt; for the extension.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; - &amp;lt;Root&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; - Scripts&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; - AjaxControlToolkit&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; - 1.0.10301.0&lt;/P&gt;
&lt;P&gt;3. Open the Control Toolkit project and build the solution.&amp;nbsp; This should generate the \obj folder that contains all the .js files.&lt;/P&gt;
&lt;P&gt;4. Copy the Script files for the toolkit project to the site&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; From:&amp;nbsp; &amp;lt;path_to_unzipped_toolkit&amp;gt;\AjaxControlToolkit\obj\Debug&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; To:&amp;nbsp;&amp;nbsp;&amp;nbsp; 1.0.10301.0 folder from above&lt;/P&gt;
&lt;P&gt;5. Copy the Script files for the AJAX Extension:&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; From:&amp;nbsp; Copy the System.Web.Extensions folder and all it's contents from C:\Program Files (x86)\Microsoft ASP.NET\ASP.NET 2.0 AJAX Extensions\v1.0.61025\MicrosoftAjaxLibrary&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; To:&amp;nbsp;&amp;nbsp;&amp;nbsp; ~/Script folder.&amp;nbsp; You should have a folder structure similar to:&lt;/P&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; - &amp;lt;Root&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; - Scripts&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; -&amp;nbsp;System.Web.Extensions&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; - 1.0.61025.0&lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;6. Set the ScriptPath on the &amp;lt;scriptManager&amp;gt; to "~/Scripts"&lt;/P&gt;
&lt;P&gt;7. Make sure the controls are not explicitly setting ScriptPath as that will override the ScriptManager property.&lt;/P&gt;
&lt;P&gt;Now when you browse the page, the .js files will be loaded from the ~/Scripts folder instead of via calls to ScriptResource.axd.&amp;nbsp; If you're getting script errors, take a netmon and ensure all the requests to the .js files are returning a status code of 200 or 304.&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=2718290" width="1" height="1"&gt;</content><author><name>Jorman</name><uri>http://blogs.msdn.com/members/Jorman.aspx</uri></author><category term="ASP.Net" scheme="http://blogs.msdn.com/jorman/archive/tags/ASP.Net/default.aspx" /></entry><entry><title>JavaScript errors occur...only when the script is in a .js file</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/jorman/archive/2007/04/13/javascript-errors-occur-only-when-the-script-is-in-a-js-file.aspx" /><id>http://blogs.msdn.com/jorman/archive/2007/04/13/javascript-errors-occur-only-when-the-script-is-in-a-js-file.aspx</id><published>2007-04-13T22:13:00Z</published><updated>2007-04-13T22:13:00Z</updated><content type="html">&lt;P&gt;This was tricky to track down and hopefully the troubleshooting information will help you should you run into this type of error and can't track it down.&amp;nbsp; &lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;Symptom&lt;/STRONG&gt;&lt;BR&gt;When browsing a web application you receive the following JavaScript errors.&lt;/P&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;&lt;STRONG&gt;JavaScript errors:&lt;BR&gt;&lt;/STRONG&gt;&lt;BR&gt;Error 1:&lt;BR&gt;Syntax Error&lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;&amp;nbsp;Error 2:&lt;BR&gt;&amp;nbsp;Object expected&lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;If using 3rd party ASP.Net controls, you may see errors similar to the following:&lt;/P&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;&lt;STRONG&gt;ASP.Net Error related to 3rd party control&lt;/STRONG&gt;&lt;BR&gt;Unable to find script library '/aspnet_client/basicframe_webcontrols_basicdatepicker/1_1_1959/bdplite.js'. Try placing this file manually by uploading the /aspnet_client directory to your web application root.&lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;Typically the aspnet_client directory can be found at the following path:&lt;BR&gt;C:\inetpub\wwwroot\aspnet_client&lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;&lt;BR&gt;Looking at the IIS logs will show that requests to these pages are serving correctly with a 304 or 200 response. Investigation of the .js file in the IE cache or network trace response will show you that there is additional text at the end of the .js files. For example, you have a .js file with the following:&lt;/P&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;function AlertMe()&lt;BR&gt;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;alert('The JS File loaded');&lt;BR&gt;}&lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;However, in the netmon or IE cache, you see the following:&lt;/P&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;function AlertMe()&lt;BR&gt;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;alert('The JS File loaded');&lt;BR&gt;}&lt;STRONG&gt;&lt;EM&gt;&amp;lt;div&amp;gt;Confidential Information&amp;lt;/div&amp;gt;&lt;/EM&gt;&lt;/STRONG&gt;&lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;The extra information results in Internet Explorer throwing the JavaScript errors. BTW, the error doesn't occur in Firefox as it seems to be more tolerant of the invalid script.&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;Troubleshooting Steps&lt;/STRONG&gt;&lt;BR&gt;Check the IE cache to see if there is extra data appended to the .js file.&lt;/P&gt;
&lt;OL&gt;
&lt;LI&gt;Tools | Internet Options in IE&lt;/LI&gt;
&lt;LI&gt;General Tab | Settings button under Browsing History&lt;/LI&gt;
&lt;LI&gt;Click View Files&lt;/LI&gt;
&lt;LI&gt;Sort by Internet Address and find the URL to your site&lt;/LI&gt;
&lt;LI&gt;Do you see the .js file being requested? If so, open it in notepad and look for extra text at the end or any characters not in the original file on the server.&lt;/LI&gt;&lt;/OL&gt;
&lt;P&gt;You can also use a tool that captures the network data (Netmon 3, Ethereal, Fiddler, Web Development Helper, HttpWatch, Firebug, etc).&amp;nbsp; However, if IE is caching the page, you will see a request with the If-Modified-Since header coming from the client and the server will return a response with a 304 status code which will not contain the script.&amp;nbsp; The If-Modified-Since header indicates the browser has the file in cache, and is asking the server if it has a newer copy.&amp;nbsp; In order to avoid this behavior, you can force IE to always request the actual page instead of using cache.&amp;nbsp; This way you can see the 200 response coming from the server with the contents of the .js file to see if anything extra is added to your script.&lt;/P&gt;
&lt;OL&gt;
&lt;LI&gt;Open IE&lt;/LI&gt;
&lt;LI&gt;From Tools menu, select Internet Options&lt;/LI&gt;
&lt;LI&gt;Click Settings under Browsing History (IE7)&lt;/LI&gt;
&lt;LI&gt;Click Every Time I Visit the Web Page, click OK&lt;/LI&gt;
&lt;LI&gt;Use network capture tool and browse the page.&lt;/LI&gt;&lt;/OL&gt;
&lt;P&gt;&lt;STRONG&gt;Cause&lt;/STRONG&gt;&lt;BR&gt;In this particular scenario, the "Enable document footer" option in IIS was enabled on the folders serving the .js files. This option appends text to the end of any static documents served:&lt;/P&gt;
&lt;OL&gt;
&lt;LI&gt;Open IIS Manager&lt;/LI&gt;
&lt;LI&gt;Right-click the folder hosting the test pages, select Properties&amp;nbsp;&lt;/LI&gt;
&lt;LI&gt;Click the Documents tab&amp;nbsp;&lt;/LI&gt;
&lt;LI&gt;Uncheck "Enable document footer".&amp;nbsp;&lt;/LI&gt;&lt;/OL&gt;
&lt;P&gt;Anything in the pipeline could potentially cause this.&amp;nbsp; Isapi filters, proxy servers, HttpModules/handlers(if .js is mapped to aspnet_isapi.dll), etc.&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=2118791" width="1" height="1"&gt;</content><author><name>Jorman</name><uri>http://blogs.msdn.com/members/Jorman.aspx</uri></author></entry><entry><title>Fix: Random FileNotFoundException in ASP.Net 2.0 application</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/jorman/archive/2007/03/26/fix-random-filenotfoundexception-in-asp-net-2-0-application.aspx" /><id>http://blogs.msdn.com/jorman/archive/2007/03/26/fix-random-filenotfoundexception-in-asp-net-2-0-application.aspx</id><published>2007-03-26T18:17:00Z</published><updated>2007-03-26T18:17:00Z</updated><content type="html">&lt;P&gt;&lt;STRONG&gt;Issue&amp;nbsp;&lt;/STRONG&gt; -&amp;nbsp; Random FileNotFoundException when browsing ASP.Net 2.0 application.&amp;nbsp; An event similar to the following will be logged in the event viewer.&amp;nbsp; The file name in the exception is typically different every time:&lt;/P&gt;
&lt;P&gt;Exception message: Could not load file or assembly 'App_Web_-a8debde, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null' or one of its dependencies. The system cannot find the file specified. &lt;BR&gt;&lt;BR&gt;&amp;nbsp; Stack trace:&amp;nbsp;&amp;nbsp;&amp;nbsp; at ASP.UserControl_ascx.__BuildControlmain()&lt;BR&gt;&amp;nbsp;&amp;nbsp; at ASP.UserControl_ascx.__BuildControlTree(dynamic_default_ascx __ctrl)&lt;BR&gt;&amp;nbsp;&amp;nbsp; at ASP.UserControl_ascx.FrameworkInitialize()&lt;BR&gt;&amp;nbsp;&amp;nbsp; at System.Web.UI.UserControl.InitializeAsUserControlInternal()&lt;BR&gt;&amp;nbsp;&amp;nbsp; at System.Web.UI.UserControl.InitializeAsUserControl(Page page)&lt;BR&gt;&amp;nbsp;&amp;nbsp; at ASP.default_aspx.__BuildControlhtml_content()&lt;BR&gt;&amp;nbsp;&amp;nbsp; at ASP.default_aspx.__BuildControlTree(default_aspx __ctrl)&lt;BR&gt;&amp;nbsp;&amp;nbsp; at ASP.default_aspx.FrameworkInitialize()&lt;BR&gt;&amp;nbsp;&amp;nbsp; at System.Web.UI.Page.ProcessRequest(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint)&lt;BR&gt;&amp;nbsp;&amp;nbsp; at System.Web.UI.Page.ProcessRequest()&lt;BR&gt;&amp;nbsp;&amp;nbsp; at System.Web.UI.Page.ProcessRequestWithNoAssert(HttpContext context)&lt;BR&gt;&amp;nbsp;&amp;nbsp; at System.Web.UI.Page.ProcessRequest(HttpContext context)&lt;BR&gt;&amp;nbsp;&amp;nbsp; at ASP.default_aspx.ProcessRequest(HttpContext context)&lt;BR&gt;&amp;nbsp;&amp;nbsp; at System.Web.HttpApplication.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute()&lt;BR&gt;&amp;nbsp;&amp;nbsp; at System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean&amp;amp; completedSynchronously)&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;Workarounds&lt;/STRONG&gt;&amp;nbsp; -&amp;nbsp; In some cases, it's necessary to clear the Temporary ASP.Net Files folder and restart the application pool.&amp;nbsp; We've found in some cases that setting batch="false" in the web.config file will resolve the issue as well, however, there are some perf reasons for not doing that long term&amp;nbsp;in production.&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;Getting the Fix&amp;nbsp; &lt;/STRONG&gt;-&amp;nbsp; The KB for this fix is not yet public (I'll link it as soon as it is), however, the fix is available.&amp;nbsp; You will need to contact Microsoft Support (&lt;A href="http://support.microsoft.com/"&gt;http://support.microsoft.com/&lt;/A&gt;) and ask for the fix from KB article 934839.&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=1952824" width="1" height="1"&gt;</content><author><name>Jorman</name><uri>http://blogs.msdn.com/members/Jorman.aspx</uri></author><category term="ASP.Net" scheme="http://blogs.msdn.com/jorman/archive/tags/ASP.Net/default.aspx" /></entry><entry><title>Getting real-time updates from remote process using the AJAX Extension</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/jorman/archive/2007/03/08/getting-real-time-updates-from-remote-process-using-the-ajax-extension.aspx" /><link rel="enclosure" type="application/x-zip-compressed" length="24198" href="http://blogs.msdn.com/jorman/attachment/1840403.ashx" /><id>http://blogs.msdn.com/jorman/archive/2007/03/08/getting-real-time-updates-from-remote-process-using-the-ajax-extension.aspx</id><published>2007-03-09T01:06:00Z</published><updated>2007-03-09T01:06:00Z</updated><content type="html">&lt;P&gt;This sample was a result of an idea from Kent Post at Akamai.&amp;nbsp; He was wanting to be able to launch a process on a remote server and get real-time updates in the browser.&amp;nbsp; In this case, we focused on running &lt;A class="" title="Windows Automated Installation Kit (WAIK)" href="http://www.microsoft.com/downloads/details.aspx?familyid=993c567d-f12c-4676-917f-05d9de73ada4&amp;amp;displaylang=en" target=_blank mce_href="http://www.microsoft.com/downloads/details.aspx?familyid=993c567d-f12c-4676-917f-05d9de73ada4&amp;amp;displaylang=en"&gt;WinPE&lt;/A&gt; scripts to build ISO's on the server.&amp;nbsp; The WinPE scripts&amp;nbsp;can take a long time to process, and&amp;nbsp;the goal is to launch the process and see what was going on without having to be logged into the server console using the browser.&amp;nbsp; The attached sample provides a way to perform these actions by using &lt;A class="" title="System.Diagnostics.Process class information on MSDN" href="http://msdn2.microsoft.com/en-us/library/system.diagnostics.process(VS.80).aspx" target=_blank mce_href="http://msdn2.microsoft.com/en-us/library/system.diagnostics.process(VS.80).aspx"&gt;System.Diagnostics&lt;/A&gt; to launch the process and the &lt;A class="" title="AJAX Extension web site" href="http://ajax.asp.net/" target=_blank mce_href="http://ajax.asp.net"&gt;AJAX Extension&lt;/A&gt; to get updates.&amp;nbsp; Before getting into the sample, let's look at some of the complications of doing this type of work.&lt;/P&gt;
&lt;OL&gt;
&lt;LI&gt;&lt;STRONG&gt;Permissions on the server&lt;/STRONG&gt; - By default, the application pool running ASP.Net cannot run other processes on the server.&amp;nbsp; The process by default runs as Network Service which typically won't have Read access to the .bat, .cmd, .exe you're trying to run.&amp;nbsp; If you're writing files, it won't have access to write to directories either.&lt;/LI&gt;
&lt;LI&gt;&lt;STRONG&gt;Getting the data back to the client&lt;/STRONG&gt; - Once you launch the process, how do you get the data down to a remote browser?&amp;nbsp; HTTP is a disconnected protocol, so once you spin up the process, you need some way of making additional requests and getting the output.&amp;nbsp;&lt;/LI&gt;
&lt;LI&gt;&lt;STRONG&gt;Application can not be interactive&lt;/STRONG&gt; - Making sure the application you're running does not have an interface that requires interaction.&amp;nbsp; Keep in mind you are launching a child process from a non-interactive service and there is no way for a remote or local user to actually interact with the program.&amp;nbsp; Batch files are good for this scenario.&lt;/LI&gt;&lt;/OL&gt;
&lt;P&gt;The first obstacle is relatively easy to overcome.&amp;nbsp;&amp;nbsp;For&amp;nbsp;the demo, you can use a file based web site in Visual Studio 2005 and the built in web server.&amp;nbsp; In this&amp;nbsp;scenario, the web server and code run as&amp;nbsp;the account you are logged into the box&amp;nbsp;with and assuming this account&amp;nbsp;has&amp;nbsp;appropriate permissions to launch the program and write to any area that the program writes to, the app will work fine.&amp;nbsp; From a server perspective, we ran the Application Pool as Local System.&amp;nbsp; You can setup IIS with a new application pool running under local system and assign the application pool to the specific application to ensure other code is not running with elevated privileges.&amp;nbsp; Another option is to use PInvoke and call CreateProcessAsUser and explicitly set desktop permissions for the application pool account you're using.&amp;nbsp; This is a bit more complicated and won't be covered here.&amp;nbsp; If you're interested in looking into that approach for launching processes, check out Q165194&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&lt;A class="" title=#h1 name=#h1&gt;&lt;/A&gt;165194 - INFO: CreateProcessAsUser() Windowstations and Desktops&lt;BR&gt;&lt;A href="http://support.microsoft.com/support/kb/articles/Q165/1/94.asp" mce_href="http://support.microsoft.com/support/kb/articles/Q165/1/94.asp"&gt;http://support.microsoft.com/support/kb/articles/Q165/1/94.asp&lt;/A&gt;&lt;/P&gt;
&lt;P&gt;The second problem of getting the output has a couple of options. One way to go is to pipe the output from the program to a text file and then redirect the browser to&amp;nbsp;the textfile.&amp;nbsp; If you haven't done this before, the following pipes the output of the dir command to the file c:\output.log:&amp;nbsp; &lt;STRONG&gt;dir &amp;gt;c:\ouptut.log&lt;/STRONG&gt;&amp;nbsp; This gets you the output after the application has completed execution.&amp;nbsp; However, in order to get the data as it's occurring, you have to make multiple requests to the server and access the StandardOutput stream directly.&amp;nbsp; In this sample, we use the &lt;A class="" title="Web Services with AJAX Tutorial" href="http://ajax.asp.net/docs/tutorials/ConsumingWebServicesWithAJAXTutorial.aspx" target=_blank mce_href="http://ajax.asp.net/docs/tutorials/ConsumingWebServicesWithAJAXTutorial.aspx"&gt;AJAX Extension&lt;/A&gt;, the &lt;A class="" title="setInterval documentation on MSDN" href="http://msdn.microsoft.com/library/default.asp?url=/workshop/author/dhtml/reference/methods/setinterval.asp" target=_blank mce_href="http://msdn.microsoft.com/library/default.asp?url=/workshop/author/dhtml/reference/methods/setinterval.asp"&gt;setInterval&lt;/A&gt; method in JavaScript, the &lt;A class="" title="System.Diagnostics.Process information on MSDN" href="http://msdn2.microsoft.com/en-us/library/system.diagnostics.process(VS.80).aspx" target=_blank mce_href="http://msdn2.microsoft.com/en-us/library/system.diagnostics.process(VS.80).aspx"&gt;System.Diagnostics.Process&lt;/A&gt; class, and a custom class that's cached on the server to handle this scenario.&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;&lt;U&gt;Overview of the sample&lt;/U&gt;&lt;/STRONG&gt;&amp;nbsp;&lt;BR&gt;The attached files provide all the source to run the sample.&amp;nbsp; Here's a rundown of what the app does and&amp;nbsp;what is in the&amp;nbsp;.zip files.&lt;/P&gt;
&lt;OL&gt;
&lt;LI&gt;User browses Default.aspx - If the user&amp;nbsp;does not have a cookie called MyGUID, one is created for them.&amp;nbsp; The cookie value is used to uniquely identify the requests when making web service calls and for caching.&lt;/LI&gt;
&lt;LI&gt;User clicks the Launch button&lt;/LI&gt;
&lt;OL&gt;
&lt;LI&gt;JavaScript posts to the LaunchProcess method of the ProcessLauncher.asmx web service using the &lt;A class="" title="Web Services with AJAX Tutorial" href="http://ajax.asp.net/docs/tutorials/ConsumingWebServicesWithAJAXTutorial.aspx" mce_href="http://ajax.asp.net/docs/tutorials/ConsumingWebServicesWithAJAXTutorial.aspx"&gt;AJAX Extension&amp;nbsp;&lt;/A&gt;&amp;nbsp;&lt;/LI&gt;
&lt;LI&gt;LaunchProcess method does the following:&lt;/LI&gt;
&lt;OL&gt;
&lt;LI&gt;Creates an instance of the ProgramWatcher class&lt;/LI&gt;
&lt;LI&gt;Calls the Execute method of ProgramWatcher&lt;/LI&gt;
&lt;OL&gt;
&lt;LI&gt;Execute method launches a &lt;A class="" title="System.Thread.ThreadPool class information on MSDN" href="http://msdn2.microsoft.com/en-us/system.threading.threadpool.aspx" target=_blank mce_href="http://msdn2.microsoft.com/en-us/system.threading.threadpool.aspx"&gt;ThreadPool&lt;/A&gt; thread&lt;/LI&gt;
&lt;LI&gt;Runs the ReadLog.exe program&lt;/LI&gt;
&lt;LI&gt;Redirects the &lt;A class="" title="StandardOutput property information" href="http://msdn2.microsoft.com/en-us/system.diagnostics.process.standardoutput.aspx" target=_blank mce_href="http://msdn2.microsoft.com/en-us/system.diagnostics.process.standardoutput.aspx"&gt;StandardOutput&lt;/A&gt; of the ReadLog.exe program to a Stream property of the ProgramWatcher instance&lt;/LI&gt;&lt;/OL&gt;
&lt;LI&gt;The ProgramWatcher instance is &lt;A class="" title="ASP.Net caching on MSDN" href="http://msdn2.microsoft.com/en-us/aa478965.aspx" target=_blank mce_href="http://msdn2.microsoft.com/en-us/aa478965.aspx"&gt;cached&lt;/A&gt; using the MyGUID cookie value from Step 1&lt;/LI&gt;&lt;/OL&gt;&lt;/OL&gt;
&lt;LI&gt;When the Async call returns,&amp;nbsp;a timer kicks off that runs the GetStatus JavaScript method after 750 milliseconds.&lt;/LI&gt;
&lt;LI&gt;GetStatus JavaScript method runs&lt;/LI&gt;
&lt;OL&gt;
&lt;LI&gt;&lt;A class="" title="clearInterval documentation on MSDN" href="http://msdn.microsoft.com/workshop/author/dhtml/reference/methods/clearinterval.asp" target=_blank mce_href="http://msdn.microsoft.com/workshop/author/dhtml/reference/methods/clearinterval.asp"&gt;Timer is stopped&lt;/A&gt; to prevent async callbacks from getting out of sync.&amp;nbsp; i.e. IE can make 2 calls per server, this prevents 2 requests leaving the client and the 2nd request returning before the first request and messing up the output.&lt;/LI&gt;
&lt;LI&gt;GetStatus method of the ProcessLauncher webservice is called&lt;/LI&gt;
&lt;OL&gt;
&lt;LI&gt;GetStatus loads the ProgramWatcher method out of cache using the MyGUID cookie value&lt;/LI&gt;
&lt;LI&gt;Calls the ReadOutput method of the ProgramWatcher instance passing it how many bytes to read from the Stream property on ProgramWatcher - in this sample 50 bytes at a time.&lt;/LI&gt;
&lt;LI&gt;Returns the bytes returned from ReadOutput&lt;/LI&gt;&lt;/OL&gt;&lt;/OL&gt;
&lt;LI&gt;Client parses the response and handles output that contains \r vs. \r\n.&amp;nbsp; See the Issues section below for why this is important.&lt;/LI&gt;
&lt;LI&gt;&amp;nbsp;Timer started again and Steps 4 -&amp;nbsp;5 occur again until the GetStatus method returns Null&lt;/LI&gt;&lt;/OL&gt;
&lt;P&gt;&lt;STRONG&gt;&lt;U&gt;Included Files&lt;BR&gt;&lt;/U&gt;&lt;/STRONG&gt;Here's a list of the files included in the .zip files with a summary of what they do.&amp;nbsp; The code is commented thoroughly.&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;&amp;nbsp;AjaxBatchProcess.zip&lt;/LI&gt;
&lt;UL&gt;
&lt;LI&gt;App_Code&lt;/LI&gt;
&lt;UL&gt;
&lt;LI&gt;ProgramWatcher.cs - This class is what drives the process on the server side.&amp;nbsp; It contains an Execute method that launches&amp;nbsp;a program via System.Diagnostics.Process and redirects the StandardOutput to a property on the class.&amp;nbsp; The class is cached so that the browser can get the output from the process in chunks.&lt;/LI&gt;
&lt;LI&gt;ProcessLauncher.cs - Web Service methods that allow the AJAX Extension to generate &lt;A class="" title="AJAX calling Web Service Info" href="http://ajax.asp.net/docs/tutorials/ConsumingWebServicesWithAJAXTutorial.aspx" target=_blank mce_href="http://ajax.asp.net/docs/tutorials/ConsumingWebServicesWithAJAXTutorial.aspx"&gt;JavaScript proxy classes&lt;/A&gt; that are used to launch the process on the web server and also get the output in chunks.&lt;/LI&gt;&lt;/UL&gt;
&lt;LI&gt;AjaxBatchProcess.js - JavaScript file that calls the webservice methods and also handles getting and parsing&amp;nbsp;the output.&lt;/LI&gt;
&lt;LI&gt;Default.aspx - Page requested by an end user.&amp;nbsp; Has a &lt;A class="" title="ScriptManager documentation on ajax.asp.net" href="http://ajax.asp.net/docs/mref/T_System_Web_UI_ScriptManager.aspx" target=_blank mce_href="http://ajax.asp.net/docs/mref/T_System_Web_UI_ScriptManager.aspx"&gt;ScriptManager &lt;/A&gt;that hooks up AjaxBatchProcess.js and ProcessLauncher.asmx&lt;/LI&gt;
&lt;LI&gt;ProcessLauncher.asmx - Web Service requested by the client.&lt;/LI&gt;
&lt;LI&gt;Web.config - Web.config from the AJAX Extension project&lt;/LI&gt;&lt;/UL&gt;
&lt;LI&gt;ReadLog.zip&lt;/LI&gt;
&lt;UL&gt;
&lt;LI&gt;ReadLog.exe - Command-line program that reads the build_pe_out.txt file and pushes the output to the console.&lt;/LI&gt;
&lt;LI&gt;build_pe_out.txt - Output from WinPE commands.&lt;/LI&gt;&lt;/UL&gt;
&lt;LI&gt;ReadLog-Source.zip&lt;/LI&gt;
&lt;UL&gt;
&lt;LI&gt;Program.cs - source for the ReadLog program.&amp;nbsp; This program reads in a file passed in as an argument and pushes the text to the console.&lt;/LI&gt;
&lt;LI&gt;Default C# console project files &lt;/LI&gt;&lt;/UL&gt;&lt;/UL&gt;
&lt;P&gt;Here are the steps to use the files attached to the blog:&lt;/P&gt;
&lt;OL&gt;
&lt;LI&gt;Unzip AjaxBatchProcess.zip to a folder in your file system.&lt;/LI&gt;
&lt;LI&gt;Unzip ReadLog.zip to c:\ReadLog&lt;/LI&gt;
&lt;LI&gt;Open Visual Studio 2005&lt;/LI&gt;
&lt;LI&gt;From the File menu | Select Open Web Site&lt;/LI&gt;
&lt;LI&gt;Select the path from Step 1 (the folder that contains app_code, default.aspx, etc. from the .zip file)&lt;/LI&gt;
&lt;LI&gt;Right-click Default.aspx, select View in Browser&lt;/LI&gt;
&lt;LI&gt;Click the Launch button&lt;/LI&gt;&lt;/OL&gt;
&lt;P&gt;&lt;STRONG&gt;&lt;U&gt;Issues&lt;/U&gt;&lt;BR&gt;&lt;/STRONG&gt;I wanted to highlight a few areas and why we chose to go that route.&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;Caching the ProgramWatcher and the Stream property&lt;/STRONG&gt;&lt;/P&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;This is an important part of the application and is the piece that allows access to the output from the application in real-time.&amp;nbsp; In this case you have a program that is redirecting the StandardOutput to a Stream.&amp;nbsp; This is essentially writing bytes into memory with a pointer at the end.&amp;nbsp; &lt;/P&gt;
&lt;P&gt;&lt;EM&gt;These are bytes&lt;/EM&gt;&amp;lt;StandardOutput Pointer&amp;gt;&lt;/P&gt;
&lt;P&gt;The ProgramWatcher class sets the StandardOutput stream to a property called Stream.&amp;nbsp; This gives you another pointer to the same bytes that starts at the beginning.&amp;nbsp; &lt;/P&gt;
&lt;P&gt;&amp;lt;ProgramWatcher.Stream pointer&amp;gt;&lt;EM&gt;These are&amp;nbsp;bytes&lt;/EM&gt;&amp;lt;StandardOutput Pointer&amp;gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;With this setup, you have the System.Diagnostics.Process adding bytes to the end of the stream via StandardOutput and ProgramWatcher.Stream reading the same bytes with a pointer that starts at the beginning.&amp;nbsp; The ProgramWatcher instance is cached so that when you Read bytes off of ProgramWatcher.Stream, you are&amp;nbsp;incrementing the pointer.&amp;nbsp; &lt;/P&gt;
&lt;P&gt;&lt;EM&gt;These are&lt;/EM&gt; &amp;lt;ProgramWatcher.Stream pointer&amp;gt;&lt;EM&gt; bytes.&amp;nbsp; This is additional data&lt;/EM&gt; &amp;lt;StandardOutput Pointer&amp;gt;&lt;/P&gt;
&lt;P&gt;When the GetStatus method is called again, you are&amp;nbsp;accessing the same instance of the class, so the pointer is where you left it.&amp;nbsp; I was making this way to hard, so thanks to &lt;A class="" title="Todd Carter's blog" href="http://blogs.msdn.com/toddca" target=_blank mce_href="http://blogs.msdn.com/toddca"&gt;Todd Carter &lt;/A&gt;for helping clear this up.&lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;&lt;STRONG&gt;Parsing the \r and \r\n in the output returned by GetStatus&lt;/STRONG&gt;&lt;/P&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;This is important as console applications handle text ending in \r different than \r\n.&amp;nbsp; In the case of WinPE, you get output showing the percentage complete.&amp;nbsp; The text looks like:&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; |6.0.6001.16464 |&amp;nbsp; +&amp;nbsp; | WinPE-FontSupport-JA-JP-Package&lt;STRONG&gt;\r\n&lt;/STRONG&gt;[==============&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 25.0%&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ]&lt;STRONG&gt;\r&lt;/STRONG&gt;[===========================50.0%&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ]&lt;STRONG&gt;\r&lt;/STRONG&gt;[============================75.0%===========&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ]&lt;STRONG&gt;\r&lt;/STRONG&gt;&lt;BR&gt;[==========================100.0%==========================]&lt;STRONG&gt;\r\n&lt;/STRONG&gt;More Text&lt;/P&gt;
&lt;P&gt;In the console, this renders as the following when it is complete:&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; |6.0.6001.16464 |&amp;nbsp; +&amp;nbsp; | WinPE-FontSupport-JA-JP-Package&lt;BR&gt;More Text&lt;/P&gt;
&lt;P&gt;However, while the process is running, you would see the WinPE-FontSupport-JA-JP-Package line followed by the percentage.&amp;nbsp; When the next line ending in \r is written to the console, the previous line is replaced with the updated percentage.&amp;nbsp; The problem is that the browser doesn't handle \r and \r\n the same way.&amp;nbsp; So you would end up with the following:&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; |6.0.6001.16464 |&amp;nbsp; +&amp;nbsp; | WinPE-FontSupport-JA-JP-Package&lt;BR&gt;[==============&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 25.0%&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ]&lt;STRONG&gt;&lt;BR&gt;&lt;/STRONG&gt;[===========================50.0%&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ]&lt;STRONG&gt;&lt;BR&gt;&lt;/STRONG&gt;[============================75.0%===========&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ]&lt;STRONG&gt;&lt;BR&gt;&lt;/STRONG&gt;[==========================100.0%==========================]&lt;STRONG&gt;&lt;BR&gt;&lt;/STRONG&gt;More Text&lt;/P&gt;
&lt;P&gt;Not real pretty.&amp;nbsp; In the sample, I parse the output and if the output ends in \r,&amp;nbsp;I put the information in the TextBox.&amp;nbsp; If the text ends in \r\n, I clear the textbox and add the line to the TextArea.&amp;nbsp; This gets pretty close to the same output you see in a console and avoids a lot of noise and clutter in the output.&lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;Hopefully this sample and the information provided will help anyone out there trying to solve similar issues.&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=1840403" width="1" height="1"&gt;</content><author><name>Jorman</name><uri>http://blogs.msdn.com/members/Jorman.aspx</uri></author><category term="ASP.Net" scheme="http://blogs.msdn.com/jorman/archive/tags/ASP.Net/default.aspx" /></entry><entry><title>Viewstate error in mobile ASP.NET app</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/jorman/archive/2007/01/10/viewstate-error-in-mobile-asp-net-app.aspx" /><id>http://blogs.msdn.com/jorman/archive/2007/01/10/viewstate-error-in-mobile-asp-net-app.aspx</id><published>2007-01-10T22:35:00Z</published><updated>2007-01-10T22:35:00Z</updated><content type="html">&lt;P&gt;This is my third mobile post this week!&amp;nbsp; This one was tricky to track down so hopefully this will save someone some time.&amp;nbsp; The symptom you see is that users get the following exception.&amp;nbsp; If you're using ASP.NET 2.0, we would log this to the Event Viewer by default thanks to Web Events:&lt;/P&gt;
&lt;TABLE class="" style="COLOR: black; BACKGROUND-COLOR: beige"&gt;
&lt;TBODY&gt;
&lt;TR&gt;
&lt;TD class=""&gt;&lt;FONT size=2&gt;
&lt;P&gt;Exception of type 'System.Web.HttpUnhandledException' was thrown. ---&amp;gt; &lt;/P&gt;
&lt;P&gt;System.Exception: The page requires session state that is no longer available. Either the session has expired, the client did not send a valid session cookie, or the session state history size is too small. Try increasing the history size or session expiry limit.&lt;/P&gt;&lt;/FONT&gt;&lt;/TD&gt;&lt;/TR&gt;&lt;/TBODY&gt;&lt;/TABLE&gt;
&lt;P&gt;This error would appear randomly throughout the day in a high throughput site.&amp;nbsp; We were able to track this down using the IIS logs, Network Monitor, and in this case, the exceptions logged in the Event Viewer.&amp;nbsp; The event logging in 2.0 captures a lot of information that is&amp;nbsp;useful for lining&amp;nbsp;up the exception with data gathered.&amp;nbsp; In this instance, we used the client IP linked to the request and then filtered the Network Monitor logs using this IP.&amp;nbsp; This allowed me to track the user's requests to see how they were using the site at the time of the failure.&lt;/P&gt;
&lt;P&gt;In this case, we could see the client making requests for a few minutes, then their traffic would go away for longer than the session timeout.&amp;nbsp; Their next request would come in for a page that they weren't browsing prior and would cause the exception.&amp;nbsp; Looking at this data, we determined that users were bookmarking the site on their mobile devices.&amp;nbsp; While this normally isn't a big deal, there are some devices that result in an __viewstate field in the QueryString.&amp;nbsp; When you bookmark this URL, the initial request is now going to cause the mobile page to lookup the viewstate which is stored in Session for mobile forms.&amp;nbsp; Since this is the first request, the session is just now being initialized, the ViewState isn't available, and the exception is thrown.&lt;/P&gt;
&lt;P&gt;You can avoid this problem by adding the following code to Session_Start in the global.asax or a HttpModule.&amp;nbsp; You can even get fancier and add some code to only remove the __viewstate QueryString if your pages are looking for other items in the QueryString collection.&amp;nbsp; This code will ensure that when a new session is being created, that the __viewstate QueryString is not part of that request.&lt;/P&gt;
&lt;TABLE class="" style="COLOR: black; BACKGROUND-COLOR: beige"&gt;
&lt;TBODY&gt;
&lt;TR&gt;
&lt;TD class=""&gt;&lt;FONT size=2&gt;
&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; void Session_Start(object sender, EventArgs e) &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Code that runs when a new session is started&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (HttpContext.Current.Request.QueryString.Count &amp;gt; 0)&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; HttpContext.Current.Response.Redirect(HttpContext.Current.Request.Url.LocalPath.ToString());&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;BR&gt;&lt;/P&gt;&lt;/FONT&gt;&lt;/TD&gt;&lt;/TR&gt;&lt;/TBODY&gt;&lt;/TABLE&gt;
&lt;P&gt;You could also track this down by logging the QueryString in the IIS logs and looking for __viewstate in that field.&amp;nbsp; The exception logged in the Event Viewer in 2.0 also log the UTC time to make it easy to line up the IIS entries which use UTC by default with the exception.&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=1445628" width="1" height="1"&gt;</content><author><name>Jorman</name><uri>http://blogs.msdn.com/members/Jorman.aspx</uri></author><category term="ASP.Net" scheme="http://blogs.msdn.com/jorman/archive/tags/ASP.Net/default.aspx" /></entry><entry><title>Determining what capabilities ASP.NET is using to render pages</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/jorman/archive/2007/01/09/determining-what-capabilities-asp-net-is-using-to-render-pages.aspx" /><id>http://blogs.msdn.com/jorman/archive/2007/01/09/determining-what-capabilities-asp-net-is-using-to-render-pages.aspx</id><published>2007-01-09T22:26:00Z</published><updated>2007-01-09T22:26:00Z</updated><content type="html">&lt;P&gt;When you make a request to an ASP.NET based site, the browser's capabilities are determined by the &amp;lt;browserCaps&amp;gt; section in the 1.x Framework and the .browser files in the 2.0 framework.&amp;nbsp; Knowing which capabilites that ASP.NET is using to render the page can be especially important in mobile applications.&amp;nbsp; &lt;/P&gt;
&lt;P&gt;You can use the following page to return all the MobileCapabilities for the device by browsing the page:&lt;/P&gt;
&lt;TABLE class="" style="COLOR: black; BACKGROUND-COLOR: beige"&gt;
&lt;TBODY&gt;
&lt;TR&gt;
&lt;TD class=""&gt;&lt;FONT size=2&gt;
&lt;P&gt;&amp;lt;%&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;@&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#a31515 size=2&gt;Page&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#ff0000 size=2&gt;language&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;="c#"&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#ff0000 size=2&gt;AutoEventWireup&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;="true"&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#ff0000 size=2&gt;Inherits&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;="System.Web.UI.MobileControls.MobilePage"&lt;/FONT&gt;&lt;FONT size=2&gt; %&amp;gt;&lt;BR&gt;&amp;lt;%&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;@&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#a31515 size=2&gt;Import&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#ff0000 size=2&gt;namespace&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;="System.Web.Mobile"&lt;/FONT&gt;&lt;FONT size=2&gt; %&amp;gt;&lt;BR&gt;&amp;lt;%&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;@&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#a31515 size=2&gt;Import&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#ff0000 size=2&gt;namespace&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;="System.Reflection"&lt;/FONT&gt;&lt;FONT size=2&gt; %&amp;gt;&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&amp;lt;&lt;/FONT&gt;&lt;FONT color=#a31515 size=2&gt;script&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#ff0000 size=2&gt;runat&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;="server"&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;protected&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;void&lt;/FONT&gt;&lt;FONT size=2&gt; Page_Load(&lt;/FONT&gt;&lt;FONT color=#2b91af size=2&gt;Object&lt;/FONT&gt;&lt;FONT size=2&gt; sender, &lt;/FONT&gt;&lt;FONT color=#2b91af size=2&gt;EventArgs&lt;/FONT&gt;&lt;FONT size=2&gt; e)&lt;BR&gt;&lt;FONT color=#0000ff&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/FONT&gt;{&lt;BR&gt;&lt;FONT color=#0000ff&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#2b91af size=2&gt;MobileCapabilities&lt;/FONT&gt;&lt;FONT size=2&gt; capabilities = (&lt;/FONT&gt;&lt;FONT color=#2b91af size=2&gt;MobileCapabilities&lt;/FONT&gt;&lt;FONT size=2&gt;)Request.Browser;&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#2b91af size=2&gt;&lt;FONT color=#0000ff&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/FONT&gt;Type&lt;/FONT&gt;&lt;FONT size=2&gt; t = &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;typeof&lt;/FONT&gt;&lt;FONT size=2&gt;(&lt;/FONT&gt;&lt;FONT color=#2b91af size=2&gt;MobileCapabilities&lt;/FONT&gt;&lt;FONT size=2&gt;);&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#2b91af size=2&gt;&lt;FONT color=#0000ff&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/FONT&gt;PropertyInfo&lt;/FONT&gt;&lt;FONT size=2&gt;[] propertyInfos = t.GetProperties();&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; foreach&lt;/FONT&gt;&lt;FONT size=2&gt;(&lt;/FONT&gt;&lt;FONT color=#2b91af size=2&gt;PropertyInfo&lt;/FONT&gt;&lt;FONT size=2&gt; pi &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;in&lt;/FONT&gt;&lt;FONT size=2&gt; propertyInfos)&lt;BR&gt;&lt;FONT color=#0000ff&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/FONT&gt;{&lt;BR&gt;&lt;FONT color=#0000ff&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/FONT&gt;System.Web.UI.MobileControls.&lt;/FONT&gt;&lt;FONT color=#2b91af size=2&gt;Label&lt;/FONT&gt;&lt;FONT size=2&gt; lbl = &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;new&lt;/FONT&gt;&lt;FONT size=2&gt;&amp;nbsp;&lt;BR&gt;&lt;FONT color=#0000ff&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/FONT&gt;System.Web.UI.MobileControls.&lt;/FONT&gt;&lt;FONT color=#2b91af size=2&gt;Label&lt;/FONT&gt;&lt;FONT size=2&gt;();&lt;BR&gt;&lt;FONT color=#0000ff&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/FONT&gt;lbl.Text = pi.Name + &lt;/FONT&gt;&lt;FONT color=#a31515 size=2&gt;" = "&lt;/FONT&gt;&lt;FONT size=2&gt; + capabilities[pi.Name];&lt;BR&gt;&lt;FONT color=#0000ff&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/FONT&gt;Form1.Controls.Add(lbl);&lt;BR&gt;&lt;FONT color=#0000ff&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/FONT&gt;}&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&amp;lt;/&lt;/FONT&gt;&lt;FONT color=#a31515 size=2&gt;script&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&amp;gt;&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&amp;lt;&lt;/FONT&gt;&lt;FONT color=#a31515 size=2&gt;mobile&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;:&lt;/FONT&gt;&lt;FONT color=#a31515 size=2&gt;Form&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#ff0000 size=2&gt;id&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;=Form1&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#ff0000 size=2&gt;runat&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;="server"&amp;gt;&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&amp;lt;/&lt;/FONT&gt;&lt;FONT color=#a31515 size=2&gt;mobile&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;:&lt;/FONT&gt;&lt;FONT color=#a31515 size=2&gt;Form&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&amp;gt;&lt;/FONT&gt;&lt;/P&gt;&lt;/TD&gt;&lt;/TR&gt;&lt;/TBODY&gt;&lt;/TABLE&gt;
&lt;P&gt;The MobileCapabilities are determined by the UserAgent string that ASP.NET receives.&amp;nbsp; You can log the UserAgent string in the IIS logs or you can use a tool like &lt;A class="" title=Fiddler href="http://www.fiddlertool.com/fiddler/" target=_blank mce_href="http://www.fiddlertool.com/fiddler/"&gt;Fiddler&lt;/A&gt; or &lt;A class="" title="Web Development Helper" href="http://projects.nikhilk.net/Projects/WebDevHelper.aspx" mce_href="http://projects.nikhilk.net/Projects/WebDevHelper.aspx"&gt;Web Development Helper&lt;/A&gt; in IE to get this information.&amp;nbsp; Once you have the UserAgent string, you can use Fiddler to pass the same UserAgent string while browsing in IE.&amp;nbsp; This will give you a larger viewing area for looking at hte list of MobileCapabilities.&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=1440127" width="1" height="1"&gt;</content><author><name>Jorman</name><uri>http://blogs.msdn.com/members/Jorman.aspx</uri></author><category term="ASP.Net" scheme="http://blogs.msdn.com/jorman/archive/tags/ASP.Net/default.aspx" /></entry><entry><title>Mobile ASP.NET Emulators</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/jorman/archive/2007/01/08/mobile-asp-net-emulators.aspx" /><id>http://blogs.msdn.com/jorman/archive/2007/01/08/mobile-asp-net-emulators.aspx</id><published>2007-01-08T23:44:00Z</published><updated>2007-01-08T23:44:00Z</updated><content type="html">&lt;P&gt;When developing Mobile ASP.NET apps, it is useful to test the application across a variety of devices if the site is going to be posted to the internet.&amp;nbsp; ASP.NET Mobile controls rely on adapters to handle rendering on the different devices.&amp;nbsp; In order to hit the different adapters to ensure your page will work across the devices, you can use emulators.&amp;nbsp; While troubleshooting mobile issues, I typically use the following emulators:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;HTML3.2 - I use Internet Explorer or one of the Pocket PC/Smartphone emulators that ship with Visual Studio.&amp;nbsp; The default rendering for these devices is HTML 3.2 and as a result, the mobile controls will use the HTML32 adapters to render.&lt;/LI&gt;
&lt;LI&gt;&amp;nbsp;WML - I use the OpenWave 7 emulator that comes as part of the OpenWave 7 SDK.&amp;nbsp; ASP.NET picks up this device with a default rendering of WML allowing the mobile controls to use the WML adapters for rendering.&lt;/LI&gt;
&lt;LI&gt;XHTML - I use the OpenWave 6.2.2 emulator.&amp;nbsp; The default rendering for this device is XHTML.&lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;You can also use the &amp;lt;browserCaps&amp;gt;&amp;nbsp;section in machine.config (1.x Framework) or .browser files (2.x Framework) to force the preferredRenderingType property of a device, however, I have found that using the emulators is quicker for testing against.&lt;/P&gt;
&lt;P&gt;OpenWave emulators can be found here: &lt;A href="http://developer.openwave.com/dvl/tools_and_sdk/phone_simulator/" mce_href="http://developer.openwave.com/dvl/tools_and_sdk/phone_simulator/"&gt;http://developer.openwave.com/dvl/tools_and_sdk/phone_simulator/&lt;/A&gt;&lt;/P&gt;
&lt;P&gt;The Pocket PC/Smartphone emulators are available on the Tools menu, under the Connect to Device option.&lt;/P&gt;
&lt;P mce_keep="true"&gt;If you have a specific device and ASP.NET is not rendering the right content; i.e. your device supports JavaScript, but you're not getting JavaScript; you can use the Device Profiling Tool to generate a profile of the device and generate a &amp;lt;browserCaps&amp;gt; section (1.x) or a .browser file(2.0).&amp;nbsp; &lt;/P&gt;
&lt;P mce_keep="true"&gt;&amp;nbsp;If you need to build a section for &amp;lt;browserCaps&amp;gt;, you can do this online here:&amp;nbsp; &lt;BR&gt;&lt;A href="http://www.asp.net/mobile/profile/default.aspx" mce_href="http://www.asp.net/mobile/profile/default.aspx"&gt;http://www.asp.net/mobile/profile/default.aspx&lt;/A&gt;&lt;/P&gt;
&lt;P mce_keep="true"&gt;If you need to generate a .browser file you can download the device profiler and run it locally:&lt;BR&gt;&lt;A href="http://www.asp.net/sandbox/app_devprof.aspx?tabid=62" mce_href="http://www.asp.net/sandbox/app_devprof.aspx?tabid=62"&gt;http://www.asp.net/sandbox/app_devprof.aspx?tabid=62&lt;/A&gt;&lt;/P&gt;
&lt;P mce_keep="true"&gt;You can find links to training and mobile ASP.NET development here:&amp;nbsp; &lt;A href="http://www.asp.net/default.aspx?tabIndex=6&amp;amp;tabId=44" mce_href="http://www.asp.net/default.aspx?tabIndex=6&amp;amp;tabId=44"&gt;http://www.asp.net/default.aspx?tabIndex=6&amp;amp;tabId=44&lt;/A&gt;&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=1435949" width="1" height="1"&gt;</content><author><name>Jorman</name><uri>http://blogs.msdn.com/members/Jorman.aspx</uri></author><category term="ASP.Net" scheme="http://blogs.msdn.com/jorman/archive/tags/ASP.Net/default.aspx" /></entry><entry><title>JavaScript Fun!</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/jorman/archive/2006/11/22/javascript-fun.aspx" /><id>http://blogs.msdn.com/jorman/archive/2006/11/22/javascript-fun.aspx</id><published>2006-11-23T01:24:00Z</published><updated>2006-11-23T01:24:00Z</updated><content type="html">&lt;P&gt;I was recently working with JavaScript and ran into some weird things I hadn't ran into before.&amp;nbsp; While I'm sure the JavaScript masters of the world already know all about this stuff, hopefully this post can keep others from pulling out too much hair.&amp;nbsp; The first one deals with scoping:&lt;/P&gt;
&lt;P&gt;If you don’t explicitly var an object, that object is declared globally.&amp;nbsp; The code will typically not fail, however, it will give you odd behavior.&amp;nbsp; This becomes an issue if you have the following:&lt;/P&gt;
&lt;P&gt;&amp;nbsp;function Loop1(){&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; for(x = 0; x &amp;lt; 10; x++){&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Loop2();&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; alert(x);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; function Loop2(){&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; for(x = 0; x &amp;lt; 10; x++){&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; //do work here&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/P&gt;
&lt;P&gt;You would expect the alert to occur 10 times, however, since the x declared in the first for loop does not have var in front of it, the variable is global.&amp;nbsp; When Loop2 is called, the loop increments x to 10 causing the for loop in Loop1 to only occur 1 time.&amp;nbsp; To correct this code, change the for loops to:&lt;BR&gt;for(var x = 0; x &amp;lt; 10; x++)&lt;BR&gt;&lt;/P&gt;
&lt;P&gt;The other issue deals with naming of objects and functions.&amp;nbsp; If you're developing everything it's no big deal as you will typically know what the ID's will be on the client as well as the names of JavaScript functions, but if you're leveraging someone's JavaScript library, this can become more interesting.&amp;nbsp;&amp;nbsp; The error you get&amp;nbsp;in Internet Explorer is&amp;nbsp;"Object doesn't support this property or method".&amp;nbsp; The following line will reproduce the behavior, but imagine if you had a page with 50 controls and the function name that matches is in a JavaScript file you didn't write:&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&amp;lt;input type="button" id="AbortCallback" value="Abort" onclick="AbortCallback()" /&amp;gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=1124189" width="1" height="1"&gt;</content><author><name>Jorman</name><uri>http://blogs.msdn.com/members/Jorman.aspx</uri></author><category term="ASP.Net" scheme="http://blogs.msdn.com/jorman/archive/tags/ASP.Net/default.aspx" /></entry><entry><title>Custom WebPart Catalog</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/jorman/archive/2006/10/05/Custom-WebPart-Catalog.aspx" /><id>http://blogs.msdn.com/jorman/archive/2006/10/05/Custom-WebPart-Catalog.aspx</id><published>2006-10-05T23:34:00Z</published><updated>2006-10-05T23:34:00Z</updated><content type="html">&lt;P&gt;Trying to catch back up on my blogging, I have a list of topics to post on, just haven't had time to get to them.&amp;nbsp; I wrote this article over a month ago...figured I would link it up from here. &lt;/P&gt;
&lt;P&gt;The default web part catalogs that are shipped with ASP.Net&amp;nbsp;require you to configure the list of web parts you want to display in your catalog.&amp;nbsp; We've had a few requests for a more dynamic approach and the article has a sample that can get you started on this.&lt;/P&gt;
&lt;P&gt;&lt;A href="http://support.microsoft.com/kb/910446" mce_href="http://support.microsoft.com/kb/910446"&gt;http://support.microsoft.com/kb/910446&lt;/A&gt;&lt;/P&gt;
&lt;P&gt;The article links up to a sample Solution and lays out the files and what they do.&amp;nbsp; The main piece is a custom web part catalog that uses reflection to populate the list of web parts.&amp;nbsp; The idea is that you drop a .dll into the /bin folder of your app and the catalog will automatically pick out the web part controls in the dll.&amp;nbsp; It caches the list of parts to avoid the cost of looking up the dll's on future requests.&amp;nbsp; This works great since adding a dll to the /bin will recycle the app domain and clear the cache, so all you need to do to add web parts to the catalog is to add the dll to the /bin.&lt;/P&gt;
&lt;P&gt;The other piece is a custom WebPart that pulls data from an RSS feed and shows the different types of properties you can implement in the web part.&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=794569" width="1" height="1"&gt;</content><author><name>Jorman</name><uri>http://blogs.msdn.com/members/Jorman.aspx</uri></author><category term="ASP.Net" scheme="http://blogs.msdn.com/jorman/archive/tags/ASP.Net/default.aspx" /></entry><entry><title>System.InvalidOperationException: Mutex could not be created.</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/jorman/archive/2006/07/24/system-invalidoperationexception-mutex-could-not-be-created.aspx" /><id>http://blogs.msdn.com/jorman/archive/2006/07/24/system-invalidoperationexception-mutex-could-not-be-created.aspx</id><published>2006-07-24T16:35:00Z</published><updated>2006-07-24T16:35:00Z</updated><content type="html">&lt;P&gt;&lt;FONT face=Arial size=2&gt;We've seen a few of these issues come through lately andwanted to get something posted so people can find it.&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;If you created a custom account to run the process that ASP.NET is running in, you may encounter the following exception:&lt;/FONT&gt;&lt;/P&gt;
&lt;TABLE class="" style="COLOR: black; BACKGROUND-COLOR: beige"&gt;
&lt;TBODY&gt;
&lt;TR&gt;
&lt;TD class=""&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;System.InvalidOperationException: Mutex could not be created.&lt;BR&gt;&lt;BR&gt;Stack Trace:&amp;nbsp;&lt;BR&gt;[InvalidOperationException: Mutex could not be created.]&lt;BR&gt;&amp;nbsp;&amp;nbsp; System.Web.Compilation.CompilationMutex..ctor(String name, String comment) +3464689&lt;BR&gt;&amp;nbsp;&amp;nbsp; System.Web.Compilation.CompilationLock..cctor() +158&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;[TypeInitializationException: The type initializer for 'System.Web.Compilation.CompilationLock' threw an exception.]&lt;BR&gt;&amp;nbsp;&amp;nbsp; System.Web.Compilation.CompilationLock.GetLock(Boolean&amp;amp; gotLock) +32&lt;BR&gt;&amp;nbsp;&amp;nbsp; System.Web.Compilation.BuildManager.EnsureTopLevelFilesCompiled() +114&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT size=2&gt;&lt;FONT face=Arial&gt;[HttpException (0x80004005): The type initializer for 'System.Web.Compilation.CompilationLock' threw an exception.]&lt;BR&gt;&amp;nbsp;&amp;nbsp; System.Web.HttpRuntime.FirstRequestInit(HttpContext context) +3426871&lt;BR&gt;&amp;nbsp;&amp;nbsp; System.Web.HttpRuntime.EnsureFirstRequestInit(HttpContext context) +88&lt;BR&gt;&amp;nbsp;&amp;nbsp; System.Web.HttpRuntime.ProcessRequestInternal(HttpWorkerRequest wr) +149&lt;BR&gt;--------------------------------------------------------------------------------&lt;BR&gt;Version Information: Microsoft .NET Framework Version:2.0.50727.42; ASP.NET Version:2.0.50727.42&lt;/FONT&gt; &lt;/FONT&gt;&lt;/P&gt;&lt;/TD&gt;&lt;/TR&gt;&lt;/TBODY&gt;&lt;/TABLE&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;Note:&amp;nbsp; The error will appear to be random, but once it appears, will remain until a reboot or until the handles to the mutex are closed.&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;&lt;STRONG&gt;Cause:&lt;BR&gt;&lt;/STRONG&gt;&lt;/FONT&gt;&lt;FONT face=Arial size=2&gt;&lt;STRONG&gt;======&lt;BR&gt;&lt;/STRONG&gt;&lt;/FONT&gt;&lt;FONT face=Arial size=2&gt;This occurs because the permissions on the following registry key no longer have your custom account:&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\ASP.NET\2.0.50727.0\CompilationMutexName&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;The compilation mutex gets it's permissions from this registry key and with your custom account missing, the process running ASP.NET cannot get a handle to the mutex and fails during compilation.&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;&lt;FONT face=Arial size=2&gt;Resolution:&lt;BR&gt;&lt;/FONT&gt;&lt;FONT face=Arial size=2&gt;=========&lt;/FONT&gt;&lt;/STRONG&gt;&lt;/P&gt;
&lt;OL&gt;
&lt;LI&gt;&lt;FONT face=Arial size=2&gt;Run the following to add your custom account to the registry key permissions:&lt;BR&gt;&lt;/FONT&gt;&lt;FONT face=Arial size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;ASPNET_regiis -ga domain\account.&lt;/FONT&gt; 
&lt;LI&gt;&lt;FONT face=Arial size=2&gt;Either restart the server or close the handles to the mutex (see below)&lt;/FONT&gt;&lt;/LI&gt;&lt;/OL&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;To close the handles to the Mutex:&lt;/FONT&gt;&lt;/P&gt;
&lt;OL&gt;
&lt;LI&gt;&lt;FONT face=Arial size=2&gt;Download and launch Process Explorer from &lt;/FONT&gt;&lt;A href="http://www.sysinternals.com/" mce_href="http://www.sysinternals.com/"&gt;&lt;FONT face=Arial size=2&gt;&lt;A href="http://www.sysinternals.com/" mce_href="http://www.sysinternals.com/"&gt;www.sysinternals.com&lt;/FONT&gt;&lt;FONT face=Arial size=2&gt;&lt;/FONT&gt;&lt;/A&gt; 
&lt;LI&gt;&lt;FONT face=Arial size=2&gt;From the Find menu, select Find Handle or DLL&lt;/FONT&gt; 
&lt;LI&gt;&lt;FONT face=Arial size=2&gt;In the Handle or DLL substring box, type “mutant” (without quotes) and click Search&lt;/FONT&gt; 
&lt;LI&gt;&lt;FONT face=Arial size=2&gt;Click the Handle or DLL column heading to sort the items and find a mutex that starts with CL.&amp;nbsp; The handle will typically be devenv.exe (the IDE for Visual Studio) and aspnet_wp.exe or w3wp.exe.&amp;nbsp; The handle will look similar to:&lt;/FONT&gt; 
&lt;LI&gt;&lt;FONT face=Arial size=2&gt;\BaseNameObjects\CLbdd6aa8f&lt;/FONT&gt; 
&lt;LI&gt;&lt;FONT face=Arial size=2&gt;Select the handle in the search box and Process Explorer locates the Process and the handle in the main window&lt;/FONT&gt; 
&lt;LI&gt;&lt;FONT face=Arial size=2&gt;Right-click the handle in the main window and select Close Handle&lt;/FONT&gt;&lt;/LI&gt;&lt;/OL&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;&lt;STRONG&gt;Additional Info:&lt;BR&gt;&lt;/STRONG&gt;&lt;/FONT&gt;&lt;FONT face=Arial size=2&gt;&lt;STRONG&gt;============&lt;/STRONG&gt;&lt;BR&gt;The error may occur anytime you run ASP.NET as a custom account and the above mentioned registry key does not have the account listed in the permissions.&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;If you receive the error and you are running with a custom account on IIS 6 in worker process mode (code running in w3wp.exe), you can add your custom account to the IIS_WPG group on the server.&amp;nbsp; The IIS_WPG group is granted access to the registry key by default.&lt;/FONT&gt;&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=676660" width="1" height="1"&gt;</content><author><name>Jorman</name><uri>http://blogs.msdn.com/members/Jorman.aspx</uri></author><category term="ASP.Net" scheme="http://blogs.msdn.com/jorman/archive/tags/ASP.Net/default.aspx" /></entry></feed>