Here’s an addendum to my previous LogParser collection of scripts: how can we filter our IIS logs folder to extract only the events happened in a certain time range?
logparser "select * into 27.5.log from med*.log where to_timestamp(date,time) between timestamp('2008/05/27 10:11:00', 'yyyy/MM/dd hh:mm:ss') and timestamp('2008/05/27 10:13:00', 'yyyy/MM/dd hh:mm:ss')" -i:iisw3c -o:nat -rtp:-1
Note I’m using the to_timestamp conversion to combine date and time fields from the IIS log and compare to the date range I’m interested in.
Carlo
Quick hint for today: how do you switch the thread you’re examining in Windbg? If you know the thread number you can type the command ~<thread number>s (e.g. ~21s to switch to thread 21).
But what about if you only know the ThreadID (which is an hexadecimal value)? For example if you examine the output of the !lock command:
0:000> !locks CritSec mscorwks!ThreadpoolMgr::WorkerCriticalSection+0 at 7a393800 WaiterWoken No LockCount 21 RecursionCount 1 OwningThread 26a0 EntryCount 0 ContentionCount 15 *** Locked
What thread is 26a0? Well… you can display all available threads (with the managed !sos.threads command or the native ~ [tilde] command) and then manually look for the ID, or use the following:
0:000> ~~[26a0]s eax=000057b4 ebx=00000000 ecx=79f40a2b edx=18926823 esi=000e194c edi=000006c4 eip=7c82ed54 esp=02d2fbf0 ebp=02d2fc2c iopl=0 nv up ei pl zr na pe nc cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000246 ntdll!KiFastSystemCallRet: 7c82ed54 c3 ret
~~[<threadID>]s (e.g. ~~[26a0]s), and with the sample above Windbg will switch to thread 21
There are a variety of web applications out there which are relying on http headers for different purposes: automatic redirection, streaming a binary file to the client, controlling how content is cached on the client, adapting the site’s functionalities and interface to the capabilities of the browse and a lot more I’m sure you can think to.
If you’re upgrading to ASP.NET 2.0 (or higher) an existing application which relies on http headers, you might encounter some problems, especially in the case you’re producing binary context (say a PDF file) to your clients: corrupted file, or type not supported, or inability to print the downloaded document are some of the symptoms you may get.
First, check your code if you have something like the following:
Response.ContentType = "application/pdf"; Response.AppendHeader("Content-Disposition", "attachment; filename=document.pdf"); Response.AddHeader("Content-Length", m.GetBuffer().Length.ToString()); ObjPdf writer = ObjPdf.getInstance(document, m); document.Open();
Try changing it to this:
Response.ContentType = "application/pdf"; Response.AppendHeader("Content-Disposition", "attachment; filename=document.pdf"); ObjPdf writer = ObjPdf.getInstance(document, m); document.Open(); Response.AddHeader("Content-Length", m.GetBuffer().Length.ToString());
If m.GetByffer().Length is zero then you have a problem, so it’s important to open the writer object before adding the header.
If that’s enough or you don’t want to change your code (maybe because too many pages are affected) then you can change your web.config:
<configuration> <system.net> <settings> <httpWebRequest useUnsafeHeaderParsing=”true” /> </settings> </system.net> </configuration>
The useUnsafeHeaderParsing config option will relax the header parsing so that headers do not have to strictly follow the standard described in the HTTP RFC. This option has been added for backwards compatibility, because the header parsing has been hanged to be very strict. Unfortunately a fair number of servers do not correctly follow the RFC, so clients using these servers will probably break due to this change. However, not using strict header parsing is a security risk, because malicious servers could send the client malformed headers which the client will then handle incorrectly. If you don't use the config option to turn off the strict parsing you probably won't get the server protocol error, but you open up the client to attack. The best solution is to try and get the server fixed.
When this property is set to false, the following validations are performed during HTTP parsing:
When a protocol violation occurs, a WebException exception is thrown with the status set to ServerProtocolViolation. If the UseUnsafeHeaderParsing property is set to true, validation errors are ignored. Setting this property to true has security implications, so it should only be done if backward compatibility with a server is required.
I saw this error twice recently, but as often happens for two completely different cases so here they are, hope it helps someone to same their time…
Invalid postback or callback argument. Event validation is enabled using <pages enableEventValidation="true"/> in configuration or <%@ Page EnableEventValidation="true" %> in a page. For security purposes, this feature verifies that arguments to postback or callback events originate from the server control that originally rendered them. If the data is valid and expected, use the ClientScriptManager.RegisterForEventValidation method in order to register the postback or callback data for validation
The first problematic application was dynamically building page layout and manipulating the HTML stream sent to the client; in my specific case there was some manipulation carried on the client through Javascript, but I think the same may happen if for example the HTML stream is changed through an HttpHandler after the main ASP.NET processing has been completed. The page was rendered correctly within the browser, but a postback thrown the exception above and this was due to a malformed page structure, where we had nested <form> tags like in the following example:
<body> <form id="form1" runat="server"> <div> <asp:Button ID="Button1" runat="server" Text="Button" /> <form></form> </div> </form> </body>
There was a bug in the page, so the solution is to fix it to avoid the nested <fom> tags.
Here we had a DataGrid and on the ItemCreated event the customer was calling Item.Attributes.Add() to add a call to __DoPostBack() and have an automatic postback when a record was selected; needless to say, the postback attempt returned the error at the beginning of the post.
The customer had defined a “Select” column with a button to actually select the row within the DataGrid and set the Visible property of this button to false; ASP.NET renders the button to select the record as a LinkButton. This also emits the __DoPostBack() javascript method and registers it for event validation calling ClientScript.RegisterForEventValidation(); as you can imagine, if the control is not visible (i.e. Visible=”false”) the control is not rendered and therefore is not registered for event validation. But the DataGrid uses that event anyway, which ultimately throws the error.
The solution in this case is to manually register each row for event validation with code similar to the following:
protected override void Render(HtmlTextWriter writer) { foreach (DataGridItem row in DataGrid1.Items) ClientScript.RegisterForEventValidation(row.UniqueID.ToString() + ":_ctl0"); base.Render(writer); }
The event validation must be registered within the Render() method of the page.
Also note that there could be different degrees of added complexity to this scenario: for example if the name of the control causing the postback is built dynamically and maybe the application has been migrated from ASP.NET 1.1 to 2.0, you have to be aware that the naming convention for dynamic controls has changed. ASP.NET 1.1 uses DataGrid1$_ctl2$_ctl0 while ASP.NET 2.0 uses DataGrid1$ctl02$ctl00. It is possible to control this behavior setting xhtmlConformance=”Legacy” (see xhtmlConformance); however note that reverting back to Legacy mode causes ASP.NET 2.0 to use a column (“:”) sign in control names for event validation, instead of the dollar sign (“$”) which uses for rendering.