Возможна ли отдельная услуга WCF, несколько контрактов и дженериков? - PullRequest
0 голосов
/ 02 марта 2011

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

    namespace WCFSingleService
    {
        // NOTE: You can use the "Rename" command on the "Refactor" menu to change the interface name "IService1" in both code and config file together.
        [ServiceContract]
        public interface ISingleService<T>
        {
            [OperationContract]
            T GetData(T item);

         }   

    }

namespace WCFSingleService
{
    [ServiceContract(Name = "User")]
    public interface IUserSingleService: ISingleService<User>
    {
    }
}

namespace WCFSingleService
{
    [ServiceContract(Name = "Some")]
    public interface ISomeSingleService: ISingleService<Some>
    {
    }
}

public partial class SingleService : IUserSingleService
    {
        public User GetData(User item)
        {
            //Do something
        }



    }

public partial class SingleService : ISomeSingleService
    {
        public Some GetData(Some item)
        {
            //Do something
        }



    }

Возможно ли это икак будет выглядеть конфигурация для этого сервиса?Кроме того, смогу ли я использовать службу, скажем, от клиента AJAX?Я полагаю, что сделал бы это, поскольку я не пытаюсь передать тип в контракт, и каждый контракт будет иметь свою конечную точку, верно?Спасибо!

Вот моя текущая конфигурация:

<system.serviceModel>
    <services>
      <service name="WCFSingleService.SingleService" behaviorConfiguration="WCFSingleService.ServiceBehavior">
        <host>
          <baseAddresses>
            <add baseAddress = "http://localhost:8732/Design_Time_Addresses/WCFSingleService/SingleService" />            
          </baseAddresses>
        </host>
        <!-- Service Endpoints -->
        <!-- Unless fully qualified, address is relative to base address supplied above -->
        <endpoint address="User" binding="wsHttpBinding" contract="WCFSingleService.IUserSingleService"/>
        <endpoint address="Some" binding="wsHttpBinding" contract="WCFSingleService.ISomeSingleService"/>




        <!-- Metadata Endpoints -->
        <!-- The Metadata Exchange endpoint is used by the service to describe itself to clients. --> 
        <!-- This endpoint does not use a secure binding and should be secured or removed before deployment -->
        <endpoint contract="IMetadataExchange" binding="mexHttpBinding" address="mex"/>
      </service>
    </services>
    <behaviors>
      <serviceBehaviors>
        <behavior name="WCFSingleService.ServiceBehavior">
          <!-- To avoid disclosing metadata information, 
          set the value below to false and remove the metadata endpoint above before deployment -->
          <serviceMetadata httpGetEnabled="True"/>
          <!-- To receive exception details in faults for debugging purposes, 
          set the value below to true.  Set to false before deployment 
          to avoid disclosing exception information -->
          <serviceDebug includeExceptionDetailInFaults="False" />
        </behavior>
      </serviceBehaviors>
    </behaviors>
  </system.serviceModel>

ОБНОВЛЕНИЕ: Ну, я пытался выяснить, почему мой сервак не сработал, как только я повернулсяотладка, которая открыла ошибку dorr.ДУХ!В любом случае, проблема, с которой я столкнулся, была связана с тем же именем метода, который создавался для обеих служб.Итак, кто-нибудь знает, как WCF переименовывает имена методов, если несколько служб влияют на один и тот же интерфейс?Есть ли декорация, которую я могу надеть на метод внутри одной из реализаций, чтобы он выглядел по-другому?

Ответы [ 3 ]

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

да, у вас может быть один сервис с несколькими контрактами, вы должны установить ConfigurationName в интерфейсе вашего сервиса.

Вы должны объявить свой интерфейс следующим образом

Namespace ServiceNameSpace

<System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "3.0.0.0"), _
     System.ServiceModel.ServiceContractAttribute([Namespace]:="whatever namespace you like", ConfigurationName:="ServiceContract1")> _
    Public Interface ServiceContract1
    <System.ServiceModel.OperationContractAttribute(Action:="Service Action"), _
         System.ServiceModel.XmlSerializerFormatAttribute(SupportFaults:=True)> _
        Function ServiceFunction1(ByVal var As Class1) As Class1

End Interface



 <System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "3.0.0.0"), _
     System.ServiceModel.ServiceContractAttribute([Namespace]:="temp namespace", ConfigurationName:="ServiceContract2")> _
    Public Interface ServiceContract2

<System.ServiceModel.OperationContractAttribute(Action:="Service Action"), _
         System.ServiceModel.XmlSerializerFormatAttribute(SupportFaults:=True)> _
        Function function2(ByVal var As Class2) As Class2
End INterface

End Namespace

Тогда вам нужен класс, который на самом деле имел бы реализацию обоих сервисных контрактов, которые вы выставили

namespace ServiceNameSpace

Public Class ServiceImplementationCLass Implements ServiceContract1, ServiceContract2

Public Function ServiceFunction1(byval var as class1) as class1

'Do whatever you want to 

end Function

Public Function function2(byval var as class2) as class2

'Do whatever you want to 

end Function

end namespace

end Class

И, наконец, просто настройте службу, как показано ниже

<system.serviceModel>
    <services>

<service name="ServiceNameSpace.ServiceImplementationCLass" behaviorConfiguration="ServiceBehavior">
                <endpoint address="" binding="basicHttpBinding" contract="ServiceContract1" />
                <endpoint address="" binding="basicHttpBinding" contract="ServiceContract2" />
</service>
</services>
    <behaviors>
      <serviceBehaviors>
        <behavior name="ServiceBehavior">
          <!-- To avoid disclosing metadata information, 
          set the value below to false and remove the metadata endpoint above before deployment -->
          <serviceMetadata httpGetEnabled="True"/>
          <!-- To receive exception details in faults for debugging purposes, 
          set the value below to true.  Set to false before deployment 
          to avoid disclosing exception information -->
          <serviceDebug includeExceptionDetailInFaults="False" />
        </behavior>
      </serviceBehaviors>
    </behaviors>
  </system.serviceModel>

Приведенный выше код находится в VB.NET, если вы хотите, я также могу предоставить вам код C #,

Надеюсь, мое решение поможет вам.

0 голосов
/ 03 марта 2011

Я понял, во многом, чего я хотел достичь.По сути, я все еще мог бы настроить свой код для использования обобщений, имея один сервис.У меня появилась идея для единственного сервиса здесь .Затем я понял, что мне нужно указать ServiceContract для частичного класса SingleService (не для самих интерфейсов) и украсить мои реализованные методы с помощью OperationContract (Name = "TheExposedNameOfTheMethod").Вот часть кода:

public interface ISingleService<T>
    {
        //[OperationContract]
        T GetData(T item);


    }


public interface IUserSingleService: ISingleService<User>
    {
    }

public interface IOtherSingleService: ISingleService<Other>
    {
    }

[ServiceContract]
    public partial class SingleService : IUserSingleService
    {
        [OperationContract(Name = "GetDataUser")]
        public User GetData(User item)
        {
            switch(item.MessageCommand)
            {
                case "Create":
                    //do stuff to for a User create
                    break;
                case "Update":
                    //do stuff to for a User update
                    break;
                case "Delete":
                    //do stuff to for a User Delete
                    break;
            }

            return item;

        }



    }

//You only need to specifc the ServiceContract attribute in one of the partial classes
        public partial class SingleService : IOtherSingleService
    {
        [OperationContract(Name = "GetDataOther")]
        public Other GetData(Other item)
        {
            ...do something
            return item;

        }



    }

Вот как будет выглядеть конечная точка:

<endpoint  binding="basicHttpBinding" name="TheService"
          contract="SingleService" />
0 голосов
/ 02 марта 2011

Мне придется с №

Я пытался заставить сервис возвращать интерфейс, потому что он мог возвращать несколько типов. В конце концов, он ответил так же, как и возвращение Object (плохо).

Вместо этого я реализовал различные функции обратного вызова для каждого возможного возвращаемого типа:

[ServiceContract(CallbackContract=typeof(IClientFeedback))]
public interface IDataService
{
    [OperationContract]
    void GetItem(string entryID);
}

[ServiceContract]
public interface IClientFeedback
{
    [OperationContract(IsOneWay = true)]
    void ReturnMailMessage(MailMessage msg);

    [OperationContract(IsOneWay = true)]
    void ReturnContact(Contact cont);
}

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

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