WCF: Retrieving MethodInfo from OperationContext
Asked Answered
D

4

20

Is there an elegant way to get the method that will be executed on a service instance from MessageInspector/AuthorizationPolicy/some other extension point? I could use

OperationContext.Current.IncomingMessageHeaders.Action

but I hope there's some way to do it without manually matching SOAP actions with OperationContracts.

What I'm trying to do is examine the method's attributes before it executes.

Dixie answered 12/5, 2009 at 13:41 Comment(0)
H
26

It took me forever, but I did find a way that's better than finding and slogging through the entire contract:

string action = operationContext.IncomingMessageHeaders.Action;
DispatchOperation operation = 
    operationContext.EndpointDispatcher.DispatchRuntime.Operations.FirstOrDefault(o =>
        o.Action == action);
// Insert your own error-handling here if (operation == null)
Type hostType = operationContext.Host.Description.ServiceType;
MethodInfo method = hostType.GetMethod(operation.Name);

And there you are. You can get the attributes or do whatever else you like.

Note: You might be tempted to try to use the OperationSelector in the DispatchRuntime. The problem I found was that in my case, at the particular stage of processing, the OperationSelector was a null reference. If you have access to this property, it's probably faster and more reliable to use than "scanning" the OperationCollection as above.

Hypothesis answered 1/10, 2009 at 17:22 Comment(4)
DispatchOperation does not contain a definition for FirstOrDefault?Delphinus
@Fulvio: Make sure you've added a namespace reference to System.Linq.Hypothesis
Thanks for that. I managed to get it working, however I need to grab the parameter values from the OperationContext and I'm having a bit of trouble doing that.Delphinus
This doesn't work if the operation is renamed in the OperationContract.Respiratory
F
15

If OperationContext.CurrentIncomingMessageHeaders.Action is null, you can do this -- it's a bit terser:

string actionName = OperationContext.Current.IncomingMessageProperties["HttpOperationName"] as string;
Type hostType = operationContext.Host.Description.ServiceType;
MethodInfo method = hostType.GetMethod(actionName);
Folsom answered 11/4, 2011 at 18:44 Comment(0)
T
8

Based on @Aaronaught and @TimDog 's answers, and this SO question I came up with a solution that should work for both REST and SOAP.

///<summary>Returns the Method info for the method (OperationContract) that is called in this WCF request.</summary>
System.Reflection.MethodInfo GetActionMethodInfo(System.ServiceModel.OperationContext operationContext ){
    string bindingName = operationContext.EndpointDispatcher.ChannelDispatcher.BindingName;
    string methodName;
    if(bindingName.Contains("WebHttpBinding")){
            //REST request
            methodName = (string) operationContext.IncomingMessageProperties["HttpOperationName"];
    }else{
            //SOAP request
            string action = operationContext.IncomingMessageHeaders.Action;
            methodName = operationContext.EndpointDispatcher.DispatchRuntime.Operations.FirstOrDefault(o =>o.Action == action).Name;
    }
    // Insert your own error-handling here if (operation == null)
    Type hostType = operationContext.Host.Description.ServiceType;
    return hostType.GetMethod(methodName);
}
Tague answered 5/4, 2012 at 8:40 Comment(1)
Unfortunately, we are going Core and ChannelDispatcher is no longer reachable. Just leaving this comment for the next one who tries to get CoreWCF up and running, you have been warned!Goddamned
T
1

Castle WCF integration facility enables you to do just that (among many useful things) by using DynamicProxy proxies. Take a look here.

There's not much documentation on it, so for docs on how to use it it's best to take a look at its tests.

Teador answered 12/5, 2009 at 14:31 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.