Search code examples
asp.net-web-apiinternet-explorer-9http-postcors

CORS Post in IE9 fails


So I'm creating an application which uses CORS to communicate with a .NET MVC Sidecar project. Everything works great except for in IE9, where POST requests fail. I have a library which allows the GETs to work, but the POST requests are still having issues. It seems that IE9 strips out the contentType header. The server ends up interpreting this as appplication/octet-stream, as opposed to text/plain which is what I understand it's actually getting set by.

Inside of my WebAPIConfig.cs, I have the following function (called by Register):

private static void RegisterFormatters(HttpConfiguration config)
    {
        // enable browser viewing + jsonp
        config.Formatters.Add(new BrowserJsonFormatter());
        config.Formatters.Add(new JsonpMediaTypeFormatter(new BrowserJsonFormatter()));

        // prettify json: indented + camel case
        var json = config.Formatters.JsonFormatter;
        json.SerializerSettings.Formatting = Formatting.Indented;
        json.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();

        // Tell the formatter to accept text/plain
        config.Formatters.JsonFormatter.SupportedMediaTypes.Add(new MediaTypeHeaderValue("text/plain"));
        // When we use CORS on IE9, it strips off the content type. The server assigns it application/octet-stream
        config.Formatters.JsonFormatter.SupportedMediaTypes.Add(new MediaTypeHeaderValue("application/octet-stream"));
    }

However, Fiddler is still telling me that the requests don't have a contentType, and that the server can't handle a contentType of application/octet-stream.

Has anyone gotten this working?


Solution

  • I ended up fixing this by creating my own MediaTypeFormatter that worked with application/octet-stream. (My server was not accepting the calls because I hadn't done an IIS Reset (duh), but it still wasn't correctly parsing the objects.

    Here's the formatter I ended up using.

    public class OctetStreamMediaTypeFormatter : MediaTypeFormatter
    {
        public OctetStreamMediaTypeFormatter()
        {
            // We only support octet-stream
            SupportedMediaTypes.Add(new MediaTypeHeaderValue("application/octet-stream"));
        }
    
        public override Task<object> ReadFromStreamAsync(Type type, Stream readStream, HttpContent content, IFormatterLogger formatterLogger)
        {
            var task = new Task<object>(() =>
            {
                using (var reader = new StreamReader(readStream, Encoding.UTF8))
                {
                    // The data is passed as somethign identical to a query string (but not in the query string)
                    var dic = HttpUtility.ParseQueryString(reader.ReadToEnd());
                    var json = JsonConvert.SerializeObject(dic.AllKeys.ToDictionary(k =>
                    {
                        if (k.EndsWith("[]"))
                        {
                            return k.Substring(0, k.IndexOf("[]", StringComparison.OrdinalIgnoreCase));
                        }
                        else
                        {
                            return k;
                        }
                    }, k =>
                    {
                        var val = dic[k];
                        // We need to speciallly handle arrays
                        if (k.EndsWith("[]"))
                        {
                            // parse into separate values;
                            var values = val.Split(',');
                            val = values.Aggregate("[", (current, value) => current + ("'" + value + "',"));
                            if (val.EndsWith(","))
                            {
                                val = val.Substring(0, val.Length - 1);
                            }
                            val += "]";
                        }
                        return val;
                    }));
                    // It still puts it in as a string, which is not what we want, so we need to remove the quotes
                    json = json.Replace("\"[", "[").Replace("]\"", "]");
                    var obj = JsonConvert.DeserializeObject(json, type);
                    return obj;
                }
            });
    
            task.Start();
    
            return task;
        }
    
        public override bool CanReadType(Type type)
        {
            return true;
        }
    
        public override bool CanWriteType(Type type)
        {
            return true;
        }
    }