Wednesday 08 October, 2008 (.Net | Bugs | Fixes | Vista | Web)
While trying out a complex URL rewriting scenario in ASP.Net I ran into a pretty strange problem that resulted in a 404 error:
Description: HTTP 404. The resource you are looking for (or one of its dependencies) could have been removed, had its name changed, or is temporarily unavailable. Please review the following URL and make sure that it is spelled correctly.
Requested Url: /6.aspx/t.aspx
My code is very similar to a solution that I have created previously in ASP.Net 2.0 on Windows XP so I was a little surprised that I was getting an error. The strange thing is that /6.aspx is the original URL and /default.aspx is the rewritten url, in the error message it looks like the original URL has partially overwritten the new URL!
The exception that is caught has a stack trace that ends with: System.Web.UI.Util.CheckVirtualFileExists(VirtualPath virtualPath)
Looking around the Internet for people who have already encountered this problem (as I always do) didn't lead to any immediate solutions. On the IIS forum there is one discussion on Module doesn't work on IIS7 under vista business which lead me to a solution. It seems to me that URL rewriting is broken on Vista prior to SP1. Part of the SP1 upgrade incorporates changes to IIS 7 that were made in Windows Server 2008 as detailed on Microsoft TechNet. So after installing SP1 my solution works as expected.
Thursday 26 June, 2008 (.Net | Bugs | Fixes | Team System)
We have just had a major Active Directory issue that has affected the Team Foundation Server instance that all the developers at the client that I am working at use. The problem occured when some users where erased in the Active Directory and were subsequently recreated with the same user names. These new user accounts cannot access the Team Foundation Server.
A large part of the problem was solved by just removing users from TFS and then putting them back in again. This recreates all the wiring under the surface in TFS so that the users can access the server but all their existing workspace info, pending checkins and so on are lost locally yet exist in Team Foundation Server with a different Owner under the same user name... The only way to tell them apart is by their SID and that the original account may get suffixed with a number in workspace lists: AD\username:61.
My first thought was to remove all the workspaces and pending checkins and let people manually resynch their projects. When I clicked undo pending change for a bunch of changes in Attrice Sidekicks an unhandled exception popped up: "Object reference not set to an instance of an object". I just can't undo these changes, there is a clue to the problem when I try to unlock a changed file, I get an Unlock error:
Failed to unlock $/Project/Path/file (TF14061: The workspace COMPUTERNAME; AD\username does not exist.)
I can't search for workspaces by username either, even doing a simple TFSSecurtiy /i "ad\username" /server:TFSName for one of the affected accounts returns "Error: The identity cannot be resolved." Since the original accounts have been removed from Active Directory I cannot easily get hold of their SIDs for querying with TFSSecurity. Attempting to delete the workspaces from the command line return the following error:
TF14061: The workspace WORKSPACENAME;AD\username does not exist.
Things seemed pretty messed up... I found some clues as to what was required to get things working again:
http://support.microsoft.com/kb/948679
http://support.microsoft.com/kb/823278
http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=454060&SiteID=1
According to the KnowledgeBase articles trying to create a new project while TFS is in this state may result in the following error:
TF30170: the plugin Microsoft.ProjectCreationWizard.WorkItemTracking Failed during task WITS from group WorkItemTracking
Basically Team Foundation Server has a bug that causes deleted accounts to not be resynched correctly and SharePoint doesn't handle recreated user accounts at all - you have to resynch them manually. Unfortunately in addition to this there is a bug in TFS SP1 which prevents TfsAdminUtilI from correcting the SIDS! You get the following error:
ERROR: Could not access database.
In the end I managed to correct all the problems, here are the steps required:
- Contact Microsoft Support and request the hotfix for http://support.microsoft.com/kb/934216
- Install the hotfix...
- Follow the steps in http://support.microsoft.com/kb/948679 to resynch the users SIDs in TFS
- Follow the steps in http://support.microsoft.com/kb/823278 to resynch the users in SharePoint
- Recycle the TFS App Pool to force an update of all users and groups in TFS.
Look out with users who have their workspaces mapped to "c:\documents and settings\" the new user accounts cannot necessarily access their old files there since they now log on with a new account (which just happens to have the same name).
Thursday 15 May, 2008 (.Net | Bugs | Java | Web)
I have been having some trouble lately trying to debug a .Net web service that I have constructed for a proof of concept. The scenario is that we have a Java application that calls a web service and the web service passes the call on to BizTalk for processing. Not a terribly complex scenario so I wasn't expecting much trouble setting up the POC. Unfortunately we have experienced some really strange problems. Calling the web service from a .Net client works without problems but when the exact same SoapEnvelope is used in the Java client through a proxy we get a "HTTP/1.1 400 Bad Request" error!
How is this possible? Well after much trial and error, searching the net and generally scratching my head I finally found a clue to the root cause of the error. One of the scenarios when "400 Bad Request" is returned is if the value of the content-length header is smaller then the actual length of the message body. I could not find a simple way to get IIS 6 to log the actual HTTP headers which were received and my favourite HTTP debugger Fiddler couldn't be used when the calls came from the Java client so it was very difficult to verify. The WSE input tracing showed a correct request and the application log contained the following unhelpful message
Process information:
Process ID: 5856
Process name: w3wp.exe
Account name: AD\serviceaccount
Exception information:
Exception type: HttpException
Exception message: Server cannot clear headers after HTTP headers have been sent.
I managed to get a nice raw HTTP dump sent to the application log by adding the following to my Global.asax
void Application_BeginRequest(object sender, EventArgs e)
{
//save position for reset
long position = HttpContext.Current.Request.InputStream.Position;
string requestBody = new StreamReader(HttpContext.Current.Request.InputStream).ReadToEnd();
//reset the position
HttpContext.Current.Request.InputStream.Position = position;
EventLog.WriteEntry("Service HTTP Dump", Server.UrlDecode(Context.Request.Headers.ToString()).Replace("&", Environment.NewLine) + Environment.NewLine + requestBody);
}
Using this I could verify that it was in fact an incorrect content-length in the HTTP header which was causing the problem. Using Notepad++ and Fiddler I could see that the actual content-length was 634 using CRLF and 631 using only CR. The Java client was specifying 631 but the .Net web service was actually receiving 634. With the help of Telnet I could send in a call with 631 characters and CR as line-end and verify that the .Net web service handled the request properly. For the sake of clarity this is a sample Java HTTP header:
POST /path/service.asmx HTTP/1.1
Host: servername:80
Cache-Control: no-cache
Connection: close
Pragma: no-cache
Content-Type: text/xml; charset=utf-8
Accept: application/soap+xml, application/dime, multipart/related, text/*
User-Agent: Axis/1.1
SOAPAction: "http://schemas.example.com/2008/04/22/Service:ValidateRequest"
Content-Length: 631
The same request from a .Net client:
POST /path/service.asmx HTTP/1.1
Host: servername:80
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; MS Web Services Client Protocol 2.0.50727.1433)
Content-Type: text/xml; charset=utf-8
SOAPAction: "http://schemas.example.com/2008/04/22/Service:ValidateRequest"
Content-Length: 634
Expect: 100-continue
Both requests had a length of 634.
More info on the exact nature and calculation of the HTTP headers are in the RFC and in section 3.7.1 of the RFC valid line endings for the message body are defined. Basically it says that CR, LF or CRLF should be valid as long as they are used consistently but CRLF should still be treated as two characters for content-length (the spec doesn't explicitly say that but I presume that it is required). So the .Net web service has a correct behaviour, the specification also says that content-length may be omitted in HTTP 1.1 although it should be honoured if it is specified. Since it is required in 1.0 and it is usually very easy to calculate it isn't something that you usually have to think about trying to omit and it is hidden in the web calling infrastructure of Java and .Net.
I am not sure where our error is introduced. It could be when the original message is constructed in Java, whatever library is used to calculate the content-length could do so incorrectly (not likely). A more probable source is that the message is constructed with correct line-ends in the body (CR or LF) but that the intermediary proxy recodes the call with new line-ends (CRLF) without updating the content-length.
How can we fix it? I believe that there are three possible solutions for the problem (we haven't solved it yet).
- Remove the proxy, should be the easiest but due to the network configuration that isn't possible at the moment.
- Change the way that the Java client creates it's content so that it uses CRLF by default thereby forcing a correct larger content-length.
- Use the Application_BeginRequest method in Global.asax or an HTTPHandler to somehow rewrite the input stream or recalculate the content-length. At the moment I am not sure that either is possible.
Update
We managed to remove the proxy (which was actually part of a VPN connection) and our troubles disappeared.
Tuesday 15 April, 2008 (.Net | Blogging | Bugs | Fixes | Web)
I seem to have managed to get server pings from dasBlog to work in medium trust! This has been a major issue for me previously, not as much of an issue now that I primarily use off-line tools but it is still great to have it. The key is that originUrl in the medium trust settings supports regular expressions! More info on Haacked, which is where I found the solution. Just to make things clear:
<trust level="Medium" originUrl=".*" />
will allow your web site to send web requests to any external site...
Monday 04 February, 2008 (.Net | Bugs | Fixes | Web)
Recently I was working on ASP.Net 2.0 Web Parts in a Virtual PC environment and ran across a strange exception. I had read that the Web Parts personalization database is separate from the membership and profiles databases but had not really thought about it further. Previously everything just seemed to work once I ran "aspnet_regsql" to create the aspnetdb database to handle all the data for the services.
In the VPC there was already a really simple Web Part Page that I wanted to test. I had not prepared the VPC myself and others had been using it before me (so I presumed that it would work) but no one had used it in a long while. When I attempted to login and access the Web Part page I received this exception:
Procedure or Function 'aspnet_PersonalizationPerUser_GetPageSettings' expects parameter '@TimeZoneAdjustment', which was not supplied.
I checked the aspnetdb database to see if there was something wrong there but the stored procedure did not contain a '@TimeZoneAdjustment' parameter... Some related forum discussions on the web indicated that it might be a problem with the solution and database being created under a pre-release version of .Net 2.0. I tried re-running aspnet_regsql to remove and recreate the aspnetdb database, I reinstalled .Net 2.0, I installed SP1 for .Net 2. Nothing helped.
It turns out that the default personalization provider for Web Parts uses a file based SQL Express database which is automatically created in the App_Data folder of the web application. This database had already been created using a previous version of the framework before I started looking at the solution. For the sake of confusion it is also named aspnetdb, removing this database from the App_Data folder solved the problem. When I logged in and opened the Web Part page the database was recreated with the correct structure and everything just worked!
Tuesday 28 November, 2006 (.Net | Bugs | dasBlog)
Basically avoid changing the xml files under content for dasBlog, you will mess up your blog. I did this in an attempt to make a post that I started on the 7th but posted on the 8th go back to being on the 7th... First I just changed the CreatedDate in the content xml and this almost worked, the post would intermittently disappear from the site (and the file). Luckily I had made a backup of the content files before I did this so I could just put the post back up when it disappeared. I quickly realised that this was a suboptimal solution! So I moved the post over to a new file with the correct date in the name. This file was eaten up by dasBlog and mysteriously disappeared, although I didn't notice it for about a week. What had happened was that I had got the date for the outer element set to another day in conflict with another file. So dasBlog just kicked it. Once I had got the date right it still took several updates for the change to propagate. Now I hope I have saved all my posts!
Thursday 23 November, 2006 (Bugs | Team System)
I have been attempting to run a Team Foundation build server on a separate machine outside our domain. Install and connectivity between the servers was no problem but once we got the build configuration up and tried to perform a build from Team Explorer we got an error:
TF42056: The build service could not connect to the Team Foundation Server: TF30063: You are not authorized to access https://myserver.
I tried all our standard solutions:
- Set https://myserver as local intranet in Internet Explorer security settings.
- Stored username and password in the control panel applet.
- Cached username and password in Team Explorer
The IDE works perfectly but nothing works when we run Team Build, it turns out that this is an unsupported configuration due to the Team Build service not picking up locally configured alternate credentials. It's a known issue in v1 for some of the command line tools. So far there doesn't seem to be a workaround that could fix this, perhaps SP1 will add alternate credential support for all the command line tools.
These MSDN forum threads didn't really help us but might help others with non-domain related issues:
https://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=380144&SiteID=1
http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=20644&SiteID=1
UPDATE:
I continued searching for info on this and found http://msdn2.microsoft.com/en-US/library/ms400712(VS.80).aspx#:
The Team Foundation client is in a workgroup instead of a domain, but Team Foundation Server is deployed in a domain. Local user accounts must be created on the Team Foundation client computers. If you do not want to require users to type a user name and password every time that a Team Foundation client must connect to Team Foundation Server, make sure that the local user accounts use the same user name and password as the domain user names. For more information, see Managing Team Foundation Server in a Workgroup.
I couldn't get a local workgroup account set up so that it mapped to a domain account but I attempted a completely local configuration which did work even though my Team Foundation Server is set up in a domain:
- Create a local build user account (tfsbuilder) on the Team Foundation server.
- Add the tfsbuilder account to the Build Service TFS group for your project, this has to be done through Team Explorer on the TFS server since clients can't add local accounts to the TFS server.
- Create a local build user account (tfsbuilder) on the build server.
- Give the tfsbuilder account all required permissions. I'm not sure which they are but I added the user to the Power User group and this works.
- Change the logon account for the Team Build Service to you local tfsbuilder account also giving the user log on as service permission.
- Restart the team Build Service.
- Kick off a build from your client and things should work smoothly!
The same solution should work for all command line tools using the "run as" start method.
Tuesday 14 November, 2006 (.Net | AJAX | Blogging | Bugs | dasBlog | Fixes)
So far I have managed to get my dasBlog up and running. But in doing so I have disabled and broken several features:
- No HttpCompression
- No date picker while editing
- No Pingback/trackback support
It seems that I have also broken my FreeTextBox editing control. I believe that this may be an unrelated issue to the medium trust fixes and wont get into that in this post.
How could I get the broken features back up again? The strong naming issues that affect SharpZipLib and BasicDatePicker are easy to fix since there is a new free version of BasicDatePicker available BasicDatePicker Lite, the new version is not strong named and may require you to recompile dasBlog. SharpZipLib is open source so you can download it and add:
using System.Security;
[assembly:AllowPartiallyTrustedCallers]
to assemblyinfo.cs then just recompile and these functions should be up and running again, you may have to install SharpDevelop to compile the code for SharpZipLib. Any changes that were made to web.config or aspx pages to disable the functions need to be reverted and recompiled. Your web.config will need to be updated with a new version for SharpZipLib:
<
dependentAssembly>
<assemblyI entity name="ICSharpCode.SharpZipLib" publicKeyToken="1b03e6acf1164f73" culture="neutral"/>
<bindingReirect oldVersion="0.5.0.0-0.84.0.0" newVersion="0.85.0.0"/>
</dependentAssembly>
After doing this I received an "Invalid use of response filter" exception (more info at dasBlog.us) which turns out to be because my host already implements httpCompression, but disabling the blowery handler sorted it out.
TrackBack support
The main problems that remain are getting TrackBack and PingBack support. I will start by looking at getting TrackBacks working. The problem with TrackBacks is that they require dasBlog to call a web page on another site and network access to other servers is not allowed by default under medium trust so this jut won't work. I checked the TrackBack protocol to see if I could find any workarounds that could be applied. Reading the spec I realised that TrackBacks do not require the call to originate from the server that hosts the blog, if we could implement this as a client call then we could theoretically allow TrackBacks under medium trust.
I started by implementing a very simple html page to post a trackback call to localhost.
<
html><body>
<form method=post action=http://localhost/Trackback.aspx?guid=3d9f45e4... enctype="application/x-www-form-urlencoded;charset=utf-8">
<input type="hidden" name="title" value="SuperTrackback 1" />
<input type="hidden" name="excerpt" value="This is a vlient trackback call." />
<input type="hidden" name="url" value=http://localhost/Trackback.aspx?guid=dc205699... />
<input type="hidden" name="blog_name" value="TestBlogger" />
<input type=submit name="doit" value=1>
</form>
</body></html>
I have hardcoded the trackback urls just for testing. Of course it was not as easy as just posting the call since dasBlog includes spammer protection by checking the url in the trackback call. We have to disable spammer protection by checking if we can call the url at runtime in TrackBackHandler.cs (added lines are bold) .
Entry entry = dataService.GetEntry( entryId );
if ( entry != null )
{
System.Net.WebPermission urlPermission = new WebPermission(System.Net.NetworkAccess.Connect,url);
if(System.Security.SecurityManager.IsGranted(urlPermission))
{
try
{
string requestBody = null;
// see if this is a spammer
HttpWebRequest webRequest = WebRequest.Create(url) as HttpWebRequest;
webRequest.Method="GET";
webRequest.UserAgent = Utils.GetUserAgent();
...
...
}
catch
{
// trackback url is not even alive
logService.AddEvent(new EventDataItem(
EventCodes.TrackbackBlocked,
context.Request.UserHostAddress + " because the server did not return a valid response",
Utils.GetPermaLinkUrl(entryId),
url,
entry.Title
));
context.Response.StatusCode = 404;
context.Response.End();
return;
}
}
// if we've gotten this far, the trackback is real and valid
Tracking t = new Tracking();
t.PermaLink = url;
t.RefererBlogName = blog_name;
t.RefererExcerpt = excerpt;
This allows an anonymous caller to add a TrackBack to our blog but it also enables incoming TrackBacks under medium trust. This is only half of the solution for TrackBacks; we have opened up dasBlog för incoming calls to our TrackBackHandler but we still have to make calls to remote trackback urls. The next step would be to implement initiate a client-side trackback call to a remote server from inside dasBlog, this can be done in an AJAX (or is it Ajaxian) manner using XMLHttpRequest in JavaScript http://developer.mozilla.org/en/docs/AJAX:Getting_Started. I will cover this and tackling the spammer threat in future posts, since I haven't implemented a solution yet.
Tuesday 07 November, 2006 (.Net | Bugs | dasBlog | Fixes)
Since changeing web hosts I have not been able to get dasBlog running in the new environment. The host server is setup so that .Net code runs at medium trust level and won't allow me to override the trust settings. As anyone who has tried to get dasBlog to run at medium trust knows, it just isn't possible out of the box. To make life even more difficult Asp.Net returns an incomplete and ambiguous SecurityException:
Description:
The application attempted to perform an operation not allowed by the security policy. To grant this application the required permission please contact your system administrator or change the application's trust level in the configuration file.
Exception Details:
System.Security.SecurityException: Security error.
Source Error:
An unhandled exception was generated during the execution of the current web request. Information regarding the origin and location of the exception can be identified using the exception stack trace below.
|
The stack trace that is included provides no help in solving the problem and actually sent me on a wild goose chase trying to solve completely unrelated issues.
I have started to dig into this to try and see if I could find a quick fix for it with googles help. So far I haven't found a quick fix but I have found a few other things that may lead me to a solution... First of all I have seen a few forum posts and blogs referring to reflection used by serialization as part of the problem. But I have managed to get XmlSerialization to work without chainging the serializer or trust level of the application so it doesn't seem to be the XmlSerializer that is causing the exception. I changed the virtual directory settings on my local machine so that dasBlog runs under .Net 2, this provided me with a much clearer exception. dasBlog has a custom XmlTextReader called XmlNamespaceUpgradeReader which inherits fom XmlTextReader. The only problem is that XmlTextReader has a security demand for exicit inheritance permissions [PermissionSet(SecurityAction.InheritanceDemand, Unrestricted=true)]. Running under medium trust you don't have the required permissions. Changing all XmlNamespaceUpgradeReader references to XmlTextReader allowed the deserialization of SiteConfig (and all other serialized data) to run.
The next problem was that even though the site serialization was working dasBlog stilled just returned a big fat exception. Another wild goose chase followed trying to solve new unrelated issues, but working on them gave me a flashback to a problem I solved a year or so ago while setting up NGallery on the same host. Calling strong named assemblies from partially trusted code can also be a show stopper if the signed assemblies don't allow partially trusted callers. Two assemblies in dasBlog cause this problem SharpZipLib which is used for HttpCompression and BasicFrame BasicDatePicker, neither are compiled with the AllowPartiallyTrutedCallers setting. Removing references to these solves the rest of the problems that I was experiencing. Unfortunately the fixes disable some functionality in dasBlog and may have unexpected effects on configurations other than mine.
I am planning on following up on this post with detailed instructions on implementing the fixes and maybe som attempts to restore full functionality.
References on the web that sort of showed me in the right direction:
http://choirulamri.or.id/archives/94
http://www.hanselman.com/blog/CommentView.aspx?guid=a7e58fa0-9390-4270-bab3-83ea2e969352
http://www.hanselman.com/blog/CommentView.aspx?guid=4dd4573a-1fee-4680-b28e-983271bd3ae8
http://www.jwerx.com/blog/CommentView,guid,31c5f741-3d52-46a3-beb5-b934dea73423.aspx
http://dasblog.us/viewtopic.php?p=761&sid=b87a704cc1fffacabcb0bfff2660aac9
Friday 14 October, 2005 (.Net | Bugs | Fixes)
There seems to be a problem in how empty DataSets handle new rows in .Net 2, we received an exception with the message "DataTable internal index is corrupted".
Our realy simple solution is to call BeginLoadData before adding the new row and then EndLoadData afterwards. This fixed the problem for us, but the actual status of the bug can be found here:
http://lab.msdn.microsoft.com/productfeedback/viewfeedback.aspx?feedbackid=ecc665a5-d71a-4e08-ac42-f3c6c5d758e0
Thursday 11 August, 2005 (.Net | Bugs | Fixes)
I have been experiencing a lot of weird problems when running the Data Block from a Web service on a Windows 2003 server. Googling around the web a bit revealed that I am not the only person experience these exact problems. My main problem has been with the following message:
System.InvalidOperationException: Cannot open log for source 'Enterprise Library Data Service'.
You may not have write access.
I have tried all the proposed solutions with varying degrees of success most of the time the fix will work for a while or for a specific testing scenario but will stop working when the source changes. I think our problem is worsened by the fact that we are running everything through Visual Studio 2005 and Team Build with automated tests. Maybe the proposed solutions (installutil and registry permissions) would work when we go into production but I just don't feel confident that the system will run smoothly. As a last resort I have removed all the instrumentation stuff and recompiled it.
For anyone else who is searching for a resolution these are links to the sources I have used:
Tom Hollands blog about instrumentation in Enterprise Library:
http://blogs.msdn.com/tomholl/archive/2005/02/18/376187.aspx
Install util fix:
http://codebetter.com/blogs/eric.wise/archive/2005/03/21/60163.aspx
Give ASPNET user write access to the Enterprise Library logs:
http://objectsharp.com/blogs/bruce/archive/2003/11/03/180.aspx
Remove instrumentation:
http://dotnetjunkies.com/WebLog/sskokku/archive/2005/03/25/61376.aspx
The fixes didn't work for us in the automated build, perhaps it would work if i added a task to the MSBuild in Team Build that ran the installutil script after each compilation of the web site and set the right registry permissions but for now I am just going to go with disabled instrumentation. We aren't planning on using it but I know it could be good to have in the future!
Page 1 of 1 in the Bugs category
Disclaimer
The opinions expressed herein are my own personal opinions and do not represent
my employer's view in any way.
Sign In