Interception always happens before and after. It's up to you in the implementation of the call handler if something happens at each of those points. The handler sits on "top" of the target method, and it can decide to do stuff before calling
the target, after calling the target, or even not to call the target at all. Handlers aren't placed in the call chain before or after the target, they're a decorator chain instead.
Have you looked at the implementation of a custom behavior or call handler yet? In the Invoke method of every once, you'll see a call like this:
IMethodReturn result = getNext()(input, getNext);
This call is what calls either the next handler in the chain, or the target if there isn't any. If you want to do stuff before calling the target, put that code before this call. If you want to do stuff after calling the target, put code
after this call. It's that simple.
Also notice the return value result - this contains the value that was returned from the target or exception that was thrown, if any.
The ultimate return value from an intercepted called is determined by the IMethodReturn object returned from the Invoke method. There's nothing that requires you to return the same IMethodReturn object you got back from the target. The input parameter you
received contains two methods you can use: CreateMethodReturn and CreateExceptionMethodReturn. These methods can be used to construct whole new return values, and either return a value or cause an exception to be thrown.
I hope this points you in the right direction.