Исключение NetNamedPipeBinding ActionNotSupportedException

#c# #.net #wcf

#c# #.net #wcf

Вопрос:

Я запускаю службу, которая выглядит как пример MS Calculator. Это интерфейс контракта ServiceContract.

 [ServiceContract(Namespace = "http://localhost:8000/Calculator")]
public interface ICalculator
{
    [OperationContract]
    double Add(double n1, double n2);
    [OperationContract]
    double Subtract(double n1, double n2);
    [OperationContract]
    double Multiply(double n1, double n2);
    [OperationContract]
    double Divide(double n1, double n2);
}
 

Я настроил службу следующим образом:

 public partial class Service1: ServiceBase
{
    private static readonly string sNameOfService = "CalculatorService";
    public static string NameOfService
    {
        get { return sNameOfService; }
    }

    public ServiceHost serviceHost = null;

    public Service1()
    {
        InitializeComponent();

        this.ServiceName = sNameOfService;
        this.CanStop = true;
        this.CanPauseAndContinue = false;
        this.AutoLog = true;
    }

    protected override void OnStart(string[] args)
    {
        if (serviceHost != null)
            serviceHost.Close();

        Uri[] baseAddress = new Uri[]{
      new Uri("net.pipe://localhost")};

        string PipeName = "Calculator";

        serviceHost = new ServiceHost(typeof(CalculatorImplementation), 

        serviceHost.AddServiceEndpoint(typeof(ICalculator), new NetNamedPipeBinding(), PipeName);

        serviceHost.Open();
    }

    protected override void OnStop()
    {
        if (serviceHost != null amp;amp; serviceHost.State != CommunicationState.Closed)
        {
            serviceHost.Close();
            serviceHost = null;
        }
    }
}
 

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

 public interface ICalculator
{
    // die einzelnen Teile können auch als Vorgänge bzw. Kanäle verstanden werden
    // öffentliche Teile des Interfaces definieren
    // diese werden durch das OperationContract Attribut identifiziert
    [OperationContract]
    double Add(double n1, double n2);
    [OperationContract]
    double Subtract(double n1, double n2);
    [OperationContract]
    double Multiply(double n1, double n2);
    [OperationContract]
    double Divide(double n1, double n2);
}

class Program
{
    static void Main(string[] args)
    {
        ChannelFactory<ICalculator> pipeFactory = new ChannelFactory<ICalculator>(new NetNamedPipeBinding(), new EndpointAddress("net.pipe://localhost/Calculator"));

        ICalculator pipeProxy = pipeFactory.CreateChannel();

        double erg = pipeProxy.Add(5, 6);

        Console.WriteLine("Ergebnis: {0}", erg.ToString());
        Console.ReadLine();
    }
}
 

Но я получаю ActionNotSupportedException при попытке вызвать «pipeProxy.Add()», и я понятия не имею, почему это происходит.
Мой сервер настроен неправильно, или я что-то не так в клиенте, или я пропустил установку некоторых необходимых атрибутов? Я просмотрел несколько примеров с использованием именованных каналов, но не нашел ничего, что помогло бы мне решить мою проблему.

Кроме того, я спрашивал себя, в чем разница и где я должен использовать реализацию ServiceHost и реализацию NamedPipeClientStream / NamedPipeServerStream?

Ответ №1:

ActionNotSupportedException выдается, когда ваш клиент использует действие SOAP, которое неизвестно серверу. По умолчанию имена действий SOAP выводятся из типов сервисных контрактов и операционных контрактов.

В вашем примере я вижу, что контракт определен дважды. Означает ли это, что и служба, и клиент имеют свое собственное определение ICalculator ? В таком случае без дальнейших усилий эти два контракта не совпадают, потому что они, скорее всего, находятся в разных пространствах имен, и ваш первый контракт определяет свое собственное пространство имен, тогда как второй — нет. Если вы хотите использовать один и тот же интерфейс, поместите его в отдельную сборку и ссылайтесь на сборку как из службы, так и из клиента. В противном случае вам придется просмотреть ServiceContract OperationContract атрибуты и и убедиться, что значения для Namespace , Action и ReplyAction одинаковы в обоих интерфейсах.

Комментарии:

1. Спасибо! Это решение моей проблемы! Но мне интересно, есть ли другой способ подключения к конечной точке, фактически не зная, что это EndpointAddress, здесь: net.pipe://localhost/Calculator . Имеет ли это какое-то отношение к ServiceMetadataBehavior, который заполняет конечную точку внешним миром?