【问题标题】:WCF Client not able to connect on some machinesWCF 客户端无法在某些机器上连接
【发布时间】:2014-05-19 17:00:58
【问题描述】:

我有一个简单的自托管 WCF 服务。我在远程服务器上运行此服务。我能够与在我的机器上运行的客户端进行通信(我是本地管理员)。 但是当我在不同的机器(非管理员)上运行相同的客户端时,他们无法通信。

我监控了资源管理器,我看到在每次服务调用和回调时都有两个随机本地端口处于打开状态。所以我无法打开特定的端口。

任何想法可能是什么原因或其他机器上的防火墙配置更改?

我对 WCF 很陌生。如果这是一个基本问题,请原谅我。

WCF 服务器代码

namespace CService
    {
    class Program
       {
       static void Main(string[] args) {

        Console.Title = "C Service";

        // Step 1 of the address configuration procedure: Create a URI to serve as the base address.
        Uri baseAddress = new Uri("http://" + GetServerIPPort.ServerIP + ":" + GetServerIPPort.Port + "/CService/Service");


        // Step 2 of the hosting procedure: Create ServiceHost
        ServiceHost selfHost = new ServiceHost(typeof(CSerice), baseAddress);

        try
        {
            // Step 3 of the hosting procedure: Add a service endpoint.
            selfHost.AddServiceEndpoint(typeof(ICService), new BasicHttpBinding(), "CService");

            // Step 4 of the hosting procedure: Enable metadata exchange.
            ServiceMetadataBehavior smb = new ServiceMetadataBehavior();
            smb.HttpGetEnabled = true;
            selfHost.Description.Behaviors.Add(smb);

            // Step 5 of the hosting procedure: Start (and then stop) the service.
            selfHost.Open();
            Console.WriteLine("The Coemet Service is ready and its listening on {0}", baseAddress.AbsoluteUri.ToString() + ":" + baseAddress.Port.ToString());

            Console.WriteLine("Press <ENTER> to terminate service.");
            Console.WriteLine();
            Console.ReadLine();

            // Close the ServiceHostBase to shutdown the service.
            selfHost.Close();
        }
        catch (CommunicationException ce)
        {
            Console.WriteLine("An exception occurred: {0}", ce.ToString());
            selfHost.Abort();
        }
    }
}

我在这个链接http://msdn.microsoft.com/en-us/library/ms733133(v=vs.110).aspx的帮助下生成了Proxy对象

我的客户端代码 sn-p 是这样的。

string serviceEndPointAddress = "http://" + GetServerIPPort.ServerIP + ":" +     GetServerIPPort.Port + "/CService/Service/CService";

            var remoteAddress = new System.ServiceModel.EndpointAddress(new Uri(serviceEndPointAddress));
            object rawOutput;
            using (var client = new CServiceClient(new BasicHttpBinding(), remoteAddress))
            {
                client.Endpoint.Binding.SendTimeout = new TimeSpan(0, 0, 0, 100);
                try
                {
                    rawOutput = client.GetData(Identifier, field, date);
                }
                catch (Exception e)
                {
                    errorMsg = e.ToString();
                }
            }\n

“client.GetData(Identifier, field, date)”出现错误

System.Runtime.Serialization.InvalidDataContractException: 类型 'System.Threading.Tasks.Task1[System.Object]' cannot be serialized. Consider marking it with the DataContractAttribute attribute, and marking all of its members you want serialized with the DataMemberAttribute attribute. If the type is a collection, consider marking it with the CollectionDataContractAttribute. See the Microsoft .NET Framework documentation for other supported types. at System.Runtime.Serialization.DataContract.DataContractCriticalHelper.ThrowInvalidDataContractException(String message, Type type) at System.Runtime.Serialization.DataContract.DataContractCriticalHelper.CreateDataContract(Int32 id, RuntimeTypeHandle typeHandle, Type type) at System.Runtime.Serialization.DataContract.DataContractCriticalHelper.GetDataContractSkipValidation(Int32 id, RuntimeTypeHandle typeHandle, Type type) at System.Runtime.Serialization.XsdDataContractExporter.GetSchemaTypeName(Type type) at System.ServiceModel.Dispatcher.DataContractSerializerOperationFormatter.CreatePartInfo(MessagePartDescription part, OperationFormatStyle style, DataContractSerializerOperationBehavior serializerFactory) at System.ServiceModel.Dispatcher.DataContractSerializerOperationFormatter.CreateMessageInfo(DataContractFormatAttribute dataContractFormatAttribute, MessageDescription messageDescription, DataContractSerializerOperationBehavior serializerFactory) at System.ServiceModel.Dispatcher.DataContractSerializerOperationFormatter..ctor(OperationDescription description, DataContractFormatAttribute dataContractFormatAttribute, DataContractSerializerOperationBehavior serializerFactory) at System.ServiceModel.Description.DataContractSerializerOperationBehavior.GetFormatter(OperationDescription operation, Boolean& formatRequest, Boolean& formatReply, Boolean isProxy) at System.ServiceModel.Description.DataContractSerializerOperationBehavior.System.ServiceModel.Description.IOperationBehavior.ApplyClientBehavior(OperationDescription description, ClientOperation proxy) at System.ServiceModel.Description.DispatcherBuilder.BindOperations(ContractDescription contract, ClientRuntime proxy, DispatchRuntime dispatch) at System.ServiceModel.Description.DispatcherBuilder.BuildProxyBehavior(ServiceEndpoint serviceEndpoint, BindingParameterCollection& parameters) at System.ServiceModel.Channels.ServiceChannelFactory.BuildChannelFactory(ServiceEndpoint serviceEndpoint, Boolean useActiveAutoClose) at System.ServiceModel.ChannelFactory.CreateFactory() at System.ServiceModel.ChannelFactory.OnOpening() at System.ServiceModel.Channels.CommunicationObject.Open(TimeSpan timeout) at System.ServiceModel.ChannelFactory.EnsureOpened() at System.ServiceModel.ChannelFactory1.CreateChannel(EndpointAddress address, Uri via) 在 System.ServiceModel.ClientBase1.CreateChannel() at System.ServiceModel.ClientBase1.CreateChannelInternal() 在 System.ServiceModel.ClientBase`1.get_Channel() at CServiceClient.GetData(String Identifier, String field, DateTime date)

【问题讨论】:

  • 问:您遇到了哪些具体错误?请发布确切的错误消息(如果可能,请发布生成消息的相应代码行)。
  • 也请分享 CService 实现。该服务可能需要授权。
  • 如果您还可以发布您的 ICService 代码,并且如果您的数据传输对象未在同一文件中定义,请也发布。
  • CService 只有一个方法GetData,它是从ICSerive 接口派生的。什么是服务授权?我对 WCF 世界比较陌生。
  • @FoggyDay 我已将堆栈跟踪添加到问题中。

标签: c# wcf


【解决方案1】:

在 .NET 4.5 中,WCF 中新增了对基于任务的异步操作的支持。当您使用 VS 2012 或更高版本在您的开发机器上生成代理时 - 它可以默认包含这些。

现在您使用的新机器可能在 .NET 4.0 上运行,因此不知道如何处理基于任务的异步操作 - 因此出现异常。

这是一个非常简单的修复,要支持运行 .NET 4.0 的客户端,您只需在 服务参考设置中执行以下任一操作:

  1. 取消选中允许生成异步操作
  2. 选择生成异步操作而不是生成基于任务的操作

特别感谢blog post

【讨论】:

  • 为了使用 .Net 4.0 生成代理,我使用了 .Net 4.0 SDK 的 svcutil.exe 并解决了问题。谢谢!!
【解决方案2】:

根据异常,您正在传递一个不可序列化的对象。我怀疑这是以下代码行中的标识符:

rawOutput = client.GetData(Identifier, field, date);

根据堆栈跟踪,CService 需要两个字符串和一个日期时间:

System.ServiceModel.ClientBase`1.get_Channel() 在 CServiceClient.GetData(String Identifier, String field, DateTime date)

如果您需要使用 WCF 传递自定义对象(数据传输对象),您应该使用类的 DataContractAttribute 属性和每个成员的 DataMemberAttribute,如下所示:

[DataContract]
public class Identifier
{
    [DataMember]
    public string Id {get;set;}
}

【讨论】:

  • 我可以从我的机器连接到此服务,但问题出在另一台机器上。序列化错误不是特定于机器的。
  • 所以你是在暗示异常并不代表潜在的问题?
【解决方案3】:

我也面临同样的问题,当我在 4.5 更高的框架上创建 WCF 服务并尝试在 IIS 8(即应用程序池 4.0)上部署时,上述步骤并没有解决我的问题,所以我重新创建了我在框架 4.0 中从头开始的完整解决方案并重新部署了它。在使用服务时,按照上述步骤取消选中“允许生成异步操作”解决了我的问题。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-01-29
    • 1970-01-01
    • 2014-11-29
    • 1970-01-01
    • 2013-02-22
    • 1970-01-01
    • 1970-01-01
    • 2011-11-26
    相关资源
    最近更新 更多