用于公开部分Web API的WCF服务

本文关键字:WCF 服务 API Web 开部 用于 | 更新日期: 2023-09-27 18:17:13

我的任务是创建一个只公开部分oData REST API的WCF服务。只有REST API允许的某些功能应该由WCF服务公开。(WCF服务基本上作为一个过滤器)。

我该怎么做呢?我知道我可以使用代理类调用WCF服务。但那些只是直接的方法调用。我不希望每个操作都有一个单独的函数。有没有更好的办法?

用于公开部分Web API的WCF服务

您可以选择通过WebApi在操作契约上添加属性[WebGet]来公开哪些操作。

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

但是如果你通过网络公开服务。TCP协议没有默认的禁用方式。

要管理此任务,您需要编写自定义行为,该行为将检查使用的协议,并允许执行调用或抛出异常。

从定义可通过所选通道执行的操作的自定义属性开始。

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

接下来我们需要消息检查器,它将使用我们的自定义属性。Mmessage检查器

  • 检查选择的协议(net.tcp)。
  • 获取被调用的方法名
  • 在接口方法
  • 中查找
  • 检查方法是否被标记为自定义属性
  • if not抛出异常
下面的代码:

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)
    {
    }
}

服务行为需要连接到服务。最简单的方法就是用attribute:

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

我创建了解决方案来展示它在行动。如果您有兴趣,请查看分支 onlynetttcp