Cors, Web Api, IE8, Publicar Datos Complejos

Como parte de mi entorno de trabajo, necesitamos apoyar IE8, pero nos gustaría avanzar con la tecnología, específicamente CORS.

Tengo problemas para publicar objetos complejos en un servicio de cors en ie8. El objeto es nulo. A continuación se presentan los pasos para reproducir. Si es necesario puedo subir el proyecto a github.

He creado un nuevo proyecto mvc4. Agregado un controlador de API. Y realizó los siguientes cambios.

Para soportar llamadas a cors complejas de verificación previa (global.asax):
    protected void Application_BeginRequest()
    {
        //This is needed for the preflight message
        //https://stackoverflow.com/questions/13624386/handling-cors-preflight-requests-to-asp-net-mvc-actions
        if (Request.Headers.AllKeys.Contains("Origin") && Request.HttpMethod == "OPTIONS")  {  Response.Flush(); }
    }

Fuente:Manejo de solicitudes de verificación previa de CORS para acciones de ASP.NET MVC

Para admitir text / plain (ie8 solo envía text / plain con cors) (global.asax):
    protected void Application_Start()
    {
        //This is needed to support text/plain
        HttpConfiguration config = GlobalConfiguration.Configuration;
        config.Formatters.JsonFormatter.SupportedMediaTypes.Add(new MediaTypeHeaderValue("text/plain"));
        config.Formatters.Remove(config.Formatters.FormUrlEncodedFormatter);
        config.Formatters.Remove(config.Formatters.XmlFormatter); 

        ...
    }

Crédito:Publicación de texto / plano como un objeto complejo en WebAPI con CORS

Para admitir nombres de funciones adicionales que no sean solo verbos (put / post / etc) (WebApiConfig.cs) "
    public static void Register(HttpConfiguration config)
    {
        config.Routes.MapHttpRoute(
            name: "APICustom",
            routeTemplate: "api/{controller}/{action}/{id}",
            defaults: new { id = RouteParameter.Optional }
        );

        ...
    }
Para soportar cors (web.config)
<httpProtocol>
   <customHeaders>
     <!-- cors -->
     <add name="Access-Control-Allow-Origin" value="*" />
     <add name="Access-Control-Allow-Headers" value="Content-Type" />
   </customHeaders>
</httpProtocol>
Controlador API, llamé a PersonController.cs
 public class PersonController : ApiController
{

    public List<string> Get()
    {
        List<string> s = new List<string>();
        s.Add("s");
        s.Add("t");
        s.Add("u");
        return s;
    }



    [Serializable()]
    public class BaseReply
    {
        public bool successful = true;
        public string error;
    }
    [Serializable()]
    public class UpdateSomethingReply:  BaseReply
    {
        public UpdateSomethingRequest request;
        public List<string> stuff = new List<string>();
    }
    [Serializable()]
    public class UpdateSomethingRequest
    {
        public int hasInt;
        public string hasString;
    }
    //[FromBody] 
    [HttpPost]
    public UpdateSomethingReply UpdateSomething([FromBody] UpdateSomethingRequest request)
    {
        string body = Request.Content.ReadAsStringAsync().Result;
        UpdateSomethingReply reply = new UpdateSomethingReply();
        reply.request = request;

        reply.stuff.Add("v");
        reply.stuff.Add("w");
        reply.stuff.Add("x");
        return reply;
    }

Ese es el alcance de los cambios en el servicio. Entonces a continuación creo un cliente. Este es también un proyecto mvc4. Cosas bastante básicas aquí.

Para polyfill ie8 con cors (index.cshtml):
<script src="~/Scripts/jQuery.XDomainRequest.js"></script>

Fuente:https://github.com/MoonScript/jQuery-ajaxTransport-XDomainRequest

Para llamar al servicio de cors.
 $(document).ready(function () {
        $.when(
          $.ajax({
              url: urls.person.UpdateSomething,
              type: 'post',
              contentType: "application/json; charset=utf-8",
              dataType: 'json',
              data: JSON.stringify({
                  hasInt: 1,
                  hasString: "u"
              })
          })
        )
        .fail(function (jqXHR, textStatus, errorThrown) {
        })
        .done(function (data) {
            console.log(JSON.stringify(data));
        });

        $.when(
          $.ajax({
              url: urls.person.Get,
              dataType: 'json'
          })
        )
        .fail(function (jqXHR, textStatus, errorThrown) {
        })
        .done(function (data) {
            console.log(JSON.stringify(data));
        });

        $.when(
          $.ajax({
              url: urls.person.UpdateSomething,
              type: 'post',
              contentType: "text/plain",
              dataType: 'json',
              data: JSON.stringify({
                  hasInt: 1,
                  hasString: "u"
              })
          })
        )
        .fail(function (jqXHR, textStatus, errorThrown) {
        })
        .done(function (data) {
            console.log(JSON.stringify(data));
        });
    });

Como dije anteriormente, las 3 llamadas se completaron en ie8. Pero el objeto de solicitud en el servicio es nulo en ie8 y en firefox se llena, incluso cuando fuerzo que el tipo de contenido sea texto / sin formato

Salida de la consola IE8:

{"request":null,"stuff":["v","w","x"],"successful":true,"error":null}

Salida de la consola de Firefox:

{"request":{"hasInt":1,"hasString":"u"},"stuff":["v","w","x"],"successful":true,"error":null}
Actualizacion 25/09/2013

Puedo confirmar que el cuerpo se está enviando, pero no está siendo analizado por la API web. Si agrego el siguiente truco, devolverá los datos como se esperaba. En Firefox, el cuerpo estará vacío y el objeto de solicitud se rellenará. En ie8 el cuerpo aún contiene los contenidos y la solicitud es nula.

    [HttpPost]
    public UpdateSomethingReply UpdateSomething(UpdateSomethingRequest request)
    {
        if (request == null && Request.Content.ReadAsStringAsync().Result !="")
        {
            request = JsonConvert.DeserializeObject<UpdateSomethingRequest>(Request.Content.ReadAsStringAsync().Result);
       }

        UpdateSomethingReply reply = new UpdateSomethingReply();
        reply.request = request;
        reply.body=Request.Content.ReadAsStringAsync().Result;
        reply.headers = Request.Headers.ToString();
        reply.stuff.Add("v");
        reply.stuff.Add("w");
        reply.stuff.Add("x");
        return reply;
    }

Respuestas a la pregunta(2)

Su respuesta a la pregunta