Cors, Web Api, IE8, Post Complex Data

Jako część mojego środowiska pracy musimy wspierać IE8, ale chcielibyśmy iść naprzód z technologią, w szczególności CORS.

Mam problem z wysyłaniem złożonych obiektów do usługi cors w ie8. Obiekt ma wartość NULL. Poniżej przedstawiono kroki, które należy wykonać. W razie potrzeby mogę przesłać projekt do github.

Stworzyłem nowy projekt mvc4. Dodano kontroler API. I wprowadził następujące zmiany.

Aby obsługiwać skomplikowane wywołania clight (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(); }
    }

Źródło:Obsługa żądań wstępnej weryfikacji CORS do akcji ASP.NET MVC

Aby obsługiwać tekst / zwykły (np8 wysyła tylko tekst / zwykły tekst z 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); 

        ...
    }

Kredyt:Publikowanie tekstu / zwykłego jako złożonego obiektu w WebAPI z CORS

Aby obsługiwać dodatkowe nazwy funkcji inne niż tylko czasowniki (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 }
        );

        ...
    }
Aby wspierać cors (web.config)
<httpProtocol>
   <customHeaders>
     <!-- cors -->
     <add name="Access-Control-Allow-Origin" value="*" />
     <add name="Access-Control-Allow-Headers" value="Content-Type" />
   </customHeaders>
</httpProtocol>
Kontroler API, nazwałem 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;
    }

To jest zakres zmian w usłudze. Więc teraz tworzę klienta. To także projekt mvc4. Całkiem podstawowe rzeczy tutaj.

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

Źródło:https://github.com/MoonScript/jQuery-ajaxTransport-XDomainRequest

Aby zadzwonić do usługi 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));
        });
    });

Jak wspomniałem wcześniej, wszystkie 3 połączenia zostały zakończone w ie8. Ale obiekt żądania w usłudze ma wartość null w ie8, aw firefoxie jest wypełniony, nawet jeśli wymuszam, aby typ zawartości był tekstem / zwykłym

Wyjście konsoli IE8:

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

Wyjście konsoli Firefox:

{"request":{"hasInt":1,"hasString":"u"},"stuff":["v","w","x"],"successful":true,"error":null}
Aktualizacja 25.09.2013

Mogę potwierdzić, że ciało jest wysyłane, ale nie jest analizowane przez API internetowe. Jeśli dodam następujący hack, zwróci dane zgodnie z oczekiwaniami. W firefox ciało będzie puste, a obiekt żądania wypełniony. W ie8 ciało nadal zawiera zawartość, a żądanie jest zerowe.

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

questionAnswers(2)

yourAnswerToTheQuestion