【问题标题】:WCF service call returns data but receiver gets nullWCF 服务调用返回数据,但接收者为空
【发布时间】:2016-11-10 02:18:15
【问题描述】:

我正在调试一个 wcf 服务,该服务基本上连接到我的 sql 数据库,收集数据并以列表的形式返回数据(即在被调用时返回给调用者)。然而,我的客户(调用者)得到空数据,即使当我单步执行 wcf 代码时,它正在返回数据。

这是调用 wcf 服务的客户端代码。请注意,它是在这里,当我设置一个断点并查看

GetServerUpdatesSyncOthers

调用返回后,我的列表不应该为空(是的,客户端在 vb.net 中,但 wcf 服务在 c# 中)

  Dim svc As PocketPCServerClient = GetServiceClient()

  Dim updates As ServerUpdatesSyncDTO = svc.GetServerUpdatesSyncOthers(myDeviceId, timestamps.ToArray, operatorName, Me.IdMethodName(idMethod), idMethodValue, destinationHub, withLocationGroup)

为了记录,ServerUpdatesSyncDTO 在客户端看起来像这样:

<DataContract()>
Public Class ServerUpdatesSyncDTO
Public Const EMPLOYEES_PROCESS_MAXIMUM_NONE As Integer = 0
Public Const EMPLOYEES_PROCESS_MAXIMUM_ALL As Integer = -1

<DataMember()>
Public Property SystemDateTimeUtc As DateTime
<DataMember()>
Public Property SyncTimestamps As List(Of SyncTimestampDTO)
<DataMember()>
Public Property DeviceSettings As List(Of DeviceSettingDTO)
<DataMember()>
Public Property Couriers As List(Of CourierDTO)
<DataMember()>
Public Property Validation As List(Of ValidationDTO)
<DataMember()>
Public Property NameVariants As List(Of String)
<DataMember()>
Public Property NameScrubs As List(Of String)
<DataMember()>
Public Property Notes As List(Of String)
<DataMember()>
Public Property Notifications As List(Of NotifyDTO)
<DataMember()>
Public Property Locations As List(Of LocationDTO)
<DataMember()>
Public Property UpsValids As List(Of UpsValidDTO)
<DataMember()>
Public Property StatusCodes As List(Of StatusCodeDTO)
<DataMember()>
Public Property HubRecon As List(Of String)
<DataMember()>
Public Property HubNames As List(Of String)
<DataMember()>
Public Property ExtCustomFieldNames As CustomFieldHeadersDTO
<DataMember()>
Public Property HoldPickupLocations As List(Of HoldPickupDTO)
<DataMember()>
Public Property EmployeeUpdates As List(Of EmployeeDTO)
<DataMember()>
Public Property EmployeeInserts As List(Of EmployeeDTO)
<DataMember()>
Public Property EmployeeDeletes As List(Of EmployeeDTO)
<DataMember()>
Public Property EmployeesProcessMore As Boolean
<DataMember()>
Public Property EmployeesProcessMoreIdGreaterThan As String
End Class

在 wcf 服务端,一个 c# 版本的 ServerUpdatesSyncDTO:

  [DataContract]
public class ServerUpdatesSyncDTO
{
    public const int EMPLOYEES_PROCESS_MAXIMUM_NONE = 0;
    public const int EMPLOYEES_PROCESS_MAXIMUM_ALL = -1;

        [DataMember]
        public DateTime SystemDateTimeUtc { get; set; }
        [DataMember]
        public List<SyncTimestampDTO> SyncTimestamps { get; set; }
        [DataMember]
        public List<DeviceSettingDTO> DeviceSettings { get; set; }
        [DataMember]
        public List<CourierDTO> Couriers { get; set; }
        [DataMember]
        public List<ValidationDTO> Validation { get; set; }
        [DataMember]
        public List<string> NameVariants { get; set; }
        [DataMember]
        public List<string> NameScrubs { get; set; }
        [DataMember]
        public List<string> Notes { get; set; }
        [DataMember]
        public List<NotifyDTO> Notifications { get; set; }
        [DataMember]
        public List<LocationDTO> Locations { get; set; }
        [DataMember]
        public List<UpsValidDTO> UpsValids { get; set; }
        [DataMember]
        public List<StatusCodeDTO> StatusCodes { get; set; }
        [DataMember]
        public List<EmployeeDTO> EmployeeUpdates { get; set; }
        [DataMember]
        public List<EmployeeDTO> EmployeeInserts { get; set; }
        [DataMember]
        public List<EmployeeDTO> EmployeeDeletes { get; set; }
        [DataMember]
        public bool EmployeesProcessMore { get; set; }
        [DataMember]
        public string EmployeesProcessMoreIdGreaterThan { get; set; }
        [DataMember]
        public List<string> HubRecon { get; set; }
        [DataMember]
        public List<string> HubNames { get; set; }
        [DataMember]
        public CustomFieldHeadersDTO ExtCustomFieldNames { get; set; }
        [DataMember]
        public List<HoldPickupDTO> HoldPickupLocations { get; set; }
    }

最后是客户端调用的wcf服务方法。请记住,我可以在这里设置一个断点并单步执行,我看到这个方法每次都返回有效数据,没有异常。例如,其中一项,Couriers 列表。当它返回时,我在 wcf 端的列表中有 48 个,但客户端在调用返回后在“更新”中为 Couriers 显示 null。

 public ServerUpdatesSyncDTO GetServerUpdatesSyncOthers(string deviceId, List<SyncTimestampDTO> syncTimestamps, string operatorName, string locationCriteriaType, string locationCriteria, string destinationHub, bool withLocationGroup)
    {
        var thisMethodName = MethodBase.GetCurrentMethod().Name;
        CurrentTaskName = thisMethodName;
        CurrentDeviceId = deviceId;

        if (string.IsNullOrWhiteSpace(deviceId))
            throw new FaultException(string.Format("Argument null [{0}]", "deviceId"));
        if (syncTimestamps == null)
            throw new FaultException(string.Format("Argument null [{0}]", "syncTimestamps"));
        if (string.IsNullOrWhiteSpace(operatorName))
            throw new FaultException(string.Format("Argument null [{0}]", "operatorName"));
        if (locationCriteriaType.ToUpper() != LOCATION_ID_METHOD_BY_EMPLOYEE && locationCriteriaType.ToUpper() != LOCATION_ID_METHOD_BY_NAME)
            throw new FaultException(string.Format("locationCriteriaType [{0}] is invalid. Valid values are {1} or {2}", locationCriteriaType, LOCATION_ID_METHOD_BY_EMPLOYEE, LOCATION_ID_METHOD_BY_NAME));
        if (string.IsNullOrWhiteSpace(locationCriteria) & locationCriteriaType != LOCATION_ID_METHOD_BY_EMPLOYEE)
            throw new FaultException(string.Format("Argument null [{0}]", "locationCriteria"));

        var result = new ServerUpdatesSyncDTO();

        try
        {
            WriteServerLog(SERVER_TASK_BEGIN);
            using (var conn = GetSQLConnection())
            {
                var homeLocationCode = 0;
                var loginLocationCode = 0;
                List<int> groupLocationCodes;

                if ((locationCriteriaType == LOCATION_ID_METHOD_BY_EMPLOYEE) && (string.IsNullOrWhiteSpace(locationCriteria)))
                {
                    locationCriteria = operatorName;
                }

                loginLocationCode = GetLocationCode(conn, null, locationCriteriaType, locationCriteria);
                groupLocationCodes = GetGroupLocationCodes(conn, null, loginLocationCode);

                if (locationCriteriaType == LOCATION_ID_METHOD_BY_EMPLOYEE)
                {
                    homeLocationCode = loginLocationCode;
                }
                else
                {
                    homeLocationCode = GetLocationCode(conn, null, LOCATION_ID_METHOD_BY_EMPLOYEE, operatorName);
                }

                var lastUpdateUtc = GetLocationSyncDateTimeUtc(loginLocationCode, syncTimestamps);
                result.Couriers = GetCourierUpdates(conn, lastUpdateUtc, loginLocationCode);
                result.Validation = GetValidationUpdates(conn, lastUpdateUtc, loginLocationCode);
                result.HubNames = GetHubNames(conn, lastUpdateUtc, loginLocationCode);

                result.NameVariants = GetNameVariantUpdates(conn, lastUpdateUtc);
                result.NameScrubs = GetNameScrubUpdates(conn, lastUpdateUtc);
                result.Notes = GetNotesUpdates(conn, loginLocationCode);
                result.Notifications = GetNotifyUpdates(conn, lastUpdateUtc);
                result.Locations = GetLocationUpdates(conn, lastUpdateUtc);
                result.UpsValids = GetUpsValidUpdates(conn, lastUpdateUtc);
                result.StatusCodes = GetStatusCodeUpdates(conn, lastUpdateUtc);
                result.ExtCustomFieldNames = GetExtendedCustomFieldHeaderUpdates(conn, lastUpdateUtc);

                if (Properties.Settings.Default.HoldForPickupUpdates)
                {
                    result.HoldPickupLocations = GetHoldPickupUpdates(conn);
                }
                else
                {
                    result.HoldPickupLocations = new List<HoldPickupDTO>();
                }

                if (!string.IsNullOrWhiteSpace(destinationHub))
                {
                    result.HubRecon = GetHubReconUpdates(conn, destinationHub);
                }
                else
                {
                    result.HubRecon = new List<string>();
                }

                result.DeviceSettings = GetDeviceSettingUpdates(conn, loginLocationCode, deviceId);

                result.SystemDateTimeUtc = DateTime.Now.ToUniversalTime();
                result.SyncTimestamps = GetSyncTimestampUpdates(result.SystemDateTimeUtc, syncTimestamps, loginLocationCode, groupLocationCodes, withLocationGroup);

            }

            WriteServerLog(SERVER_TASK_COMPLETE, true, true);
            return result;

        }
        catch (FaultException ex)
        {
            throw ex;
        }
        catch (Exception ex)
        {
            string exText = FormatException(ex, string.Format("{0}:{1}", Assembly.GetExecutingAssembly().GetName().Name, thisMethodName));
            WriteServerLog(thisMethodName, ServerLogDTO.LogTypeEnum.Critical, exText, ServerLogDTO.EventDataFormatEnum.MultilineText);
            throw new FaultException(exText);
        }
    }  

所以,我认为虽然客户端是 vb 并且服务是 wcf 应该没问题,但一定存在某种不匹配,vb 在返回数据时不喜欢这种不匹配?我只是没看到。数据类型都是一样的,都是列表。

提前感谢您的帮助!

【问题讨论】:

  • 我的建议是创建一些示例数据并使用您的 vb 数据合同将其序列化为 xml....然后获取相同的数据并使用您的 C# 数据合同将其序列化为 xml....然后得到一个diff 工具并比较 xml,如果它们不同,您需要对合同进行更改以使其相同
  • 还有什么理由你没有为你的数据契约创建一个类库然后在你的客户端引用那个程序集而不是复制数据契约?
  • Mick,感谢您的建议,非常有道理,现在就试试。我假设是这样的stackoverflow.com/questions/11142280/…
  • 至于你的问题,客户端和服务器都是前段时间用vb写的。我最近的任务是转换服务....现在。如果我进行更改,此时将很难更新所有现有的客户端软件。
  • 我会认为如果 C# 数据合同与 VB 合同同名,只需删除 VB 合同的代码,然后在您的 vb 代码中添加程序集引用和使用语句

标签: c# .net vb.net web-services wcf


【解决方案1】:

我发现了问题。通常,客户端具有 wcf 服务的服务引用,它可以从服务中提取 WSDL 并为您创建客户端类。这可以通过转到 References > Add service Reference 并指向 Web 服务地址来完成。

有两点需要注意,这两点对我来说都是一个问题。 1.您可以右键单击服务参考并进行更新。这将下拉并更新服务引用。如果对 WCF 服务进行了更改,那么这是必须的,以便引用所述服务的客户端也得到更新。否则,界面会有所不同,事情将无法正常工作。 2. 当您添加或编辑服务参考时,可以选择您使用的集合类型。默认情况下,我的被选为数组。但是,在 WCF 服务中,我没有使用数组,而是使用列表。如果您的服务参考/客户端代码不匹配,集合将被破坏。如果您更新您的服务参考,您应该会收到警告,但在我的情况下,我也没有更新我的服务参考。

因此,在我更新了我的服务参考之后,我还选择了我使用的是列表而不是数组。之后,一切都按预期进行。

希望这会有所帮助。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-06-01
    • 2016-06-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-06-20
    相关资源
    最近更新 更多