2012-04-04 7 views
6

Im Versuch, ein Bild von einem WCF Rest-Service zu erhalten, wie so:body Parameter 'Breite'. GET-Operationen können keinen Körper haben?

[ServiceContract] 
public interface IReceiveData 
{ 
    [OperationContract] 
    [WebInvoke(Method = "GET", BodyStyle = WebMessageBodyStyle.Bare, ResponseFormat = WebMessageFormat.Xml, UriTemplate = "picture/")] 
    //this line is wrong though 
    Stream GetImage(int width, int height); 
} 
public class RawDataService : IReceiveData 
{ 
    public Stream GetImage(int width, int height) 
    { 
     // Although this method returns a jpeg, it can be 
     // modified to return any data you want within the stream 
     Bitmap bitmap = new Bitmap(width, height); 
     for (int i = 0; i < bitmap.Width; i++) 
     { 
      for (int j = 0; j < bitmap.Height; j++) 
      { 
       bitmap.SetPixel(i, j, (Math.Abs(i - j) < 2) ? Color.Blue : Color.Yellow); 
      } 
     } 
     MemoryStream ms = new MemoryStream(); 
     bitmap.Save(ms, System.Drawing.Imaging.ImageFormat.Jpeg); 
     ms.Position = 0; 
     WebOperationContext.Current.OutgoingResponse.ContentType = "image/jpeg"; 
     return ms; 
    } 
} 

In meiner Host-Anwendung:

class Program 
    { 
     static void Main(string[] args) 
     { 
      string baseAddress = "http://" + Environment.MachineName + ":8000/Service"; 
      ServiceHost host = new ServiceHost(typeof(RawDataService), new Uri(baseAddress)); 
      host.AddServiceEndpoint(typeof(IReceiveData), new WebHttpBinding(), "").Behaviors.Add(new WebHttpBehavior()); 
      host.Open(); // this line 
      Console.WriteLine("Host opened"); 
      Console.ReadLine(); 

ich diesen Fehler:

Operation 'GetImage' in contract 'IReceiveData' uses GET, but also has body parameter 'width'. GET operations cannot have a body. Either make the parameter 'width' a UriTemplate parameter, or switch from WebGetAttribute to WebInvokeAttribute.

Ich bin nicht sicher wie Sie die webinvoke/UriTemplate-Methode für ein Bild festlegen oder wie Sie ein Bild erhalten und es zurückgeben. Kann jemand in diesem Beispiel den korrekten Weg zum Anzeigen eines Bildes posten?

EDIT

Wenn ich die unten Antwort versuchen und UriTemplate = "picture?w={width}&h={height}" als meine UriTemplate verwenden, wenn zu http://www.localhost.com:8000/Service/picture?width=50&height=40 Navigation erhalte ich einen Fehler in meinem Code:

public Stream GetImage(int width, int height) 
     { 
      Bitmap bitmap = new Bitmap(width, height); // this line 
      for (int i = 0; i < bitmap.Width; i++) 
      { 
       for (int j = 0; j < bitmap.Height; j++) 
       { 
        bitmap.SetPixel(i, j, (Math.Abs(i - j) < 2) ? Color.Blue : Color.Yellow); 
       } 
      } 
      MemoryStream ms = new MemoryStream(); 
      bitmap.Save(ms, System.Drawing.Imaging.ImageFormat.Jpeg); 
      ms.Position = 0; 
      WebOperationContext.Current.OutgoingResponse.ContentType = "image/jpeg"; 
      return ms; 
     } 

Welche ArguementException was unhandled by user code:Parameter besagt, ist nicht gültig .

Antwort

11

In den Attributen müssen Sie der Laufzeit mitteilen, dass Sie die Breite und Höhe als URL-Parameter erwarten.

Momentan wird in der Laufzeit davon ausgegangen, dass Sie die URL ohne Parameter aufrufen, aber die Methode heißt Parameter erwartet, sodass die Laufzeit nicht weiß, wie die Werte für Ihre Methode für width und height.

Dies kann

[WebInvoke(Method = "GET", BodyStyle = WebMessageBodyStyle.Bare, ResponseFormat = WebMessageFormat.Xml, UriTemplate = "picture/{width}/{height}")] 
Stream GetImage(string width, string height) 
{ 
    int w, h; 
    if (!Int32.TryParse(width, out w)) 
    { 
     // Handle error: use default values 
     w = 640; 
    } 
    if (!Int32.TryParse(height, out h)) 
    { 
     // Handle error use default values 
     h = 480; 
    } 

    .... 
} 

aussehen und Sie erhalten die URL wie http://test.tld/picture/320/200 aufrufen müssen.

+0

Ihre Methode gibt zurück: 'Operation 'GetImage' im Vertrag 'IReceiveData' hat eine Pfadvariable mit dem Namen 'width', die nicht den Typ 'string' hat. Variablen für UriTemplate-Pfadsegmente müssen den Typ 'string' haben. –

+1

Sie haben recht, ich habe vergessen, 'int' in' string' zu ändern. Eine URL hat keine Vorstellung davon, ob ein Parameter eine "int" oder eine "string" ist, also wird alles als "string" übergeben und Sie müssen die Werte in Ihrem Code entsprechend validieren und umsetzen. Wie auch immer, meine Lösung ist die richtige Antwort, da ich genau das auch in einer meiner Anwendungen ausgeführt habe :-D –

+0

Ok, ich werde meine Antwort noch einmal aktualisieren, um klarzustellen, dass * natürlich * die Zeile '// Handle Error 'sollte durch einen Code ersetzt werden, um den Fehler zu behandeln ... –

9
UriTemplate = "picture/" 

Sollte so etwas wie

UriTemplate = "picture?w={width}&h={height}" 

Dies sagt WCF, wie sein, um die Breite und Höhe Parameter aus der URL zu erhalten.

+0

Dies läuft, aber wenn ich versuche, zu "http: // localhost: 8000/Service/Bild? Breite = 50 & Höhe = 40" zu navigieren, erhalte ich einen Fehler in dieser Zeile: 'Bitmap Bitmap = neue Bitmap (Breite, Höhe);' Das sagt ** Parameter ist nicht gültig. ** –

+1

Und dies auch deshalb, weil '{width}' und '{height}' Strings sind und Ihre Methode 'int' erwartet. Benutze meine Lösung unten und du wirst sehen, dass a) die URLs sauberer aussehen als Bargs und b) die Dinge nach dem Umwandeln der Strings nach "int" funktionieren. –

+0

Achten Sie auch darauf, dass Ihre URL und UriTemplate konsistent sind. Oberhalb der UriTemplate werden zwei Parameter mit dem Namen 'w' und 'h' angegeben, aber Ihre URL enthält die Parameter 'width' und 'height'. Die korrekte URL wäre: http: // localhost: 8000/Service/Bild? W = 50 & h = 40 – Opsimath

Verwandte Themen