2012-05-03 38 views
12

Brakuje mi sztuczki z nowym webapi - próbuję przesłać łańcuch xml za pośrednictwem żądania postu i nie mając dużo szczęścia.ASP.NET MVC4 WebAPI i publikowanie danych XML

Czo używa jQuery tak:

$(document = function() { 
    $("#buttonTestAPI").click(function() { 

     var d = " <customer><customer_id>1234</customer_id></customer>"; 
     $.ajax({ 
      type: 'POST', 
      contentType: "text/xml", 
      url: "@Url.Content("~/api/Customer/")", 
      data: d, 
      success: function (result) { 
       var str = result; 
       $("#output").html(str); 
      } 
     }); 
    }); 
}); 

Moje kontroler jest bardzo prosty w tej chwili - tylko domyślny dla akcji post - próbuje wrócić co zostało przekazane w:

public string Post(string value) 
    { 
     return value; 
    } 

Jednak "wartość" jest wielokrotnie zerowa. Najdziwniejsze jest to, kiedy zmienić moje dane w jQuery być coś takiego:

d = "<customer_id>1234</customer_id>"; 

Potem dostać „wartość” w moim kontrolera jak 1234.

Jak mogę uzyskać dostęp do bardziej złożony ciąg xml w moim kontrolerze?

Odpowiedz

13

Wysyłasz typ zawartości text/xml, ale zdefiniowałeś swój parametr jako string. Najlepiej byłoby, gdyby Twój plik XML był mapowany na dla klasy, aby mógł być odserializowany.

Więc jeśli potrzebujesz raw xml to nie jest to jeszcze obsługiwane. Web API jest obecnie nastawiony na serializację MediaTypeFormatters i brakujące formatery proste, ale można je łatwo zbudować.

Ten jest minimalny realizacja takiego formater oporowe odczytać tylko w Twoim przypadku i na podstawie beta instalatora (a nie nightly kodu źródłowego, ponieważ znacznie się zmieniła):

public class TextMediaTypeFormatter : MediaTypeFormatter 
{ 
    public TextMediaTypeFormatter() 
    { 
     SupportedMediaTypes.Add(new MediaTypeHeaderValue("text/xml")); 
     SupportedMediaTypes.Add(new MediaTypeHeaderValue("text/plain")); 
     SupportedMediaTypes.Add(new MediaTypeHeaderValue("text/javascript")); 
    } 

    protected override bool CanReadType(Type type) 
    { 
     return type == typeof (string); 
    } 

    protected override System.Threading.Tasks.Task<object> OnReadFromStreamAsync(Type type, Stream stream, 
     HttpContentHeaders contentHeaders, 
     FormatterContext formatterContext) 
    { 
     var taskCompletionSource = new TaskCompletionSource<object>(); 
     try 
     { 
      var memoryStream = new MemoryStream(); 
      stream.CopyTo(memoryStream); 
      var s = System.Text.Encoding.UTF8.GetString(memoryStream.ToArray()); 
      taskCompletionSource.SetResult(s); 
     } 
     catch (Exception e) 
     { 
      taskCompletionSource.SetException(e);   
     } 
     return taskCompletionSource.Task; 
    } 
} 

I z niego skorzystać, wystarczy dodać go do kolekcji formatujących:

GlobalConfiguration.Configuration.Formatters.Insert(0, new TextMediaTypeFormatter()); 
+0

Możesz uprościć czytanie strumienia za pomocą '' czytelnika var = nowego StreamReadera (readStream); var text = poczekaj na odczyt.ReadToEndAsync(); '' ' –

6

Kto szuka zaktualizowanej wersji odpowiedzi Aliostad w powyższym od wersji beta do RC aplikacji asp.net mvc 4 web api (niewielkie zmiany zaowocowały dla mnie niewielką poprawką).

public class TextMediaTypeFormatter : MediaTypeFormatter 
{ 

    public TextMediaTypeFormatter() 
    { 
     SupportedMediaTypes.Add(new MediaTypeHeaderValue("text/xml")); 
     SupportedMediaTypes.Add(new MediaTypeHeaderValue("text/plain")); 
     SupportedMediaTypes.Add(new MediaTypeHeaderValue("text/javascript")); 
    } 

    public override bool CanReadType(Type type) 
    { 
     if (type == typeof(String)) 
      return true; 
     else 
      return false; 
    } 

    public override bool CanWriteType(Type type) 
    { 
     if (type == typeof(String)) 
      return true; 
     else 
      return false; 

    } 

    public override Task<object> ReadFromStreamAsync(Type type, Stream readStream, System.Net.Http.HttpContent content, IFormatterLogger formatterLogger) 
    { 
     var taskCompletionSource = new TaskCompletionSource<object>(); 
     try 
     { 
      var memoryStream = new MemoryStream(); 
      readStream.CopyTo(memoryStream); 
      var s = System.Text.Encoding.UTF8.GetString(memoryStream.ToArray()); 
      taskCompletionSource.SetResult(s); 
     } 
     catch (Exception e) 
     { 
      taskCompletionSource.SetException(e); 
     } 
     return taskCompletionSource.Task; 
    } 
} 
+0

czy mogę porozmawiać z Tobą na czacie? – medBo

18

Poniższa pozwoli Ci odczytać surowego wiadomość XML za pomocą metody POST do Web API:

public void PostRawXMLMessage(HttpRequestMessage request) 
{ 
    var xmlDoc = new XmlDocument(); 
    xmlDoc.Load(request.Content.ReadAsStreamAsync().Result); 
} 

można debugować i kontrolować ciało, nagłówki, itd i ujrzy opublikowany surowy XML. Użyłem Fiddler's Composer do utworzenia HTTP POST i działa to dobrze.

+0

Dokładnie tego, czego szukałem! Wielkie dzięki !!! – MissRaphie

0

co rozwiązało problem dla mnie było to, dodając:

static SubscriberController() 
{ 
    //Needed for xml deserialization to work 
    var xml = GlobalConfiguration.Configuration.Formatters.XmlFormatter; 
    xml.UseXmlSerializer = true; 
} 

(SubscriberController jest moja klasa, która rozciąga ApiController, a powyżej jest statyczny konstruktor, więc to będzie działać raz).

Nie wiem, czy to również konieczne, ale I dodaje atrybut [FromBody] do mojego parametru, tak jak poniżej:

public async Task<HttpResponseMessage> SynchronizeImax([FromBody] SynchronizeRequest synchronizeRequest) 
{ 
    //... 
} 

Wspaniałą rzeczą robią to w ten sposób, że można bezproblemowo obsługiwać zarówno XML i wejście JSON .