tutorial started servicecontract programming implement getting .net wcf

.net - started - ¿Puede un atributo WebGet del método OperationContract de WCF tener varios tipos de ResponseFormat?



wcf step by step (2)

Tengo un ServiceContract que describe un método utilizado en un servicio WCF. El método tiene un atributo WebGet que define un UriTemplate y un ResponseFormat.

Quiero reutilizar un solo método y tener múltiples atributos de WebGet con diferentes UriTemplates y diferentes ResponseFormats. Básicamente, espero evitar tener múltiples métodos para diferenciar cosas como el tipo de retorno como XML frente a JSON. Sin embargo, en todos los ejemplos que he visto hasta ahora, debo crear un método diferente para cada atributo de WebGet. Aquí hay una muestra de OperationContract

[ServiceContract] public interface ICatalogService { [OperationContract] [WebGet(UriTemplate = "product/{id}/details?format=xml", ResponseFormat = WebMessageFormat.Xml)] Product GetProduct(string id); [OperationContract] [WebGet(UriTemplate = "product/{id}/details?format=json", ResponseFormat = WebMessageFormat.Json)] Product GetJsonProduct(string id); }

Usando el ejemplo anterior, me gustaría usar el método GetProduct para los tipos de retorno xml y json como este:

[ServiceContract] public interface ICatalogService { [OperationContract] [WebGet(UriTemplate = "product/{id}/details?format=xml", ResponseFormat = WebMessageFormat.Xml)] [WebGet(UriTemplate = "product/{id}/details?format=json", ResponseFormat = WebMessageFormat.Json)] Product GetProduct(string id); }

¿Hay una manera de lograr esto para no atascarme escribiendo diferentes métodos solo para devolver diferentes ResponseFormats?

¡Gracias!


Puedes hacerlo

[ServiceContract] public interface ICatalogService { [OperationContract] [WebGet(UriTemplate = "product/{id}/details?format={format}")] Stream GetProduct(string id, string format); }

Y luego, en su código, la serialización se basa en el valor especificado en el parámetro.

Para XML, escriba un método auxiliar que maneje su serialización.

public static Stream GetServiceStream(string format, string callback, DataTable dt, SyndicationFeed sf) { MemoryStream stream = new MemoryStream(); StreamWriter writer = new StreamWriter(stream, Encoding.UTF8); if (format == "xml") { XmlSerializer xmls = new XmlSerializer(typeof(DataTable)); xmls.Serialize(writer, dt); WebOperationContext.Current.OutgoingResponse.ContentType = "text/xml"; } else if (format == "json") { var toJSON = new JavaScriptSerializer(); toJSON.RegisterConverters(new JavaScriptConverter[] { new JavaScriptDataTableConverter() }); writer.Write(toJSON.Serialize(dt)); WebOperationContext.Current.OutgoingResponse.ContentType = "text/json"; } else if (format == "jsonp") { var toJSON = new JavaScriptSerializer(); toJSON.RegisterConverters(new JavaScriptConverter[] { new JavaScriptDataTableConverter() }); writer.Write(callback + "( " + toJSON.Serialize(dt) + " );"); WebOperationContext.Current.OutgoingResponse.ContentType = "text/json"; } else if (format == "rss") { XmlWriter xmlw = new XmlTextWriter(writer); sf.SaveAsRss20(xmlw); WebOperationContext.Current.OutgoingResponse.ContentType = "text/xml"; } else if (format == "atom") { XmlWriter xmlw = new XmlTextWriter(writer); sf.SaveAsAtom10(xmlw); WebOperationContext.Current.OutgoingResponse.ContentType = "text/xml"; } else { writer.Write("Invalid formatting specified."); WebOperationContext.Current.OutgoingResponse.ContentType = "text/html"; } writer.Flush(); stream.Position = 0; return stream; } }


Si recuerdo correctamente, el siguiente método funcionó para mí:

Contrato de servicio json:

[ServiceContract] public interface IServiceJson { [OperationContract()] [WebGet(UriTemplate = "Operation/?param={param}", ResponseFormat = WebMessageFormat.Json)] ReturnType Operation(string param); }

Contacto para servicio xml:

[ServiceContract] public interface IServiceXml { [OperationContract(Name = "OperationX")] [WebGet(UriTemplate = "Operation/?param={param}", ResponseFormat = WebMessageFormat.Xml)] ReturnType Operation(string param); }

Implementación para ambos:

public class ServiceImplementation : IServiceJson, IServiceXml { ReturnType Operation(string param) { // Implementation } }

Y la configuración web.config (tenga en cuenta los puntos finales para las respuestas json y xml):

<system.serviceModel> <behaviors> <endpointBehaviors> <behavior name="webHttp"> <webHttp /> </behavior> </endpointBehaviors> <serviceBehaviors> <behavior name="serviceBehaviour"> <serviceMetadata httpGetEnabled="true" /> <serviceDebug includeExceptionDetailInFaults="true" /> </behavior> </serviceBehaviors> </behaviors> <services> <service behaviorConfiguration="serviceBehaviour" name="ServiceImplementation"> <endpoint address="json/" behaviorConfiguration="webHttp" binding="webHttpBinding" bindingConfiguration="webHttpBindingSettings" contract="IServiceJson"> <identity> <dns value="localhost" /> </identity> </endpoint> <endpoint address="xml/" behaviorConfiguration="webHttp" binding="webHttpBinding" bindingConfiguration="webHttpBindingSettings" contract="IServiceXml"> <identity> <dns value="localhost" /> </identity> </endpoint> <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" /> </service> </services> <bindings> <webHttpBinding> <binding name="webHttpBindingSettings"> <readerQuotas maxStringContentLength="5000000"/> </binding> </webHttpBinding> </bindings> </system.serviceModel>

Ahora puede llamar a su servicio así: json response: http: // yourServer / json / Operation /? Param = value xml response: http: // yourServer / xml / Operation /? Param = value

(Disculpe si hay algún error en el código anterior, no lo ejecuté para verificación).