воскресенье, 14 ноября 2010 г.

Client HTTP Stack: HttpWebRequest and non-ASCII characters in HTTP response headers

Client HTTP Stack in Silverlight seems to bee too strict sometimes. I have an OOB application that uses HttpWebRequest object to get data from external web service.

Unfortunately, HTTP response from the service includes header that contains non-ASCII characters. And it turns out to be a problem. See code snippet below:

void GetResponseCallback(IAsyncResult ar) {
    HttpWebRequest request = (HttpWebRequest)ar.AsyncState;
    WebResponse response = request.EndGetResponse(ar);
    // code continues …
}

EndGetResponse() call results in System.ArgumentException: Specified value has invalid Control characters. Parameter name: value.

I’m not sure whether it is a bug or designed behaviour. But it’s a pity that invalid header prevents application from obtaining response at all. In fact I don’t even need that header, so my workaround was to switch to browser http handling so that I can move on.

And just for the record: the same code works fine in WPF application.

среда, 10 ноября 2010 г.

Silverlight OOB applications and HTTP handling

With Silverlight, you can specify whether the browser or the client provides HTTP handling for your Silverlight-based applications. By default, HTTP handling is performed by the browser and you must opt-in to client HTTP handling.

Surprisingly, despite of what your intuition might suggest, Silverlight out of browser applications use browser HTTP handling by default. At least for WCF service calls :)

вторник, 22 июня 2010 г.

WinDbg: dumping the target object of a WeakReference

The following example demonstrates how to dump the target object of a WeakReference.

1. Find WeakReference’s object address. In my example it is 0bb9a878.

2. Use !dumpobj to print content of the WeakReference:

0:025> !dumpobj 0bb9a878
Name:        System.WeakReference
MethodTable: 5ec0d7ec
EEClass:     5e7eacd8
Size:        16(0x10) bytes
File:        C:\Program Files\Microsoft Silverlight\4.0.50524.0\mscorlib.dll
Fields:
      MT    Field   Offset                 Type VT     Attr    Value Name
5ec0c5a0  4000522        4        System.IntPtr  1 instance  7631528 m_handle
5ec007e4  4000523        8       System.Boolean  1 instance        0 m_IsLongReference

3. The m_handle member is a pointer to the target object. The member is value type (System.IntPtr), so we use !dumpvc command to print its content:

0:025> !dumpvc 5ec0c5a0 7631528
Name:        System.IntPtr
MethodTable: 5ec0c5a0
EEClass:     5e7e9f00
Size:        12(0xc) bytes
File:        C:\Program Files\Microsoft Silverlight\4.0.50524.0\mscorlib.dll
Fields:
      MT    Field   Offset                 Type VT     Attr    Value Name
5ec0d720  4000353        0                  PTR  0 instance 0bb9a86c m_value
5ec0c5a0  4000354      50c        System.IntPtr  1   shared   static Zero
    >> Domain:Value  0b670f20:NotInit  0b675a40:NotInit  <<

4. The address of the target object is 0bb9a86c. Now we can use !dumpobj command to print it:

0:025> !dumpobj 0bb9a86c
Name:        HelloSl.FooBar
MethodTable: 07625428
EEClass:     07621cd8
Size:        12(0xc) bytes
File:        HelloSl, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
Fields:
None

среда, 16 июня 2010 г.

Debugging Silverlight 4 application with Visual Studio 2010 and Google Chrome

Debugging Silverlight application on a system with Google Chrome installed as default browser, I run into an issue: breakpoints were not hit. I got the message: “The breakpoint will not currently be hit. No symbols have been loaded for this document”.

BreakpointWillNotBeHit

What happens? It looks like Visual Studio 2010 doesn’t play well with Chrome browser.

When Silverlight application is started for debugging, Visual Studio launches web browser and attaches debugger to it. Chrome runs in multiple processes (process per tab?) and most of the time Visual Studio attaches debugger to the wrong process, the process that doesn’t host Silverlight application. That’s why symbols are not loaded and breakpoints are disabled.

The only workaround I know at the moment is to manually attach the debugger to correct chrome.exe process, the one that hosts the application being debugged.

Step-by-step illustration.

1. Create Silverlight application, start debugging.

Processes

Notice that the debugger is attached to the chrome.exe with PID=4132 and breakpoint is disabled.

2. At the same time Process Explorer displays that there are two another chrome.exe processes running: 5816 and 3876.

ProcessExplorer 

3. In Visual Studio open “Attach to Process” dialog:

ManualAttachTo

Notice that chrome.exe process with PID=3876 has “Silverlight” in the “Type” column. Select it and press “Attach” button.

Voila: debugger output prints “'chrome.exe' (Silverlight): Loaded 'AgDemo', Symbols loaded.”, and breakpoints are resolved.

Sure, manually attaching debugger is not convenient. This is just a workaround – I’m looking forward for better solution.

DispatcherTimer memory leak in Silverlight 4

A colleague of mine found what seems to be a bug in Silverlight 4. Once started, DispatcherTimer object is never garbage collected. The following code snippet demonstrates the issue:

public partial class MainPage : UserControl {
    public MainPage() {
        InitializeComponent();
    }
 
    private void start_Click(object sender, RoutedEventArgs e) {
        DispatcherTimer timer = new DispatcherTimer();
        timer.Interval = TimeSpan.FromSeconds(1);
        timer.Tick += timer_Tick;
        timer.Start();
    }
 
    void timer_Tick(object sender, EventArgs e) {
        DispatcherTimer timer = (DispatcherTimer)sender;
        timer.Stop();
        timer.Tick -= timer_Tick;
    }
}
 
Start application, attach WinDbg. Initially there is no DispatcherTimer object instances:

0:028> !dumpheap -type DispatcherTimer
Address       MT     Size
total 0 objects
Statistics:
      MT    Count    TotalSize Class Name
Total 0 objects

Then click “Start” button. Wait a couple of seconds – the timer object fires, stops and unsubscribes from event handler. Now break into the debugger once again:

0:003> !dumpheap -type DispatcherTimer
Address       MT     Size
08ff5df8 629c4ba0       20    
total 0 objects
Statistics:
      MT    Count    TotalSize Class Name
629c4ba0        1           20 System.Windows.Threading.DispatcherTimer
Total 1 objects
0:003> !gcroot -nostacks 08ff5df8
DOMAIN(07F1AE30):HANDLE(Pinned):43b12f8:Root:  09f74260(System.Object[])->
  08fa5f64(System.Collections.Generic.Dictionary`2[[System.IntPtr, mscorlib],[System.Object, mscorlib]])->
  08feafc4(System.Collections.Generic.Dictionary`2+Entry[[System.IntPtr, mscorlib],[System.Object, mscorlib]][])->
  08ff5df8(System.Windows.Threading.DispatcherTimer)

As you can see, the timer object is “rooted” in Dictionary entry and it will prevent it from being garbage collected.

Random thoughts, ideas and questions on .NET development

Постоянные читатели