Handle Json Request data in WCF REST Service POST

2019-08-15 04:44发布

问题:

i am creating the REST service with POST method and OBJECT as input param. while client request am unable to get the actual JSON data client have posted. Is there any way to dig the JSON code from the C# WCF service.

My code:

namespace ACTService
{
  public class AssortmentService : IAssortmentService
  {
    public void DeleteColor(DeleteColorContarct objdelcolor)
    {
         new Methods.ColorUI().DeleteColorDetails(objdelcolor);
    }
  }
}

and my interface as

namespace ACTService
{
  [ServiceContract]
  public interface IAssortmentService
  {
    [OperationContract]
    [WebInvoke(UriTemplate = "DeleteColor", Method = "POST", ResponseFormat = WebMessageFormat.Json, RequestFormat = WebMessageFormat.Json,BodyStyle=WebMessageBodyStyle.Wrapped)]
    void DeleteColor(DeleteColorContarct objColor);
  }
}

I need to access the JSON format in other class file ColorUI

回答1:

WCF provides a lot of extensible points one of them is a feature called MessageInspector. You can create a custom message inspector to receive the request before it get de-serialized to C# object. And do what ever you can with Raw request data.

In order to implement it you would need to implement System.ServiceModel.Dispatcher.IDispatchMessageInspector interface like below:

public class IncomingMessageLogger : IDispatchMessageInspector
{
    const string MessageLogFolder = @"c:\temp\";
    static int messageLogFileIndex = 0;

    public object AfterReceiveRequest(ref Message request, IClientChannel channel, InstanceContext instanceContext)
    {
        string messageFileName = string.Format("{0}Log{1:000}_Incoming.txt", MessageLogFolder, Interlocked.Increment(ref messageLogFileIndex));
        Uri requestUri = request.Headers.To;

        HttpRequestMessageProperty httpReq = (HttpRequestMessageProperty)request.Properties[HttpRequestMessageProperty.Name];

        // Decode the message from request and do whatever you want to do.
        string jsonMessage = this.MessageToString(ref request);

        return requestUri;
    }

    public void BeforeSendReply(ref Message reply, object correlationState)
    {
    }
}

Here's the complete code snippet gist. Actual source.

Now you need to add this Message inspector to end point behavior. To achieve that you would be implementing System.ServiceModel.Description.IEndpointBehavior interface like below:

public class InsepctMessageBehavior : IEndpointBehavior
{
    public void AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection bindingParameters)
    {
    }

    public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime)
    {
    }

    public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher)
    {
        endpointDispatcher.DispatchRuntime.MessageInspectors.Add(new IncomingMessageLogger());
    }

    public void Validate(ServiceEndpoint endpoint)
    {
    }
}

Now if you are on selfhosting i.e. you are hosting your service programmatically you can directly attach this newly implemented behavior to your service end point. E.g.

endpoint.Behaviors.Add(new IncomingMessageLogger());

But If you have hosted the WCF Rest service in IIS then you would be injecting the new Behavior via configuration. In order to achieve that you have to create an additional class derived from BehaviorExtensionElement:

public class InspectMessageBehaviorExtension : BehaviorExtensionElement
{
    public override Type BehaviorType
    {
        get { return typeof(InsepctMessageBehavior); }
    }

    protected override object CreateBehavior()
    {
        return new InsepctMessageBehavior();
    }
}

Now in your configuration first register the behavior under system.servicemodel tag:

    <extensions>
      <behaviorExtensions>
        <add name="inspectMessageBehavior" 
type="WcfRestAuthentication.MessageInspector.InspectMessageBehaviorExtension, WcfRestAuthentication"/>
      </behaviorExtensions>
    </extensions>

Now add this behavior to the Endpoint behavior:

  <endpointBehaviors>
    <behavior name="defaultWebHttpBehavior">
      <inspectMessageBehavior/>
      <webHttp defaultOutgoingResponseFormat="Json"/>
    </behavior>
 </endpointBehaviors>

set the attribute behaviorConfiguration="defaultWebHttpBehavior" in your endpoint.

That's it your service will now capture all the messages before deserializing them.