Служба сеансов WCF, размещенная в приложении ASP.NET MVC 2.0 - PullRequest
1 голос
/ 23 июня 2010

У меня есть необходимость для размещения службы WCF с использованием механизма сеанса WCF.

Я прочитал http://msdn.microsoft.com/en-us/library/ms733040.aspx, но этого недостаточно ...

Мой простой сценарий:

У меня есть решение с 4 проектами.

Первый - SessionWCF.Base, это простая библиотека классов, которая содержит базовый интерфейс IServiceBase для моей службы.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel;

namespace SessionWCF.Base
{
    [ServiceContract(SessionMode = SessionMode.Required)]
    public interface IServiceBase
    {
        [OperationContract(IsInitiating = true, IsTerminating = false)]
        void BeginSession(string message);

        [OperationContract(IsInitiating = false, IsTerminating = false)]
        string GetMessage(int number);

        [OperationContract(IsInitiating = false, IsTerminating = true)]
        void EndSession();
    }
}

Второй - SessionWCF.Lib, это библиотека классов WCF, которая содержит интерфейс службы ISessionService и класс службы SessionService, имеет ссылку на проект SessionWCF.Base

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel;
using SessionWCF.Base;

namespace SessionWCF.Lib
{
    [ServiceContract(SessionMode = SessionMode.Required)]
    public interface ISessionService : IServiceBase
    {
    }
}

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel;
using System.ServiceModel.Activation;

namespace SessionWCF.Lib
{
    [ServiceBehavior(IncludeExceptionDetailInFaults = true)]
    [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
    public class SessionService : ISessionService
    {
        string message = "";

        #region ISessionService Members

        public void BeginSession(string message)
        {
            this.message = message;
        }

        public string GetMessage(int number)
        {
            return "message: " + message + " number: " + number;
        }

        public void EndSession()
        {
            message = "";
        }

        #endregion
    }
}

Третье - SessionWCF.Web это приложение ASP.NET MVC 2.0, которое находится внутри файла SessionService.svc. Я удалил код и открыл редактор XML, этот сервис указывает на сервис из SessionWCF.Lib, и, конечно, этот проект имеет ссылку на SessionWCF.Lib.

SessionService.svc:

<%@ ServiceHost Language="C#" Debug="true" Service="SessionWCF.Lib.SessionService" CodeBehind="SessionWCF.Lib.SessionService.cs" %>

Web.config:

<system.serviceModel>
    <serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />
    <services>
      <service behaviorConfiguration="SessionServiceBehavior" name="SessionWCF.Web.SessionService">
        <endpoint address="" binding="wsHttpBinding" bindingConfiguration="largeMessageHttpBinding" contract="SessionWCF.Lib.ISessionService">
          <identity>
            <dns value="**********"/>
          </identity>
        </endpoint>
        <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
        <host>
          <baseAddresses>
            <add baseAddress="http://**********/SessionWCF/SessionService.svc"/>
          </baseAddresses>
        </host>
      </service>
    </services>
    <bindings>
      <wsHttpBinding>
        <binding name="largeMessageHttpBinding" maxReceivedMessageSize="10485760">
          <readerQuotas maxArrayLength="100000"/>
        </binding>
      </wsHttpBinding>
    </bindings>
    <behaviors>
      <serviceBehaviors>
        <behavior name="">
          <serviceMetadata httpGetEnabled="true" />
          <serviceDebug includeExceptionDetailInFaults="false" />
        </behavior>
        <behavior name="SessionServiceBehavior">
          <serviceMetadata httpGetEnabled="True"/>
          <serviceDebug includeExceptionDetailInFaults="True"/>
        </behavior>
      </serviceBehaviors>
    </behaviors>
  </system.serviceModel>

Четвертое - SessionWCF.WPF - это стандартное приложение WPF, которое включает в себя класс SessionProxy и событие щелчка в форме xaml для вызова веб-службы. Этот проект имеет ссылку на первый SessionWCF.Base.

Класс SessionProxy:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using SessionWCF.Base;
using System.ServiceModel;

namespace SessionWCF.WPF
{
    public class SessionProxy
    {
        public IServiceBase Proxy { get; set; }

        public SessionProxy(string url)
        {
            WSHttpBinding binding = new WSHttpBinding();
            binding.ReceiveTimeout = new TimeSpan(0, 10, 0);
            binding.OpenTimeout = new TimeSpan(0, 1, 0);
            ChannelFactory<IServiceBase> factory = new ChannelFactory<IServiceBase>(binding,
                new EndpointAddress(url));
            Proxy = factory.CreateChannel();
        }
    }
}

Событие клика в форме xaml:

private void Button_Click(object sender, RoutedEventArgs e)
        {
            string url = "http://**********/SessionWCF/SessionService.svc";
            SessionProxy client = new SessionProxy(url);

            client.Proxy.BeginSession("my message");
            string msg = client.Proxy.GetMessage(666);
            client.Proxy.EndSession();

            txtMsg.Text = msg;
        }

Сейчас:

Когда я вызываю веб-сервис в веб-браузере, я получаю следующую ошибку:

Error in '/SessionWCF' Application.
Contract requires Session, but Binding 'BasicHttpBinding' doesn't support it or isn't configured properly to support it. 
Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code. 

Exception Details: System.InvalidOperationException: Contract requires Session, but Binding 'BasicHttpBinding' doesn't support it or isn't configured properly to support it.

Source Error: 
An unhandled exception was generated during the execution of the current web request. Information regarding the origin and location of the exception can be identified using the exception stack trace below. 


Stack Trace: 

[InvalidOperationException: Contract requires Session, but Binding 'BasicHttpBinding' doesn't support it or isn't configured properly to support it.]
   System.ServiceModel.Description.DispatcherBuilder.BuildChannelListener(StuffPerListenUriInfo stuff, ServiceHostBase serviceHost, Uri listenUri, ListenUriMode listenUriMode, Boolean supportContextSession, IChannelListener& result) +16376242
   System.ServiceModel.Description.DispatcherBuilder.InitializeServiceHost(ServiceDescription description, ServiceHostBase serviceHost) +1940
   System.ServiceModel.ServiceHostBase.InitializeRuntime() +82
   System.ServiceModel.ServiceHostBase.OnOpen(TimeSpan timeout) +64
   System.ServiceModel.Channels.CommunicationObject.Open(TimeSpan timeout) +789
   System.ServiceModel.HostingManager.ActivateService(String normalizedVirtualPath) +287
   System.ServiceModel.HostingManager.EnsureServiceAvailable(String normalizedVirtualPath) +1132

[ServiceActivationException: The service '/SessionWCF/SessionService.svc' cannot be activated due to an exception during compilation.  The exception message is: Contract requires Session, but Binding 'BasicHttpBinding' doesn't support it or isn't configured properly to support it..]
   System.Runtime.AsyncResult.End(IAsyncResult result) +890624
   System.ServiceModel.Activation.HostedHttpRequestAsyncResult.End(IAsyncResult result) +180062
   System.Web.CallHandlerExecutionStep.OnAsyncHandlerCompletion(IAsyncResult ar) +136


Version Information: Microsoft .NET Framework Version:4.0.30319; ASP.NET Version:4.0.30319.1

Когда я вызываю его в моем событии xaml, я получаю ServiceActivationException:

The requested service, 'http://**********/SessionWCF/SessionService.svc' could not be activated. See the server's diagnostic trace logs for more information.

Это неправильная конфигурация в web.config? Может я что-то упускаю в служебных атрибутах? И самое главное. Почему он предупреждает меня о BasicHttpBinding, когда я его не использую ???

Кто-нибудь может мне помочь с этим, пожалуйста? Это важно для моего текущего проекта ...

С уважением, Даниэль Сковронски

UPDATE:

@ marc_s

Во-первых:

Я думаю, что на стороне сервера это неправильно, потому что, когда я просто вставляю URL 'http://**********/SessionWCF/SessionService.svc' в любом веб-браузере я получу ошибку «Для контракта требуется Session, но Binding« BasicHttpBinding »не поддерживает его или неправильно настроен для его поддержки.» Вместо метаданных ...

Во-вторых:

В моем клиентском приложении WPF у меня всегда есть два варианта:

Сначала - создайте ссылку на службу, и IDE автоматически сгенерирует прокси-класс и добавит всю конфигурацию в app.config.

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

Второе - создание poxy вручную и привязка конфигурации приложения из кода, это дает мне возможность создавать прокси шаг за шагом, но кажется, что ServiceActivationException - это та же проблема «ACTIVATION», что вы можете увидеть в трассировке стека этой строки:

[ServiceActivationException: The service '/SessionWCF/SessionService.svc' cannot be activated due to an exception during compilation.  The exception message is: Contract requires Session, but Binding 'BasicHttpBinding' doesn't support it or isn't configured properly to support it..]
   System.Runtime.AsyncResult.End(IAsyncResult result) +890624
   System.ServiceModel.Activation.HostedHttpRequestAsyncResult.End(IAsyncResult result) +180062
   System.Web.CallHandlerExecutionStep.OnAsyncHandlerCompletion(IAsyncResult ar) +136

С уважением, Даниэль Сковронски

UPDATE:

@ marc_s

Это не так, потому что:

Во-первых:

<services>
    <service name="SessionWCF.Web.SessionService"
             behaviorConfiguration="SessionServiceBehavior">

Имя службы - это имя файла веб-службы внутри приложения asp.net, поэтому оно указывает на SessionService.svc, который принадлежит сборке SessionWCF.Web (то же имя, что и у проекта).

Во-вторых:

<%@ ServiceHost Language="C#" Debug="true" 
       Service="SessionWCF.Lib.SessionService" 
       CodeBehind="SessionWCF.Lib.SessionService.cs" %>

Service = - это фабричный метод, который получает «тип» службы для создания, ему также нужно описание класса, поэтому CodeBehind = должен быть указан в файле SessionService.cs, где фабричный метод может найти тип SessionService внутри сборки SessionWCF.Lib. 1087 *

Упомянутые два утверждения не являются проблемой, потому что, когда НЕ используется сценарий State Service, это работает как шарм ...

Я считаю, что для Государственной службы необходимо настроить что-то большее в web.config, если я что-то упускаю в описании интерфейса / класса в библиотеке классов WCF ...

Я все еще в критической ситуации ...

С уважением, Даниэль Сковронски

UPDATE

@ marc_s вы написали

Я думаю, что вы не правы здесь, на SVC файл - проверить: msdn.microsoft.com/en-us/library/aa751792.aspx -атрибут Service = ".." должен иметь значение "Значение атрибута Service - это имя типа общеязыковой среды выполнения (CLR) реализации службы."- вам нужно указать .NET имя класса реализации сервиса здесь!Это ваш класс SessionWCF.Lib.SessionService.

Я согласен с вами, потому что это именно то, что я написал: -)

Вы указали эту статью: http://msdn.microsoft.com/en-us/library/aa751792.aspx

Но несколько строк ниже, и вы увидите, что это под капотом:

new ServiceHost( typeof( MyNamespace.MyServiceImplementationTypeName) ); 

Поэтому, когда я набрал:

<%@ ServiceHost Language="C#" Debug="true" 
       Service="SessionWCF.Lib.SessionService" 
       CodeBehind="SessionWCF.Lib.SessionService.cs" %>

, я указал точно: SessionWCF.Lib- namespace, SessionService - класс, в котором реализован мой сервис.

В моем примере SessionWCF.Lib - это как имя сборки для .dll, так и пространство имен в проекте SessionWCF.Lib, которое вы можете увидеть в верхней части этогоопубликовать, когда я опишу второй проект в своем решении, начиная с "Second - SessionWCF.Lib, это ..."

И снова это решение работает отлично без функциональности сеанса WCF, но оно НЕ РАБОТАЕТ, когда яиспользуйте сессию WCF, что мне нужно ...

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

ОБНОВЛЕНИЕ 2010-07-08

@marc_s был прав насчет неверной конфигурации в web.config.

Правильная конфигурация должна совпадать с именем в библиотеке Wcf:

<service behaviorConfiguration="SessionServiceBehavior" name="SessionWCF.Lib.SessionService">

С уважением, Даниэль Сковронски

1 Ответ

0 голосов
/ 08 июля 2010

@ marc_s был прав насчет неверной конфигурации в web.config.

Для правильной конфигурации должно быть то же имя, что и в библиотеке Wcf:

<service behaviorConfiguration="SessionServiceBehavior" name="SessionWCF.Lib.SessionService">
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...