用于公开部分Web API的WCF服务
本文关键字:WCF 服务 API Web 开部 用于 | 更新日期: 2023-09-27 18:17:13
我的任务是创建一个只公开部分oData REST API的WCF服务。只有REST API允许的某些功能应该由WCF服务公开。(WCF服务基本上作为一个过滤器)。
我该怎么做呢?我知道我可以使用代理类调用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 。