【问题标题】:WCF Service to expose part of a Web APIWCF 服务公开 Web API 的一部分
【发布时间】:2016-11-08 21:59:33
【问题描述】:

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

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

【问题讨论】:

  • “我不希望每个操作都有单独的函数” - 为什么?
  • 因为可能有太多的操作。我正在尝试仅公开 Dynamics CRM Web API 的一部分。
  • 但是它们会在代理中为您生成,然后您只需公开您想要的?

标签: c# web-services rest wcf dynamics-crm


【解决方案1】:

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

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

但是,如果您通过 net.tcp 公开服务,则没有默认方法可以禁用此协议的某些服务。

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

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

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

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

  • 检查所选协议 (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;
    }
}

我创建了solution 来展示它。如果您有兴趣,请查看分支 OnlyNetTcp

【讨论】:

    猜你喜欢
    • 2019-07-17
    • 2014-12-02
    • 2011-10-30
    • 1970-01-01
    • 2011-08-18
    • 1970-01-01
    • 2016-09-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多