2010-05-28 1 views
0

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

Я после этого http://social.msdn.microsoft.com/Forums/en-US/wcf/thread/8f18aed8-8e34-48ea-b8be-6c29ac3b4f41

Во-первых, это, что я не знаю, как я могу установить это пользовательское поведение «MyServiceBehavior» в моем Web.config в ASP.NET MVC приложение, которое будет принимать его.

Насколько я знаю, поведение должно быть объявлено в разделе в wcf.config. Как добавить ссылку на мой класс поведения из сборки сервиса?

второе дело, что в следующем примере они создали локальный хост (они используют

ServiceHost host = new ServiceHost(typeof(Service), new Uri(baseAddress)); 

для размещения в консольное приложение), но как я могу добавить заголовки

OperationContext.Current.OutgoingMessageHeaders.Add ... 

, используемые для инициализировать конструктор, когда я использую ссылку в моей службе WPF-клиента, и она уже создаст экземпляр веб-сервиса «клиент» класса

PBSDataCacheSyncContractClient client = new PBSDataCacheSyncContractClient(); 

is't это слишком поздно? Или когда у меня есть свое собственное поведение я могу сделать что-то вроде этого:

PBSDataCacheSyncContractClient client = new PBSDataCacheSyncContractClient(my var for service constructor) ? 

С уважением, Daniel Skowronski

EDIT: 31.05.2010

@manunt

Я улучшил мой второй вопрос.

Для ответа на мой первый вопрос мне удалось создать пользовательский extenstion, но я не могу его зарегистрировать.

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

  • У меня есть определения для моего веб-службы в библиотеке WCF (интерфейс, контракт, реализация IInstanceProvider, BehaviorExtensionElement)
  • я ссылаться на него в другой проект приложения ASP.NET
  • внутри приложения ASP.NET У меня есть файл службы WCF, и он указывает на мой класс из библиотеки WCF
  • вся моя конфигурация объявлена ​​в web.config

В моей библиотеке WCF У меня есть:

namespace PBS.SyncService 
{ 
using System; 
using System.Data; 
using System.Collections.ObjectModel; 
using System.ServiceModel; 
using Microsoft.Synchronization.Data; 
using System.ServiceModel.Activation; 
using Microsoft.Synchronization.Data.Server; 
using System.Data.SqlClient; 
using System.Collections.Generic; 
using System.ServiceModel.Dispatcher; 
using System.ServiceModel.Channels; 
using System.ServiceModel.Description; 
using System.ServiceModel.Configuration; 

[XmlSerializerFormat()] 
[ServiceBehavior(IncludeExceptionDetailInFaults = true)] 
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)] 
public partial class PBSDataCacheSyncService : object, IPBSDataCacheSyncContract 
{ 

    private PBSDataCacheServerSyncProvider _serverSyncProvider; 

    public PBSDataCacheSyncService() 
    { 
     this._serverSyncProvider = new PBSDataCacheServerSyncProvider(); 
    } 

    public PBSDataCacheSyncService(long doctorId) 
    { 
     this._serverSyncProvider = new PBSDataCacheServerSyncProvider(); 
     this._serverSyncProvider.DoctorId = doctorId; 
     this._serverSyncProvider.InitializeCustomSyncProvider(); 
    } 

    [System.Diagnostics.DebuggerNonUserCodeAttribute()] 
    public virtual SyncContext ApplyChanges(Microsoft.Synchronization.Data.SyncGroupMetadata groupMetadata, DataSet dataSet, Microsoft.Synchronization.Data.SyncSession syncSession) 
    { 
     return this._serverSyncProvider.ApplyChanges(groupMetadata, dataSet, syncSession); 
    } 

    [System.Diagnostics.DebuggerNonUserCodeAttribute()] 
    public virtual SyncContext GetChanges(Microsoft.Synchronization.Data.SyncGroupMetadata groupMetadata, Microsoft.Synchronization.Data.SyncSession syncSession) 
    { 
     return this._serverSyncProvider.GetChanges(groupMetadata, syncSession); 
    } 

    [System.Diagnostics.DebuggerNonUserCodeAttribute()] 
    public virtual SyncSchema GetSchema(Collection<string> tableNames, Microsoft.Synchronization.Data.SyncSession syncSession) 
    { 
     return this._serverSyncProvider.GetSchema(tableNames, syncSession); 
    } 

    [System.Diagnostics.DebuggerNonUserCodeAttribute()] 
    public virtual SyncServerInfo GetServerInfo(Microsoft.Synchronization.Data.SyncSession syncSession) 
    { 
     return this._serverSyncProvider.GetServerInfo(syncSession); 
    } 

    public bool InitializeCustomSyncProvider(long doctorId) 
    { 
     this._serverSyncProvider.DoctorId = doctorId; 
     return this._serverSyncProvider.InitializeCustomSyncProvider(); 
    } 
} 

[XmlSerializerFormat()] 
[ServiceContractAttribute()] 
public interface IPBSDataCacheSyncContract 
{ 

    [OperationContract()] 
    SyncContext ApplyChanges(Microsoft.Synchronization.Data.SyncGroupMetadata groupMetadata, DataSet dataSet, Microsoft.Synchronization.Data.SyncSession syncSession); 

    [OperationContract()] 
    SyncContext GetChanges(Microsoft.Synchronization.Data.SyncGroupMetadata groupMetadata, Microsoft.Synchronization.Data.SyncSession syncSession); 

    [OperationContract()] 
    SyncSchema GetSchema(Collection<string> tableNames, Microsoft.Synchronization.Data.SyncSession syncSession); 

    [OperationContract()] 
    SyncServerInfo GetServerInfo(Microsoft.Synchronization.Data.SyncSession syncSession); 

    [OperationContract()] 
    bool InitializeCustomSyncProvider(long doctorId); 

    [OperationContract()] 
    string[] GetSyncAdapterInfo(); 
} 

public class PBSDataCacheSyncProvider : IInstanceProvider 
{ 
    public object GetInstance(InstanceContext instanceContext, Message message) 
    { 
     string doctorId = message.Headers.GetHeader<string>("DoctorId", "http://***/SyncService.svc"); 
     if (doctorId != null) 
     { 
      return new PBSDataCacheSyncService(Convert.ToInt64(doctorId)); 
     } 
     else 
     { 
      return new PBSDataCacheSyncService(); 
     } 
    } 
    public object GetInstance(InstanceContext instanceContext) 
    { 
     return new PBSDataCacheSyncService(); 
    } 
    public void ReleaseInstance(InstanceContext instanceContext, object instance) 
    { 
    } 
} 

public class PBSDataCacheSyncBehavior : BehaviorExtensionElement, IServiceBehavior 
{ 
    PBSDataCacheSyncProvider pbsProvider = new PBSDataCacheSyncProvider(); 
    public void AddBindingParameters(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase, Collection<ServiceEndpoint> endpoints, BindingParameterCollection bindingParameters) { } 
    public void ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase) 
    { 
     foreach (ChannelDispatcher cd in serviceHostBase.ChannelDispatchers) 
     { 
      foreach (EndpointDispatcher ed in cd.Endpoints) 
      { 
       ed.DispatchRuntime.InstanceProvider = this.pbsProvider; 
      } 
     } 
    } 
    public void Validate(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase) { } 

    public override Type BehaviorType 
    { 
     get { return typeof(PBSDataCacheSyncBehavior); } 
    } 

    protected override object CreateBehavior() 
    { 
     return new PBSDataCacheSyncBehavior(); 
    } 
} 
} 

Мой WCF файл Сервис имеет имя: SyncService.svc и в моем makrup у меня есть:

<%@ ServiceHost Language="C#" Debug="true" Service="PBS.SyncService.PBSDataCacheSyncService" CodeBehind="PBS.SyncService.PBSDataCache.Server.SyncContract.cs" %> 

Мой web.config:

<service name="PBS.Web.SyncService" behaviorConfiguration="behPBSDataCacheSyncBehavior"> 
    <host> 
     <baseAddresses> 
     <add baseAddress="http://***/SyncService.svc" /> 
     </baseAddresses> 
    </host> 
    <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" /> 
    <endpoint address="" binding="basicHttpBinding" contract="PBS.SyncService.IPBSDataCacheSyncContract" /> 
</service> 

<serviceBehaviors> 
    <behavior name="behPBSDataCacheSyncBehavior"> 
     <PBSDataCacheSyncBehavior /> <!-- this element is being ignored --> 
    </behavior> 
</serviceBehaviors> 

<extensions> 
    <behaviorExtensions> 
     <add name="PBSDataCacheSyncBehavior" type="PBS.SyncService.PBSDataCacheSyncBehavior, PBS.SyncService, 
      Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" /> 
    </behaviorExtensions> 
</extensions> 

Можете ли вы рассказать мне, что мне не хватает в этом пункте? Почему парсер игнорирует мою декларацию расширения?

Я следующее сообщение об ошибке:

Configuration Error Description: An error occurred during the processing of a configuration file required to service this request. Please review the specific error details below and modify your configuration file appropriately.

Parser Error Message: An error occurred creating the configuration section handler for system.serviceModel/behaviors: Extension element 'PBSDataCacheSyncBehavior' cannot be added to this element. Verify that the extension is registered in the extension collection at system.serviceModel/extensions/behaviorExtensions. Parameter name: element

EDIT: 01-06-2010

Проблема с анализатором решена, набрав все декларации в одной строке.

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

В моем приложении WPF у меня есть только экземпляр экземпляра клиента, который реализует мой IPBSDataCacheSyncContract, автогенерируемый Service Reference.

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

общественного PBSDataCacheSyncContractClient() {}

public PBSDataCacheSyncContractClient(string endpointConfigurationName) : 
      base(endpointConfigurationName) { 
    } 

    public PBSDataCacheSyncContractClient(string endpointConfigurationName, string remoteAddress) : 
      base(endpointConfigurationName, remoteAddress) { 
    } 

    public PBSDataCacheSyncContractClient(string endpointConfigurationName, System.ServiceModel.EndpointAddress remoteAddress) : 
      base(endpointConfigurationName, remoteAddress) { 
    } 

    public PBSDataCacheSyncContractClient(System.ServiceModel.Channels.Binding binding, System.ServiceModel.EndpointAddress remoteAddress) : 
      base(binding, remoteAddress) { 
    } 

Где я могу добавить заголовки?

«Что касается второго вопроса - вы должны определить договор сообщения с необходимыми заголовками в нем и предоставить значения заголовка для каждого сообщения отдельно». Не могли бы Вы уточнить?

EDIT: 02.06.2010

я столкнулся с другой проблемой.

Когда я теперь моя конфигурация httpGetEnabled игнорируется ...:

<serviceBehaviors> 
    <behavior name="behPBSDataCacheSyncBehavior"> 
     <PBSDataCacheSyncBehavior /> 
     <serviceMetadata httpGetEnabled="true" /><!-- ignored --> 
     <serviceDebug includeExceptionDetailInFaults="true" /><!-- ignored --> 
    </behavior> 
</serviceBehaviors> 

Как я могу это исправить?

EDIT: 02.06.2010

OK Я фигурный обходной путь. Тем не менее это странно, но это работает!

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

<serviceBehaviors> 
    <behavior name=""> 
     <PBSDataCacheSyncBehavior /> 
     <serviceMetadata httpGetEnabled="true" /> 
     <serviceDebug includeExceptionDetailInFaults="true" /> 
    </behavior> 
    <behavior name="behPBSDataCacheSyncBehavior"> 
     <PBSDataCacheSyncBehavior /> 
     <serviceMetadata httpGetEnabled="true" /> 
     <serviceDebug includeExceptionDetailInFaults="true" /> 
    </behavior> 
</serviceBehaviors> 

И я добавить заголовок в мой код так:

int doctorId = 2; 

Sync.PBSDataCacheSyncContractClient client = new Sync.PBSDataCacheSyncContractClient(); 
new OperationContextScope (client.InnerChannel); 
OperationContext.Current.OutgoingMessageHeaders.Add(
MessageHeader.CreateHeader("DoctorId", "http://***/SyncService.svc", doctorId)); 

Я изменил тему, чтобы быть более полезным.

HTH

С уважением, Daniel Skowronski

ответ

0

Ответ на первый вопрос вы можете найти here.

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

Образец, как определить пользовательские заголовки без указания сообщения договора:

var client = new Service1Client(); 
new OperationContextScope(client.InnerChannel); 
MessageHeader<string> typedHeader = new MessageHeader<string>("headercontent"); 
MessageHeader header = typedHeader.GetUntypedHeader("myheader", "myns");    
OperationContext.Current.OutgoingMessageHeaders.Add(header); 
+0

Пожалуйста, ответьте на мои последние изменения. Спасибо, Daniel –

+0

И снова, я буду признателен, если вы ответите. Спасибо, Daniel –

+0

Черт ... еще одна проблема с httpGetEnabled ... –

2

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

Если вы посмотрите на эту строку в вашем SVC файл разметки:

<%@ ServiceHost Language="C#" Debug="true" Service="PBS.SyncService.PBSDataCacheSyncService" CodeBehind="PBS.SyncService.PBSDataCache.Server.SyncContract.cs" %> 

и эта линия в вашем Web.config:

<service name="PBS.Web.SyncService" behaviorConfiguration="behPBSDataCacheSyncBehavior"> 

Вы заметите, что имя, указанное в теге службы отличается от класса Service, указанного в атрибуте Service в файле разметки.

Я думаю, что это должно быть что-то вроде этого:

вместо

<service name="PBS.Web.SyncService" behaviorConfiguration="behPBSDataCacheSyncBehavior"> 

это

<service name="PBS.SyncService.PBSDataCacheSyncService" behaviorConfiguration="behPBSDataCacheSyncBehavior"> 

Эти два значения, я думаю, есть к тому же не уверен, но в моем случае два значения были разными, и я должен был выполнить бланк служебного имени. Но, установив оба значения одинаково, оно сработало. Он нашел поведение без необходимости пустого, и я смог получить доступ к моему wsdl.