How to get a Custom Attribute value of WCF Contract's Operation using IDispatchMessageInspector

4.2k Views Asked by At

The question is in AfterReceiveRequest how to find out the custom attribute set on the Operation using the OperationDescription? If there's a way, is it better to set the custom attribute on operation declaration in service contract interface or the service implementation class?

To illustrate the question further:

public interface IGetterSetterService
{
    [OperationContract, GetterRequest]
    Data[] GetData();
    [OperationContract, SetterRequest]
    bool SetData(string Data);
}

OR

[WebInvoke(Method = "*", ResponseFormat = WebMessageFormat.Json, UriTemplate = "xyz"]
[GetterRequest]
public Data[] GetData()
{
    return new Data[];
}
[WebInvoke(Method = "*", ResponseFormat = WebMessageformat.Json, UriTemplate = "xyz/{data}"]
[SetterRequest]
public bool SetData(string data)
{
    return true;
}

Now the IDispatchMessageInspector:

public object AfterReceiveRequest(ref Message request, IClientChannel channel, InstanceContext instanceContext)
{
    //Here how to find out the GetterRequest or SetterRequest custom attribute set on an
    //operation, may be using OperationDescription for the current context?
}
2

There are 2 best solutions below

0
On BEST ANSWER

My complete solution looks like this and it works without any problem:
1. First get the operation description as discussed here
2. Then find the custom attributes set on Operations in Service interface:

private UserAction GetIntendedUserAction(OperationDescription opDesc)
{
    Type contractType = opDesc.DeclaringContract.ContractType;
    var attr = contractType.GetMethod(opDesc.Name).GeCustomAttributes(typeof(RequestedAction), false) as RequestedAction[];
    if (attr != null && attr.Length > 0)
    {
        return attr[0].ActionName;
    }
    else
    {
        return UserAction.Unknown;
    }
}
public enum UserAction
{
    Unknown = 0,
    View = 1,
    Control = 2,
    SysAdmin = 3,
}
[AttributeUsage(AttributeTargets.Method)]
public class RequestedAction : Attribute
{
    public UserAction ActionName { get; set; }
    public RequestedAction(UserAction action)
    {
        ActionName = action;
    }
}
1
On

I think you can use this code:

public class operationdispatcher : IDispatchMessageInspector
{
    List<Type> MyAttrybutes = new List<Type>() { typeof(behaviorattribute) };

    public object AfterReceiveRequest(ref System.ServiceModel.Channels.Message request, IClientChannel channel, InstanceContext instanceContext)
    {
        var serviceType = instanceContext.Host.Description.ServiceType;
        var operationName = OperationContext.Current.IncomingMessageHeaders.Action;
        var methodName = operationName.Substring(operationName.LastIndexOf("/") + 1);

        var method = serviceType.GetMethods().Where(m => m.Name == methodName && m.IsPublic).SingleOrDefault();
        var attributes = method.GetCustomAttributes(true).Where(a => MyAttrybutes.Contains(a.GetType()));

        foreach (var attribute in attributes)
        {
            // you might want to instantiate an attribute and do something
        }

        return null;
    }
}

Note: You use here the service implementation class, not the interface. If you use method.GetCustomAttributes(true) then you will get all the custom attributes on the specified method (those inherited from interface as well).