I'm looking for a way to log both requests and responses in a WCF REST service. The WCF REST starter kit comes with a RequestInterceptor class which can be used to intercept requests, but there does not seem to be an equivalent for responses. Ideally, I'd like to be able to intercept a response just before it's sent over the wire, e.g. when the underlying service method returns. Any suggestions?
R – Logging requests/responses in a WCF REST service
requestresponserestwcf
Related Solutions
You can expose the service in two different endpoints. the SOAP one can use the binding that support SOAP e.g. basicHttpBinding, the RESTful one can use the webHttpBinding. I assume your REST service will be in JSON, in that case, you need to configure the two endpoints with the following behaviour configuration
<endpointBehaviors>
<behavior name="jsonBehavior">
<enableWebScript/>
</behavior>
</endpointBehaviors>
An example of endpoint configuration in your scenario is
<services>
<service name="TestService">
<endpoint address="soap" binding="basicHttpBinding" contract="ITestService"/>
<endpoint address="json" binding="webHttpBinding" behaviorConfiguration="jsonBehavior" contract="ITestService"/>
</service>
</services>
so, the service will be available at
Apply [WebGet] to the operation contract to make it RESTful. e.g.
public interface ITestService
{
[OperationContract]
[WebGet]
string HelloWorld(string text)
}
Note, if the REST service is not in JSON, parameters of the operations can not contain complex type.
Reply to the post for SOAP and RESTful POX(XML)
For plain old XML as return format, this is an example that would work both for SOAP and XML.
[ServiceContract(Namespace = "http://test")]
public interface ITestService
{
[OperationContract]
[WebGet(UriTemplate = "accounts/{id}")]
Account[] GetAccount(string id);
}
POX behavior for REST Plain Old XML
<behavior name="poxBehavior">
<webHttp/>
</behavior>
Endpoints
<services>
<service name="TestService">
<endpoint address="soap" binding="basicHttpBinding" contract="ITestService"/>
<endpoint address="xml" binding="webHttpBinding" behaviorConfiguration="poxBehavior" contract="ITestService"/>
</service>
</services>
Service will be available at
REST request try it in browser,
SOAP request client endpoint configuration for SOAP service after adding the service reference,
<client>
<endpoint address="http://www.example.com/soap" binding="basicHttpBinding"
contract="ITestService" name="BasicHttpBinding_ITestService" />
</client>
in C#
TestServiceClient client = new TestServiceClient();
client.GetAccount("A123");
Another way of doing it is to expose two different service contract and each one with specific configuration. This may generate some duplicates at code level, however at the end of the day, you want to make it working.
Overall:
Both PUT and POST can be used for creating.
You have to ask, "what are you performing the action upon?", to distinguish what you should be using. Let's assume you're designing an API for asking questions. If you want to use POST, then you would do that to a list of questions. If you want to use PUT, then you would do that to a particular question.
Great, both can be used, so which one should I use in my RESTful design:
You do not need to support both PUT and POST.
Which you use is up to you. But just remember to use the right one depending on what object you are referencing in the request.
Some considerations:
- Do you name the URL objects you create explicitly, or let the server decide? If you name them then use PUT. If you let the server decide then use POST.
- PUT is defined to assume idempotency, so if you PUT an object twice, it should have no additional effect. This is a nice property, so I would use PUT when possible. Just make sure that the PUT-idempotency actually is implemented correctly in the server.
- You can update or create a resource with PUT with the same object URL
- With POST you can have 2 requests coming in at the same time making modifications to a URL, and they may update different parts of the object.
An example:
I wrote the following as part of another answer on SO regarding this:
POST:
Used to modify and update a resource
POST /questions/<existing_question> HTTP/1.1 Host: www.example.com/
Note that the following is an error:
POST /questions/<new_question> HTTP/1.1 Host: www.example.com/
If the URL is not yet created, you should not be using POST to create it while specifying the name. This should result in a 'resource not found' error because
<new_question>
does not exist yet. You should PUT the<new_question>
resource on the server first.You could though do something like this to create a resources using POST:
POST /questions HTTP/1.1 Host: www.example.com/
Note that in this case the resource name is not specified, the new objects URL path would be returned to you.
PUT:
Used to create a resource, or overwrite it. While you specify the resources new URL.
For a new resource:
PUT /questions/<new_question> HTTP/1.1 Host: www.example.com/
To overwrite an existing resource:
PUT /questions/<existing_question> HTTP/1.1 Host: www.example.com/
Additionally, and a bit more concisely, RFC 7231 Section 4.3.4 PUT states (emphasis added),
4.3.4. PUT
The PUT method requests that the state of the target resource be
created
orreplaced
with the state defined by the representation enclosed in the request message payload.
Best Answer
Notice that if you want to intercept the raw message, and not the parameters, you can inject your implementation of IDispatchMessageInspector instead of the IParameterInspector extension point that Dani suggests.