/ Silverlight

Silverlight 5 + Internet Explorer 9 using old Content-Type from POST in a subsequent GET

We've been running into a super annoying problem at work. After our Silverlight application makes it's login POST the next GET that we send fails with a NotFoundException. This only happens when using the Silverlight 5 runtime and only happens in Internet Explorer 9. I have tested now with Silverlight 4 as well as Chrome, Firefox, Opera and Safari, and IE9/SL5 is the only bad combination.

Here are the headers of our login POST:

POST /login HTTP/1.1
Accept: application/xml
Referer: http://localhost:8080/censored.xap?timestamp=1326148328000
Accept-Language: en-CA
Content-Length: 38
Content-Type: application/x-www-form-urlencoded
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0)
Host: localhost:8080
Connection: Keep-Alive
Pragma: no-cache
Cookie: JSESSIONID=DEFEAFD35E9B067A79F772C166937750

Here are the headers of our next GET:

GET /user/current HTTP/1.1
Accept: application/xml
Referer: http://localhost:8080/censored.xap?timestamp=1326148328000
Accept-Language: en-CA
Content-Length: 38
Content-Type: application/x-www-form-urlencoded
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; 	Trident/5.0)
Host: localhost:8080
Proxy-Connection: Keep-Alive
Pragma: no-cache
Cookie: JSESSIONID=5C57C93458E80E5975470F703B4A483C

Notice that the Content-Type and Content-Length are identical, even though:

  • You aren't allowed to use Content-Type or Content-Length on a GET
  • The content length is actually different in the GET request so it's obviously the old value

Here is a sample solution that demonstrates the issue.

Silverlight client:

using System.IO;
using System.Net;
using System.Net.Browser;
using System.Windows.Controls;

namespace NetworkTest
{
public partial class MainPage : UserControl
{
    public MainPage()
    {
        InitializeComponent();
        HttpWebRequest request = (HttpWebRequest)WebRequestCreator.BrowserHttp.Create(new Uri("http://localhost:59050/Home/Login"));
        request.Method = "POST";
        request.ContentType = "application/x-www-form-urlencoded";
        request.BeginGetRequestStream(result =>
            {
                var rq = result.AsyncState as HttpWebRequest;

                using (var stream = rq.EndGetRequestStream(result))
                {
                    StreamWriter writer = new StreamWriter(stream);
                    writer.WriteLine("username=test&password=test");
                    writer.Flush();
                    writer.Close();
                }

                rq.BeginGetResponse(
                    r =>
                    {
                        try
                        {
                            rq.EndGetResponse(r);
                        }
                        catch
                        {
                        }
                    }, rq);
            }, request);
    	}
	}
}

Server code:

using System.Web.Mvc;

namespace TestServer.Controllers
{
	public class HomeController : Controller
	{
    	public ActionResult Index()
    	{
        	return View();
    	}

    	[HttpPost]
        public ActionResult Login(string test)
	    {
    	    return RedirectToAction("Index");
    	}
	}
}

Basically the Silverlight client makes a POST to the login page which redirects back to the index page. The index page GET still contains the Content-Type and Content-Length fields from the login POST and so it fails. This works just fine in Chrome. It also only happens with BrowserHttp. ClientHttp works fine but isn't an option at work because we're using cookie authentication and so we need the browser to make the requests.

Anyone else running into this?