c# - 使用 WS-MetadataExchange 为外部客户端和 WcfTestClient 公开 Service Fabric 中的 WCF/TCP 终结点

标签 c# wcf azure azure-service-fabric

我有一个无状态服务,正在将一些 CloudService WCF 端点迁移到其中。这些 enpoint 是公开可用的,并且要求我能够使用 WS-MetadataExchange 通过 Visual Studio 项目以及 References > Add Service Reference 来发现它们的属性强>WCFTestClient。

我已经遵循了一些教程并设置了测试端点:

 <Endpoint Protocol="tcp" Name="WcfServiceEndpoint" Type="Input" Port="8081" />

以及服务契约(Contract)

[ServiceContract]
public interface ITestContract
{
    [OperationContract]
    int TestMethod(int value1, int value2);
}

方法:

public class TestService : ITestContract
{
    public int TestMethod(int value1, int value2)
    {
        var result = value1 + value2;
        return result;
    }
}

以及服务监听器覆盖:

protected override IEnumerable<ServiceInstanceListener> CreateServiceInstanceListeners()
    {

return new[] { new ServiceInstanceListener((context) =>
    new WcfCommunicationListener<ITestContract>(
        this.Context,
        new TestService(),
        WcfUtility.CreateTcpClientBinding(),
        "WcfServiceEndpoint"
    )
)};

在我之前的项目(我正在从中迁移)中,我设置了自定义 ServiceHost 对象,并且能够自定义它们的绑定(bind)/Url。我能够让客户发现服务很好。我需要能够以相同的方式公开此服务,以便 WcfTestClient 以及 References > Add Service Reference 可以使用 WS-MetadataExchange< 发现其属性/强>。就目前而言,我什至无法控制服务路径!

理想情况下我仍想使用ServiceHost:

var host = new ServiceHost(ITestContract);
host.AddServiceEndpoint(TestService, new NetTcpBinding(SecurityMode.None), "net.tcp://...", new Uri("net.tcp://..."));
host.Description.Behaviors.Remove(typeof(ServiceDebugBehavior));
host.Description.Behaviors.Add(new ServiceDebugBehavior { IncludeExceptionDetailInFaults = true });
host.Open();
<小时/>

更新

根据VipulM-MSFT的建议(如下)我现在首先创建通信监听器:

var testCommunicationListener = new WcfCommunicationListener<ITestContract>(
    this.Context,
    new TestService(),
    WcfUtility.CreateTcpClientBinding(),
    "WcfServiceEndpoint"
);

然后修改 ServiceHost 对象以允许 MetadataExchange 行为:

ServiceMetadataBehavior metaDataBehavior = new ServiceMetadataBehavior();
testCommunicationListener.ServiceHost.Description.Behaviors.Add(metaDataBehavior);

以及允许错误中的异常详细信息:

testCommunicationListener.ServiceHost.Description.Behaviors.Remove(typeof(ServiceDebugBehavior));
testCommunicationListener.ServiceHost.Description.Behaviors.Add(new ServiceDebugBehavior { IncludeExceptionDetailInFaults = true });

然后我创建一个服务端点(带有我想要的服务路径):

testCommunicationListener.ServiceHost.AddServiceEndpoint(typeof(ITestContract), new NetTcpBinding(SecurityMode.None), "net.tcp://localhost:8081/Services/Tests", new Uri("net.tcp://localhost:8081/Services/Tests"));

以及 MexEndpoint(允许通过 TCP 进行 MetaExchange 绑定(bind)):

Binding mexBinding = MetadataExchangeBindings.CreateMexTcpBinding();
testCommunicationListener.ServiceHost.AddServiceEndpoint(typeof(IMetadataExchange), mexBinding, "net.tcp://localhost:8081/Services/Tests/mex", new Uri("net.tcp://localhost:8081/Services/Tests/mex"));

最后我将监听器分配给无状态服务:

return new[] { new ServiceInstanceListener((context) => testCommunicationListener)};

当我将其推送到本地集群时,出现以下错误:

The Service contains multiple ServiceEndpoints with different ContractDescriptions which each have Name='ITestContract' and Namespace='http://tempuri.org/'. Either provide ContractDescriptions with unique Name and Namespaces, or ensure the ServiceEndpoints have the same ContractDescription instance.

我想也许我需要删除默认端点以避免这种冲突,所以我尝试了:

 testCommunicationListener.ServiceHost.Description.Endpoints.RemoveAt(0);

调用之前:

testCommunicationListener.ServiceHost.AddServiceEndpoint(typeof(ITestContract), new NetTcpBinding(SecurityMode.None), "net.tcp://localhost:8081/Services/Tests", new Uri("net.tcp://localhost:8081/Services/Tests"));
Binding mexBinding = MetadataExchangeBindings.CreateMexTcpBinding();
testCommunicationListener.ServiceHost.AddServiceEndpoint(typeof(IMetadataExchange), mexBinding, "net.tcp://localhost:8081/Services/Tests/mex", new Uri("net.tcp://localhost:8081/Services/Tests/mex"));

这给了我以下错误:

Replica had multiple failures in API call: IStatelessServiceInstance.Open(); Error = System.NullReferenceException (-2147467261) Object reference not set to an instance of an object. at Microsoft.ServiceFabric.Services.Communication.Wcf.Runtime.WcfCommunicationListener1.b__0(IAsyncResult ar) at System.Threading.Tasks.TaskFactory1.FromAsyncCoreLogic(IAsyncResult iar, Func2 endFunction, Action1 endAction, Task`1 promise, Boolean requiresSynchronization)

我尝试了一些其他的变体,但得到了类似的结果...

我还尝试在默认绑定(bind)上允许 MetadataExchange 行为(无需创建任何其他端点)。但在这种情况下,我如何知道我的端点 url 是什么?我尝试使用 net.tcp://localhost:8081/TestService (应该是默认值),但我无法从控制台应用程序或 WcfTestClient。

<小时/>

更新2

我能够根据需要托管我的 WCF 端点,只需将 MetadataExchangeBinding 添加为附加端点并在以下范围内分配我所需的服务路径:

Binding mexBinding = MetadataExchangeBindings.CreateMexTcpBinding();
testCommunicationListener.ServiceHost.AddServiceEndpoint(typeof(IMetadataExchange), mexBinding, "net.tcp://localhost:8081/Services/Tests/mex", new Uri("net.tcp://localhost:8081/Services/Tests/mex"));

最佳答案

您可以在打开通信监听器之前通过访问 host 属性来自定义 ServiceHost。

https://learn.microsoft.com/en-us/dotnet/api/microsoft.servicefabric.services.communication.wcf.runtime.wcfcommunicationlistener-1#Microsoft_ServiceFabric_Services_Communication_Wcf_Runtime_WcfCommunicationListener_1_ServiceHost

默认情况下,代码添加了一些行为,包括服务调试和限制行为,因此,如果删除 SDK 中提供的 WCF 客户端堆栈可能无法正常运行。

关于c# - 使用 WS-MetadataExchange 为外部客户端和 WcfTestClient 公开 Service Fabric 中的 WCF/TCP 终结点,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42795147/

相关文章:

c# - 即使在 using 语句中,FileStream 也不会关闭

wcf - VS2013无法在解决方案中添加WCF服务引用

asp.net - 从 azure 存储下载 blob 时提示“保存”对话框

azure - 从 AddAzureADB2C 切换到 Microsoft.Identity.Web 时的身份验证链接是什么?

Azure SQL - 异地复制会导致性能影响吗?

c# - 即使我立即获得返回任务的结果,HttpClient 是否会旋转一个新线程?

c# - 在 C# 中将 XML 反序列化为类 obj

c# - 过滤连续数据,如何去除瞬变?

c# - C++ & C#,如何在 C++ 中创建包装器 dll,以便 C# 调用 C++ dll 中的实例函数?

javascript - 我得到一个 JSON/Javascript 对象,因为我可以在控制台中看到它,但如何让它序列化并使我的数据绑定(bind)到我的 Ui 元素?