Cuerpo de solicitud de acceso en un servicio RESTful WCF

¿Cómo accedo al cuerpo de solicitud HTTP POST en un servicio REST de WCF?

Aquí está la definición de servicio:

[ServiceContract] public interface ITestService { [OperationContract] [WebInvoke(Method = "POST", UriTemplate = "EntryPoint")] MyData GetData(); } 

Aquí está la implementación:

 public MyData GetData() { return new MyData(); } 

Pensé en usar el siguiente código para acceder a la solicitud HTTP:

 IncomingWebRequestContext context = WebOperationContext.Current.IncomingRequest; 

Pero el IncomingWebRequestContext solo da acceso a los encabezados, no al cuerpo.

Gracias.

La mejor manera, creo, no involucra a WebOperationContext

 [OperationContract] [WebInvoke(Method = "POST", UriTemplate = "EntryPoint", BodyStyle = WebMessageBodyStyle.Bare)] MyData GetData(System.IO.Stream pStream); 

Utilizar

OperationContext.Current.RequestContext.RequestMessage

Lo siento por la respuesta tardía, pero pensé que agregaría lo que funciona con los parámetros de UriTemplate para obtener el cuerpo de la solicitud.

 [ServiceContract] public class Service { [OperationContract] [WebInvoke(UriTemplate = "{param0}/{param1}", Method = "POST")] public Stream TestPost(string param0, string param1) { string body = Encoding.UTF8.GetString(OperationContext.Current.RequestContext.RequestMessage.GetBody()); return ...; } } 

body se asigna una cadena de los bytes sin procesar del cuerpo del mensaje.

Parece que debido a que WCF está diseñado para ser independiente del protocolo de transporte, un método de servicio no proporciona acceso a la información específica de HTTP de forma predeterminada. Sin embargo, acabo de encontrar un buen artículo que describe el “Modo de compatibilidad de ASP.Net” que, esencialmente, le permite especificar que su servicio está destinado a ser expuesto a través de HTTP.

http://blogs.msdn.com/b/wenlong/archive/2006/01/23/516041.aspx

Agregar la configuración aspNetCompatibilityEnabled a Web.config , combinado con el atributo AspNetCompatibilityRequirements a las operaciones de servicio deseadas, debería hacer el truco. Estoy a punto de intentar esto yo mismo.

Haw-Bin

Las respuestas anteriores me ayudaron a encontrar esta solución. Estoy recibiendo json con pares de nombre / valor. {“p1”: 7514, “p2”: 3412, “p3”: “joe smith” …}

 [OperationBehavior(Impersonation = ImpersonationOption.Allowed)] [WebInvoke(Method = "POST", BodyStyle = WebMessageBodyStyle.Bare, RequestFormat = WebMessageFormat.Json )] public Stream getJsonRequest() { // Get the raw json POST content. .Net has this in XML string.. string JSONstring = OperationContext.Current.RequestContext.RequestMessage.ToString(); // Parse the XML string into a XML document XmlDocument doc = new XmlDocument(); doc.LoadXml(JSONstring); foreach (XmlNode node in doc.DocumentElement.ChildNodes) { node.Name // has key node.InnerText; // has value 

Mis disculpas por la respuesta anterior, asumí estúpidamente que acababa de lanzar WebOperationContext para obtener OperationContext, desafortunadamente la respuesta real es mucho más fea.

Déjame comenzar con esto, ¡debe haber una mejor manera!

Primero creé mi propio objeto de contexto, que podría adjuntarse al objeto OperationContext existente.

 public class TMRequestContext : IExtension { private OperationContext _Owner; public void Attach(OperationContext owner) { _Owner = owner; } public void Detach(OperationContext owner) { _Owner = null; } public static TMRequestContext Current { get { if (OperationContext.Current != null) { return OperationContext.Current.Extensions.Find(); } else { return null; } } } } 

Para poder acceder a este nuevo objeto de contexto, debe agregarlo como una extensión a la actual. Lo hice creando una clase de inspector de mensajes.

 public class TMMessageInspector : IDispatchMessageInspector { public object AfterReceiveRequest(ref Message request, IClientChannel channel, InstanceContext instanceContext) { OperationContext.Current.Extensions.Add(new TMRequestContext()); return null; } } 

Para que el inspector de mensajes funcione, necesita crear un nuevo “comportamiento”. Hice esto usando el siguiente código.

  public class TMServerBehavior : IServiceBehavior { public void AddBindingParameters(ServiceDescription serviceDescription, System.ServiceModel.ServiceHostBase serviceHostBase, System.Collections.ObjectModel.Collection endpoints, System.ServiceModel.Channels.BindingParameterCollection bindingParameters) { //Do nothing } public void ApplyDispatchBehavior(ServiceDescription serviceDescription, System.ServiceModel.ServiceHostBase serviceHostBase) { foreach (ChannelDispatcher chDisp in serviceHostBase.ChannelDispatchers) { foreach (EndpointDispatcher epDisp in chDisp.Endpoints) { epDisp.DispatchRuntime.MessageInspectors.Add(new TMMessageInspector()); } } } } 

El comportamiento que debería poder agregar en el archivo de configuración, aunque lo hice creando un nuevo host y agregando el objeto de comportamiento manualmente en el método OnOpening. Terminé usando esta clase para mucho más que simplemente acceder al objeto OperationContext. Los utilicé para registrar y anular el manejo de errores y el acceso al objeto de solicitud http, etc. Entonces, no es una solución tan ridícula como parece. Casi, pero no del todo!

Realmente no recuerdo por qué no pude acceder directamente a OperationContext.Current. Tengo un leve recuerdo de que siempre estuvo vacío y este proceso desagradable fue la única manera de obtener una instancia que realmente contenía datos válidos.