Ich versuche, einen Web-Service-Client in Silverlight für einen RESTful WCF-Dienst zu programmieren, den ich entwickelt habe. In Silverlight konstruiere ich den Körper der WebRequest mit einer DataContractSerializer-Instanz.Wie kann ich WCF OperationContract-Nachrichtentext manuell erstellen?
Dieser Ansatz funktioniert gut, wenn es ein einziges Argument für den OperationContract gibt. Es funktioniert nicht so gut, wenn im OperationContract mehrere Argumente definiert sind. Ich glaube, dies liegt daran, dass ein dynamischer Typ von WCF erstellt wird, der nach dem OperationContract benannt ist, und die Member dieses Typs nach den für die Operation definierten Parametern benannt sind. Der Zweck des dynamischen Typs besteht darin, sicherzustellen, dass ein einzelnes XML-Element im Nachrichtentext vorhanden ist, der an den WCF-Dienst übergeben wird. Frage: Wie konstruiere ich diesen dynamischen Typ selbst, damit ich ihn selbst an den DataContractSerializer senden kann?
Das erste Beispiel ist ein Arbeitsbeispiel, das einen einzelnen Parameter definiert. Zweites Beispiel ist das Szenario, das ich zu lösen versuche (mehrere Parameter).
Beispiel 1:
[OperationContract,
WebInvoke(Method = HttpMethodType.Post,
BodyStyle = WebMessageBodyStyle.Bare,
UriTemplate = "UnregisterProvider"),
WebHelp(Comment = "Unregistered the provider type with the specified URI.")]
void UnregisterProvider(RdfUri providerUri);
-Code verwendet Nachrichtenkörper serialisieren:
StringBuilder msgBody = new StringBuilder(250);
using (XmlWriter xw = XmlWriter.Create(msgBody))
{
var serializer = new DataContractSerializer(typeof(RdfUri));
serializer.WriteObject(xw, providerUri);
}
resultierende Körper:
<RdfUri xmlns="http://schemas.datacontract.org/2004/07/Intellidimension.Rdf">esp:semanticserver</RdfUri>
Beispiel 2:
[OperationContract,
WebInvoke(Method = HttpMethodType.Post,
BodyStyle = WebMessageBodyStyle.WrappedRequest, /* WrappedRequest must somehow signal WCF to create the anonymous type as it is required for multiple parameter OperationContracts */
UriTemplate = "RegisterProvider"),
WebHelp(Comment = "Registered a provider type with the specified URI.")]
void RegisterProvider(PoolableEntityServiceProviderDescriptor descriptor, RdfUri providerUri);
-Code verwendet Nachrichtentext serialisiert:
//?????
resultierende Körper:
<RegisterProvider xmlns="http://tempuri.org/">
<descriptor i:type="a:SemanticServerProviderDescriptor" xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns:a="http://schemas.datacontract.org/2004/07/Intellidimension.RdfEntity.Service.DataContracts">
<a:ConnectionString>Data Source=.\sqlexpress;Initial Catalog=RdfTest1;Persist Security Info=True;User ID=sa;Password=password</a:ConnectionString>
<a:ProviderGraphUri>http://entitystore/graph-provider</a:ProviderGraphUri>
</descriptor>
<providerUri>esp:semanticserver</providerUri>
</RegisterProvider>
Update 1:
Hier ist ein Typ in den MSDN-Foren, die eine ähnliche Frage stellen: Can I use DataContractSerializerOperationFormatter to format a list of parameters from client to server?
DataContractSerializerOperationFormatter ist eine interne Klasse. Sieht so aus, als müsste ich sein Verhalten für meinen Kunden implementieren.
Update 2:
Einige fragen sich, warum ich gerade nicht das normale Silverlight WCF-Client von einer Service-Referenz erzeugt. Der Grund dafür ist, dass der WCF-Dienst auf dem Server ein REST-fähiger Dienst ist. Von der docs:
Kein Analog zur WebHttpBinding in WCF zur Verfügung gestellt wird. Verwenden Sie für den Zugriff auf reine HTTP-, REST-, RSS/Atom- oder AJAX-Dienste von Silverlight 2 die in Direkt auf HTTP-basierte Dienste zugreifen wie in der WebClient-Klasse beschriebenen Techniken. Informationen zum Zugriff auf ASP.NET AJAX-Dienste finden Sie unter Zugreifen auf ASP.NET AJAX Services.
Ich denke, das ist das zweite Mal, dass Sie mir gesagt haben, WCF nicht zu benutzen :) Ich finde das etwas amüsant. Ich schätze Ihre Ausdauer. Es gibt nicht mehrere Dinge, die im POST-Body veröffentlicht werden, obwohl es ein Element gibt, das auf dem Server in mehrere Methodenparameter verpackt und zerlegt wird. –
Außerdem verwende ich Silverlight und verwende den DataContractSerializer, weil es bequem ist, aber ich sehe nicht, wie WCF verlangt, dass der Klient WCF auch in irgendeiner Weise hat. Ein RESTful WCF-Endpunkt ist derselbe wie jeder andere RESTful-Endpunkt. Recht? –
Ich sage nicht, dass es nicht möglich ist, einen Nicht-WCF-Client zu erstellen, der mit einem WCF-Dienst kommuniziert, aber Sie werden viele Probleme haben. Versuchen Sie, einen Stream an einen WCF-Endpunkt zu senden. Versuchen Sie, Basic Auth mit einem nicht Windows-Benutzernamen auszuführen. Versuchen Sie, einen Fehler zurückzugeben, der nicht die Standard-HTML-Seite ist. –