ASP.NET ASMX Services mit Windows 8 Store APP

In meiner aktuellen Windows Developer Schulung wollte ich einen ASP.NET Webservice aufrufen. Dabei sollte per JSON und nicht per SOAP gearbeitet werden. Was in JavaScript ganz einfach geht, hat eine kleine Überraschung für mich bereit gehalten. Regelmäßige Leser meines Blogs werden erkennen mit C# und nicht VB.net.

ASP.NET Web Services gibt es seit der Version 1. Seit einiger Zeit kann man damit auch Json generieren und seit mir nicht bekannter Zeit in einem ganz speziellen Format.

Der Service nutzt die Northwind Customers Tabelle per EF.

   1:    [ScriptService]
   2:      public class WebService1 : System.Web.Services.WebService
   3:      {
   4:          [ScriptMethod(ResponseFormat = ResponseFormat.Json)]
   5:          [WebMethod]
   6:          public List<Customers> Kunden()
   7:          {
   8:              var nw = new NorthwindEntities2();
   9:              return nw.Customers.ToList();
  10:             
  11:          }
  12:      }

Für den Aufruf des Services gibt man die url mit Methodennamen an also webservice1.asmx/Kunden. Dabei muss aber beim Request im HTTP Header der Content Type application/json angeben sein. Um den Service zu testen kann man Fiddler verwenden.

image

ASMX Services akzeptieren seit einiger Zeit nur ein HTTP Post. Wenn man das ändern möchte kann man im Methode Attribut WebMethod des Services dies angeben.

Der JSON Repsonse hat allerdings am Anfang ein d: im Stream.

image

Das ist kein Zufall sondern Absicht um ein bestimmtes XSS Problem zu umgehen. Jedenfalls kann so nicht direkt mit DataContractJSONSerializer deserialsiert werden. Man könnte nun den String Parsen und damit anpassen, ich wähle allerdings JSON.NET weil der Code damit logischer erscheint.

Um Die Datenklasse im Windows 8 Store APP (also METRO oder WinRT) zu erzeugen kopiere ich den Json Source komplett in die Zwischenablage (hier nur ein Auszug)

   1:  {"d":[{"__type":"WebApplication1.Customers","Customer_ID":"ALFKI","Company_Name":"Alfreds 
Futterkiste"
,"Contact_Name":"Maria Anders","Contact_Title":"Sales Representative",
"Address":"Obere Str. 57","City":"Berlin","Region":null,"Postal_Code":"12209","Country":"Germany",
"Phone":"030-0074321","Fax":"030-0076545","EntityState":2,"EntityKey":{"EntitySetName":"Customers",
"EntityContainerName":"NorthwindEntities2","EntityKeyValues":[{"Key":"Customer_ID","Value":"ALFKI"}],
"IsTemporary":false}},{"__type":"WebApplication1.Customers","Customer_ID":"ANATR",
"Company_Name":"Ana Trujillo Emparedados y helados","Contact_Name":"Ana Trujillo"
,"Contact_Title":"Owner","Address":"Avda. de la Constitución 2222","City":"México D.F.",
"Region":null,"Postal_Code":"05021","Country":"Mexico","Phone":"(5) 555-4729",
"Fax":"(5) 555-3745","EntityState":2,"EntityKey":{"EntitySetName":"Customers",
"EntityContainerName":"NorthwindEntities2","EntityKeyValues":[{"Key":"Customer_ID","Value":"ANATR"}],
"IsTemporary":false}},{"__type":"WebApplication1.Customers","Customer_ID":"ANTON",
"Company_Name":"Antonio Moreno Taquería","Contact_Name":"Antonio Moreno",
"Contact_Title":"Owner","Address":"Mataderos 2312","City":"México D.F.","Region":null,"

Wenn man den  Code schon in der Zwischenablage hat, kann man auch per Visual Studio Paste JSON as Class die Klasse erzeugen lassen.

image

Um den Traffic belauschen zu können habe ich fiddler zwischengeschaltet. Dann muss der Webservice im Code mit der speziellen Fiddler Adresse angesprochen werden. Dann per httpclient ein Post auslösen.

Das D wird als JsonObject extrahiert und daraus dann einen Liste erstellt.

   1:    private async void Button_Click(object sender, RoutedEventArgs e)
   2:          {
   3:              var http = new HttpClient();
   4:              HttpContent cnt = new StringContent("");
   5:              cnt.Headers.ContentType = new MediaTypeHeaderValue("application/json");
   6:              var r = await http.PostAsync(
new Uri("http://localhost.fiddler:26826/WebService1.asmx/Kunden", UriKind.Absolute), cnt);
   7:              var js = await r.Content.ReadAsStringAsync();
   8:              JObject jsonobj = (JObject)JsonConvert.DeserializeObject(js);
   9:              var x = JsonConvert.DeserializeObject<List<Customers>>(jsonobj["d"].ToString());
  10:              grid1.ItemsSource = x.ToList();
  11:          }
Kommentare sind geschlossen