Конструктор WCF с параметром / Пользовательское поведение, созданное в коде - PullRequest
0 голосов
/ 28 мая 2010

Мне нужно создать службу wcf с параметром.

Я слежу за этим 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();

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

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

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

РЕДАКТИРОВАТЬ: 31-05-2010

@ manunt

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

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

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

  • У меня есть определения для моего веб-сервиса в библиотеке 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 и в моем макрокоманде:

<%@ 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>

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

У меня следующая ошибка:

Ошибка конфигурации Описание: во время обработки файла конфигурации, необходимого для обслуживания этого запроса, произошла ошибка.Пожалуйста, просмотрите подробности конкретной ошибки ниже и измените файл конфигурации соответствующим образом.

Сообщение об ошибке синтаксического анализатора: при создании обработчика раздела конфигурации для system.serviceModel / поведение: произошла ошибка: элемент расширения 'PBSDataCacheSyncBehavior' не может быть добавлен к этому элементу.Убедитесь, что расширение зарегистрировано в коллекции расширений в system.serviceModel / extensions / поведениеExtensions.Имя параметра: элемент

РЕДАКТИРОВАТЬ: 01-06-2010

Проблема с парсером решена путем ввода всего объявления в одну строку.

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

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

public 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) {
    }

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

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

РЕДАКТИРОВАТЬ: 02-06-2010

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

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

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

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

РЕДАКТИРОВАТЬ: 02-06-2010

ОК Я решил, что обходной путь.Тем не менее, это странно, но это работает!

Моя проблема была с 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

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

Ответы [ 2 ]

2 голосов
/ 27 февраля 2011

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

Если вы посмотрите на эту строку в файле разметки 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 в файле разметки.

Я думаю, что это должно быть примерно так:

вместо

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

это

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

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

0 голосов
/ 28 мая 2010

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

Относительно ошибки, которую вы получаете - не разбивайте определение вашего расширения на две строки, потому что анализатор 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);
...