Logging requests/responses in a WCF REST service - wcf

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?

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.

There is a technic in WCF:
you create InstrumentedOperationAttribute that derives from Attribute, IOperationBehavior.
Inside you implement:
public void ApplyDispatchBehavior(
OperationDescription operationDescription,
DispatchOperation dispatchOperation
)
{
dispatchOperation.ParameterInspectors.Add(
new ServerPI()
);
}
and the ServerPI() class is what does the magic:
you do everything you need in beforecall and aftercall methods:
class ServerPI : IParameterInspector
{
public void AfterCall(string operationName, object[] outputs, object returnValue, object correlationState)
{
Guid result = (Guid)correlationState;
// ...
}
public object BeforeCall(string operationName, object[] inputs)
{
string parameter1 = inputs[0] as string;
return Guid.NewGuid();
}
}

Related

jaxrs queryparam not loaded for interceptor

I have a REST service of the form:
#GET
#NeedsInterception
public void getSomething(#QueryParam("xxx") #MyAnnotation String thing) {
//Stuff
}
I then have an interceptor for #NeedsInterception.
In it, I perform some logic on the element annotated with #MyAnnotation.
However, when the interceptor is called, the MethodInvocation object has not yet been resolved with the value of the QueryParam, instead it is always "";
Is there a way for me to make the interception happen after the QueryParam is resolved?
Don't know which kind of interceptor you are using but a jax-rs ReaderInterceptor is intended to wrap calls to MessageBodyReader.readFrom. As you don't send a request body with a #GET request this kind of interceptor won't be used.
A ContainerRequestFilter should help:
#Provider
public class SomeFilter implements ContainerRequestFilter {
#Override
public void filter(ContainerRequestContext requestContext) throws IOException {
MultivaluedMap<String,String> queryParameters = requestContext.getUriInfo().getQueryParameters();
}
}

Handling Invalid URI passed to a WCF service

I have WebGet, and WebInvoke attributes describing my contract, but what is the best method of handling invalid URI's? Right now, if a user passes an URI that does not match my current operations, they get an "Endpoint not found." message. I want to pass back a more descriptive message.
For example, my URI template looks like:
/Stuff/{ID}/subStuff
but say they type
/Stuff/{ID}/OtherStuff
There is no such thing as OtherStuff, and I do not have a template for that.
Is there a way to cover all non mapped URI's with a single contract?
Thanks!
If you want to catch all the unhandled requests at a global level in WCF REST then you have to create a custom WebHttpBehavior and custom IOperationInvoker as described in this post.
If you want to return a custom error text with custom status code(404) you can also look into the WebOperationContext.OutgoingResponse property as described here.
While I did follow the links mark provided, and they did give a hint of what I needed. The answers that were linked did not actually answer my original question.
I was able to follow the steps, and I wanted to list my steps to solve this problem on this question as well.
To create my own response to any URI that was not mapped to a method in my contract I created the following:
A custom ServiceHostFactory
Behavior that I mapped to my end points within the custom ServiceHostFactory
a dispatcher that would handle all unmapped uri's that were provided to the service.
Below are the full definitions of the object's I created:
using System.ServiceModel;
using System.ServiceModel.Activation;
namespace your.namespace.here
{
public class CustomServiceHostFactory : WebServiceHostFactory
{
protected override ServiceHost CreateServiceHost(Type serviceType, Uri[] baseAddresses)
{
ServiceHost host = base.CreateServiceHost(serviceType, baseAddresses);
//note: these endpoints will not exist yet, if you are relying on the svc system to generate your endpoints for you
// calling host.AddDefaultEndpoints provides you the endpoints you need to add the behavior we need.
var endpoints = host.AddDefaultEndpoints();
foreach (var endpoint in endpoints)
{
endpoint.Behaviors.Add(new WcfUnkownUriBehavior());
}
return host;
}
}
}
As you can see above, we are adding a new behavior: WcfUnknownUriBehavior. This new custom behavior's soul duty is to replace the UnknownDispatcher. below is that implementation:
using System.ServiceModel.Dispatcher;
using System.ServiceModel.Channels;
using System.ServiceModel.Web;
namespace your.namespace.here
{
public class UnknownUriDispatcher : IOperationInvoker
{
public object[] AllocateInputs()
{
//no inputs are really going to come in,
//but we want to provide an array anyways
return new object[1];
}
public object Invoke(object instance, object[] inputs, out object[] outputs)
{
var responeObject = new YourResponseObject()
{
Message = "Invalid Uri",
Code = "Error",
};
Message result = Message.CreateMessage(MessageVersion.None, null, responeObject);
WebOperationContext.Current.OutgoingResponse.ContentType = "text/html";
outputs = new object[1]{responeObject};
return result;
}
public System.IAsyncResult InvokeBegin(object instance, object[] inputs, System.AsyncCallback callback, object state)
{
throw new System.NotImplementedException();
}
public object InvokeEnd(object instance, out object[] outputs, System.IAsyncResult result)
{
throw new System.NotImplementedException();
}
public bool IsSynchronous
{
get { return true; }
}
}
}
Once you have these objects specified, you can now use the new factory within your svc's "markup":
<%# ServiceHost Language="C#" Debug="true" Service="your.service.namespace.here" CodeBehind="myservice.svc.cs"
Factory="your.namespace.here.CustomServiceHostFactory" %>
And that should be it. as long as your object "YourResponseObject" can be serialized, it's serialized representation will be sent back to the client.

Implementing unit of work in a WCF service with Autofac

How can I implement unit of work pattern in a WCF service with Autofac?
Injecting the same instance per call (or in Autofac terms LifetimeScope) of the unit of work interface into my services and repositories is easy using Autofac's wcf integration - what I am after is a way to commit the unit of work changes on return of WCF service call obviously ONLY if there has not been any exceptions.
I have seen Using a Custom Endpoint Behavior with WCF and Autofac which is basically how I started out but that does not deal with exceptions.
Currently what I have is an IOperationInvoker that starts the unit of work in the Invoke and commits it only if there has not been any exceptions. The problem with this approach is that I need to resolve my unit of work instance inside the Invoke method which gives me a different instance than the one injected into my services and repositories using AutofacInstanceProvider.
Bradley Boveinis found a solution to this problem. We have not thoroughly tested it but it seems to work:
public class UnitOfWorkAwareOperationInvoker : IOperationInvoker
{
private readonly IOperationInvoker _baseInvoker;
public UnitOfWorkAwareOperationInvoker(IOperationInvoker baseInvoker)
{
_baseInvoker = baseInvoker;
}
public object[] AllocateInputs()
{
return _baseInvoker.AllocateInputs();
}
public object Invoke(object instance, object[] inputs, out object[] outputs)
{
var result = _baseInvoker.Invoke(instance, inputs, out outputs);
var context = OperationContext.Current.InstanceContext.Extensions.Find<AutofacInstanceContext>();
try
{
context.Resolve<IUnitOfWork>().Save();
}
catch (Exception ex)
{
var message = Message.CreateMessage(MessageVersion.Default, string.Empty);
new ElmahErrorHandler().ProvideFault(ex, null, ref message);
throw;
}
return result;
}
public IAsyncResult InvokeBegin(object instance, object[] inputs, AsyncCallback callback, object state)
{
return _baseInvoker.InvokeBegin(instance, inputs, callback, state);
}
public object InvokeEnd(object instance, out object[] outputs, IAsyncResult result)
{
return _baseInvoker.InvokeEnd(instance, out outputs, result);
}
public bool IsSynchronous
{
get { return _baseInvoker.IsSynchronous; }
}
}
The key is in the following line:
OperationContext.Current.InstanceContext.Extensions.Find<AutofacInstanceContext>();
This grabs the UoW out of the ambient/current/contextual LifetimeScope.

Passing callback objects to WCF service methods

Is it possible to pass callback objects (with callback methods) to a wcf service method?
Let's presume i have the following class:
class Callback
{
public Callback(){}
public int GetSomeData(int param)
{
return param;
}
}
Is it possible somehow to make a call like :
WCFServiceProxy proxy = new WCFServiceProxy();
Callback myCallback = new Callback();
proxy.SomeMethod(myCallback);
and have the service call GetSomeData() implemented on the client side?
Or what would be a working solution for this?
see Duplex Services
Yes, you can do that. You have to define a secondary interface that serves as the callback contract.
[ServiceContract]
public interface ICallback
{
[OperationContract(IsOneWay=true)]
void InvokeCallback();
}
[ServiceContract(CallbackContract=typeof(ICallback)]
public interface IContract
{
[OperationContract]
void DoSomething();
}
[ServiceBehavior]
public class MyService : IContract
{
void DoSomething() { }
}
That's the basic approach. I would strongly suggestion looking at Juval Lowy's website, IDesign.net. His downloads section has several examples of how to do this.

Difference between event-based and callback/delegate-based asynchronous methods?

When using svcutil.exe, I noticed this switch, /tcv:Version35. The docs says this:
Version35: Use /tcv:Version35 if you
are generating code for clients that
use .NET Framework 3.5. By using this
value, the SvcUtil.exe tool generates
code that references functionality in
.NET Framework 3.5 and previous
versions. When using /tcv:Version35
with the /async switch, both
event-based and
callback/delegate-based asynchronous
methods are generated. In addition,
support for LINQ-enabled DataSets and
DateTimeOffset is enabled.
What is the difference between event-based and callback/delegate based async models?
EDIT: Is one way newer/better? I only get the BeginXXX and EndXXX methods when I don't use the /tcv:Version35 switch. Silverlight uses XXXAsync which tells me I should use the event-based (XXXAsync) methods and use this switch.
Let's define a WCF service like this:
namespace StackOverflow
{
[ServiceContract]
public interface ITest
{
[OperationContract]
string GetName();
}
public class Test : ITest
{
public string GetName()
{
return "Joel Spolsky";
}
}
}
If you run svcutil on this, you'll get the following client definition:
public partial class TestClient : System.ServiceModel.ClientBase<ITest>, ITest
{
// Other details elided...
public string GetData(int value)
{
return base.Channel.GetData(value);
}
}
If you run svcutil again using the /async flag, you'll get the following client definition:
public partial class TestClient : System.ServiceModel.ClientBase<ITest>, ITest
{
// Other details elided...
public event System.EventHandler<GetDataCompletedEventArgs> GetDataCompleted;
public string GetData(int value)
{
return base.Channel.GetData(value);
}
[EditorBrowsableAttribute(EditorBrowsableState.Advanced)]
public System.IAsyncResult BeginGetData(int value, System.AsyncCallback callback, object asyncState)
{
return base.Channel.BeginGetData(value, callback, asyncState);
}
[EditorBrowsableAttribute(EditorBrowsableState.Advanced)]
public string EndGetData(System.IAsyncResult result)
{
return base.Channel.EndGetData(result);
}
public void GetDataAsync(int value, object userState)
{
if ((this.onBeginGetDataDelegate == null))
{
this.onBeginGetDataDelegate = new BeginOperationDelegate(this.OnBeginGetData);
}
if ((this.onEndGetDataDelegate == null))
{
this.onEndGetDataDelegate = new EndOperationDelegate(this.OnEndGetData);
}
if ((this.onGetDataCompletedDelegate == null))
{
this.onGetDataCompletedDelegate = new System.Threading.SendOrPostCallback(this.OnGetDataCompleted);
}
base.InvokeAsync(this.onBeginGetDataDelegate, new object[] {value}, this.onEndGetDataDelegate, this.onGetDataCompletedDelegate, userState);
}
}
So the /async flag simply provides a means for you to interact with your service asynchronously instead of the default synchronous-only behavior.
The GetDataAsync() method invokes the GetData() method asynchronously and notifies you when it is complete via the GetDataCompleted event.
The BeginGetData() and EndGetData() methods use the asynchronous behavior of delegates to invoke the GetData() method asynchronously. This is analogous to the BeginInvoke() and EndInvoke() methods on the System.Windows.Forms.Control class or the BeginRead() and EndRead() methods on the System.IO.Stream class.