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?
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;
}
}