Служба WCF для предоставления части веб-API

Мне было поручено создать службу WCF, которая предоставляет только часть API REST oData. Предполагается, что Служба WCF предоставляет только определенные функции, разрешенные REST API. (Служба WCF в основном действует как фильтр).

Каким может быть мой подход к этому? Я знаю, что могу вызвать службу WCF с помощью прокси-классов. Но это будут только прямые вызовы метода. Я не хочу отдельную функцию для каждой операции. Есть ли лучший способ?

1 ответ

  1. Можно выбрать, какие операции предоставляются через WebAPI добавление атрибута [WebGet] в контракте операции.

    [OperationContract]
    [WebGet]
    string Method2(string s);
    

    Но если вы предоставляете сервис через net.tcp нет способа по умолчанию отключить некоторые для этого протокола.

    Для управления этой задачей необходимо написать пользовательское поведение, которое будет проверять, какой протокол используется и позволит выполнять вызов или исключение.

    Начните с пользовательского атрибута, который определяет операцию, которая может быть выполнена через выбранный канал.

    [OperationContract]
    [WebGet]
    [WcfAllowed]
    string Method1(string s);
    

    Далее нам нужен инспектор сообщений, который будет использовать наш пользовательский атрибут.
    Mmessage инспектор

    • проверяет выбранный протокол (net.протокол TCP.)
    • возвращает имя вызываемого метода
    • находит в интерфейсном методе
    • проверяет, помечен ли метод нашим пользовательским атрибутом
    • если не бросает исключение

    код ниже:

    public class DispatchMessageInspector : IDispatchMessageInspector
    {
        public object AfterReceiveRequest(ref Message request, IClientChannel channel, InstanceContext instanceContext)
        {
            if (channel is IServiceChannel serviceChannel)
            {
                if (serviceChannel.ListenUri.Scheme == "net.tcp")
                {
                    string methodName=request.Headers.Action.Split('/').Last();
                    TypeInfo serviceType = instanceContext.Host.Description.ServiceType as TypeInfo;
                    foreach (var @interface in serviceType.ImplementedInterfaces)
                    {
                        var method = @interface.GetMethod(methodName);
                        if (method != null)
                        {
                            var attributes = method.GetCustomAttributes().Where(x => x.GetType() == typeof(WcfAllowedAttribute)).FirstOrDefault();
                            if (attributes == null)
                            {
                                throw new OnyWebApiException($"Method which was invoked: {methodName}");
                            }
                        }
                    }
                }
            }
            return request;
        }
    
        public void BeforeSendReply(ref Message reply, object correlationState)
        {
    
        }
     }
    

    Последний элемент объявления-это подключение нашего инспектора сообщений к сервису. Для этого нам нужно поведение сервиса.

    public class CustomServiceBehavior : Attribute, IServiceBehavior
    {
        public void AddBindingParameters(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase, Collection<ServiceEndpoint> endpoints, BindingParameterCollection bindingParameters)
        {
        }
    
        public void ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
        {
           foreach(ChannelDispatcher channelDispatcher in serviceHostBase.ChannelDispatchers)
            {
                foreach (var endpointDispatcher in channelDispatcher.Endpoints)
                {
                    endpointDispatcher.DispatchRuntime.MessageInspectors.Add(new DispatchMessageInspector());
                }
            }
        }
    
        public void Validate(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
        {
    
        }
    }
    

    Поведение службы должно быть подключено к службе. Самый простой способ-просто отметить сервис атрибутом:

    [CustomServiceBehavior]
    public class CustomService : ICustomContract
    {
        public string Method1(string s)
        {
            return s;
        }
    
        public string Method2(string s)
        {
            return s;
        }
    }
    

    Я создал решение, чтобы показать его в действии. Если вы заинтересованы, пожалуйста, проверить филиал OnlyNetTcp .