WCF CommunicationException при возврате данных - PullRequest
3 голосов
/ 10 марта 2011

Здесь, на работе, мы разработали API-интерфейс SOAP WCF, к которому можно обратиться извне. Поскольку одно из требований к API изменилось, я хотел добавить новый класс для этого API, чтобы сгенерировать правильные пути для определенных вызовов функций.

Наш API разделен на 3 отдельные библиотеки:

  • Один для объектов
  • Один для интерфейсов
  • Один для реализации.

Клиенты, конечно, получают первые два для работы в скриптах, сервер имеет все три.

Класс, который я хочу добавить в API, выглядит следующим образом:

namespace TenForce.Execution.API.Objects.Helpers
{
/// <summary>
/// <para>This interface defines the functionality available in the PathHelper for the API.</para>
/// </summary>
public interface IPathHelper
{
    string ApplicationFolder { get; }   // The HomeDataFolder for the application
    string CompanyHomeFolder { get; }   // The HomeDataFolder for the company.
    string CustomFolder { get; }        // The custom folder for professional services.
    string WikiFolder { get; }          // The WIKI folder to store pages.
    string AddinsFolder { get; }        // The AddinFolder to access the addins.
}
}

Реальная реализация класса выглядит примерно так:

using System.IO;
using System.Runtime.Serialization;
using TenForce.Execution.BUL;
using TenForce.Execution.Framework;

namespace TenForce.Execution.API.Implementation.Helpers
{
/// <summary>
/// <para>This class provides a direct implementation of the IPathHelper for the API implementation
/// and manages all the paths inside the DataHomeFolder structure for the TenForce application.</para>
/// </summary>
[DataContract]
public class PathHelper : Objects.Helpers.IPathHelper
{
    #region Private Fields

    private readonly ParameterBUL _mParameterBul;
    private const Parameter.ParameterId DataHomeFolderId = Parameter.ParameterId.DataHomeFolder;
    private const Parameter.ParameterId CompanyNameId = Parameter.ParameterId.CompanyName;

    #endregion

    #region Constructor

    /// <summary>
    /// <para>Creates a new instance of the PathHelper class</para>
    /// </summary>
    public PathHelper()
    {
        _mParameterBul = new ParameterBUL();
    }

    #endregion

    #region IPathHelper Members

    /// <summary>
    /// <para>Returns the absolute path to the DataHomeFolder of the TenForce Application.</para>
    /// </summary>
    [DataMember]
    public string ApplicationFolder
    {
        get
        {
            return CreatePath(_mParameterBul.GetParameterValue(DataHomeFolderId));
        }
    }

    /// <summary>
    /// <para>Returns the absolute path to the Company DataHomeFolder.</para>
    /// </summary>
    [DataMember]
    public string CompanyHomeFolder
    {
        get
        {
            return CreatePath(Path.Combine(ApplicationFolder, _mParameterBul.GetParameterValue(CompanyNameId)));
        }
    }

    /// <summary>
    /// <para>Returns the absolute path to the Company custom folder.</para>
    /// </summary>
    [DataMember]
    public string CustomFolder
    {
        get
        {
            return CreatePath(Path.Combine(CompanyHomeFolder, @"custom"));
        }
    }

    /// <summary>
    /// <para>Returns the absolute path to the Company wiki folder.</para>
    /// </summary>
    [DataMember]
    public string WikiFolder
    {
        get
        {
            return CreatePath(Path.Combine(CompanyHomeFolder, @"wiki"));
        }
    }

    /// <summary>
    /// <para>Returns the absolute path to the Company addins folder.</para>
    /// </summary>
    [DataMember]
    public string AddinsFolder
    {
        get
        {
            return CreatePath(Path.Combine(CompanyHomeFolder, @"addins"));
        }
    }

    #endregion

    #region Private Members

    /// <summary>
    /// <para>Checks if the specified path exists, and creates the path 
    /// if the system cannot find it.</para>
    /// </summary>
    /// <param name="path">The path to verify.</param>
    private static string CreatePath(string path)
    {
        if (!Directory.Exists(path))
            Directory.CreateDirectory(path);
        return path;
    }

    #endregion
}
}

Все это довольно простые вещи. Служба WCF создается нами динамически, используя фабрики и классы, доступные через .NET. Служба WCF отлично работает для всего кода, уже существующего внутри Службы.

Поэтому я решил добавить следующую строку в класс, который является нашим Сервисом:

    /// <summary>
    /// <para>Returns the PathHelper to construct the various paths for API Scripts.</para>
    /// </summary>
    /// <returns>An instance of the PathHelper.</returns>
    public Objects.Helpers.IPathHelper GetPathHelper()
    {
        return new Helpers.PathHelper();
    }

    #endregion

Когда я запускаю юнит-тесты, все тесты работают, кроме тех, которые проверяют функции PathHelper, все они заканчиваются тем же сообщением об ошибке / исключением:

Ошибка 1 TestCase 'TenForce.Execution.API.ImplementationTest / HelperTests / CheckApplicationFolderPath' не удалось: казнить System.ServiceModel.CommunicationException: удаленная конечная точка больше не распознает эту последовательность. Скорее всего, это связано с прерыванием работы на удаленной конечной точке. Значение wsrm: Identifier не является известным идентификатором Sequence. Надежный сеанс был сорван.

Трассировка стека серверов: в System.ServiceModel.Channels.ReliableRequestSessionChannel.SyncRequest.WaitForReply (TimeSpan timeout) в System.ServiceModel.Channels.RequestChannel.Request (сообщение-сообщение, время ожидания TimeSpan) в System.ServiceModel.Dispatcher.RequestChannelBinder.Request (сообщение-сообщение, время ожидания TimeSpan) в System.ServiceModel.Channels.ServiceChannel.Call (строковое действие, логический односторонний режим, операция ProxyOperationRuntime, Object [] ins, Object [] outs, TimeSpan timeout) в System.ServiceModel.Channels.ServiceChannel.Call (строковое действие, логический односторонний режим, операция ProxyOperationRuntime, Object [] ins, Object [] outs) в System.ServiceModel.Channels.ServiceChannelProxy.InvokeService (метод IMethodCallMessageCall, операция ProxyOperationRuntime) в System.ServiceModel.Channels.ServiceChannelProxy.Invoke (сообщение IMessage)

Исключение переброшено в [0]: в System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage (IMessage reqMsg, IMessage retMsg) в System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke (MessageData & msgData, тип Int32) в TenForce.Execution.API.Contracts.IAPI.GetPathHelper () в TenForce.Execution.API.ServiceClient.ServiceAPI.GetPathHelper () в c: \ Users \ arne.de.herdt \ Documents \ Trunk \ Robinson \ TenForce.Execution.API.ServiceClient \ ServiceAPI.cs: строка 163 в TenForce.Execution.API.ImplementationTest.HelperTests.CheckApplicationFolderPath () в C: \ Users \ arne.de.herdt \ Documents \ Trunk \ Robinson \ TenForce.Execution.API.ImplementationTest \ HelperTests.cs: строка 56 c: \ Users \ arne.de.herdt \ Documents \ Trunk \ Robinson \ TenForce.Execution.API.ServiceClient \ ServiceAPI.cs 163

Я не знаю, что происходит или чего мне не хватает. Код работает для того, что уже есть, но когда я добавил свой кусок, он становится бесполезным, но существующие функции продолжают работать. это мое, что вызывает проблемы.

Ответы [ 2 ]

1 голос
/ 10 марта 2011

Ошибка кажется мне странной, возможно, она связана с тем, как вы динамически генерируете сервисы.

Однако этот класс не сериализуем, свойства этого класса доступны только для чтения (не имеютнабор аксессуаров).Чтобы пометить свойство как DataMember, свойства должны иметь доступ к набору, даже если он помечен как закрытый.Из MSDN:

Примечание. Свойства, к которым был применен атрибут DataMemberAttribute, должны иметь поля get и set;они не могут быть только для получения или только для установки.

Документация DataMember

Единственное, что вы можете захотеть сериализовать в этом классе, - это переменная m_ParameterBul,поэтому отметив это как DataMember и удалив все остальные атрибуты DataMember из свойств только для чтения.

Вы должны заметить, что если m_ParameterBul не зависит от сервера, нет необходимости создавать этот класс на стороне сервера, потому чтовсе связано с клиентом.В этом случае вы должны создать его непосредственно на клиентах.

Надеюсь, это поможет!

/// <summary>
/// <para>This class provides a direct implementation of the IPathHelper for the API implementation
/// and manages all the paths inside the DataHomeFolder structure for the TenForce application.</para>
/// </summary>
[DataContract]
public class PathHelper : Objects.Helpers.IPathHelper
{
    #region Private Fields
    [DataMember]
    private readonly ParameterBUL _mParameterBul;
    private const Parameter.ParameterId DataHomeFolderId = Parameter.ParameterId.DataHomeFolder;
    private const Parameter.ParameterId CompanyNameId = Parameter.ParameterId.CompanyName;

    #endregion

    #region Constructor

    /// <summary>
    /// <para>Creates a new instance of the PathHelper class</para>
    /// </summary>
    public PathHelper()
    {
        _mParameterBul = new ParameterBUL();
    }

    #endregion

    #region IPathHelper Members

    /// <summary>
    /// <para>Returns the absolute path to the DataHomeFolder of the TenForce Application.</para>
    /// </summary>   
    public string ApplicationFolder
    {
        get
        {
            return CreatePath(_mParameterBul.GetParameterValue(DataHomeFolderId));
        }
    }

    /// <summary>
    /// <para>Returns the absolute path to the Company DataHomeFolder.</para>
    /// </summary>   
    public string CompanyHomeFolder
    {
        get
        {
            return CreatePath(Path.Combine(ApplicationFolder, _mParameterBul.GetParameterValue(CompanyNameId)));
        }
    }

    /// <summary>
    /// <para>Returns the absolute path to the Company custom folder.</para>
    /// </summary>
    public string CustomFolder
    {
        get
        {
            return CreatePath(Path.Combine(CompanyHomeFolder, @"custom"));
        }
    }

    /// <summary>
    /// <para>Returns the absolute path to the Company wiki folder.</para>
    /// </summary>
    public string WikiFolder
    {
        get
        {
            return CreatePath(Path.Combine(CompanyHomeFolder, @"wiki"));
        }
    }

    /// <summary>
    /// <para>Returns the absolute path to the Company addins folder.</para>
    /// </summary>    
    public string AddinsFolder
    {
        get
        {
            return CreatePath(Path.Combine(CompanyHomeFolder, @"addins"));
        }
    }

    #endregion

    #region Private Members

    /// <summary>
    /// <para>Checks if the specified path exists, and creates the path 
    /// if the system cannot find it.</para>
    /// </summary>
    /// <param name="path">The path to verify.</param>
    private static string CreatePath(string path)
    {
        if (!Directory.Exists(path))
            Directory.CreateDirectory(path);
        return path;
    }

    #endregion
}
0 голосов
/ 10 марта 2011

Благодаря отзывам от комментариев и awnser, решение состоит в том, чтобы переместить класс во вторую реализацию API, а не сделать его доступным через службу WCF.

Класс содержит функции и функции чтения.только свойства, поэтому класс не может быть сериализован службой WCF.Конечным результатом будет то, что его могут использовать только скрипты, а не сервис.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...