Search code examples
wcfgenericsservicecontract

Generic ServiceContract


[ServiceContract]
public interface ISecurities<T> : IPolicyProvider where T: EntityObject 
{
  [OperationContract(Name="GetAllSecurities")]
    IEnumerable<T> GetSecurities();

  [OperationContract]
  IEnumerable<T> GetSecurities<T1>(List<T1> lstIdentifiers) where T1 : FI_CusipMaster;

  [OperationContract]
  T GetSecurity<T1>(T1 lstIdentifiers) where T1 : FI_CusipMaster;
}

//Host
        ///CADIS Contract
        ServiceHost dmHost = new System.ServiceModel.ServiceHost(typeof(GlobalInvestors.FIPA.BLL.UDI.CADISSecurities));

        Uri baseAddress = dmHost.BaseAddresses[0];
        Uri policyAddress = new Uri(baseAddress.AbsoluteUri.Replace(baseAddress.AbsolutePath, ""));

        dmHost.AddServiceEndpoint(
            typeof(GlobalInvestors.FIPA.BLL.IPolicyProvider),
            new System.ServiceModel.WebHttpBinding(),
            policyAddress).Behaviors.Add(new System.ServiceModel.Description.WebHttpBehavior());

        dmHost.Open();

 //App.Config
  <service behaviorConfiguration="UDIBehaviour" name="GlobalInvestors.FIPA.BLL.UDI.CADISSecurities">
    <endpoint binding="basicHttpBinding" contract="GlobalInvestors.FIPA.BLL.UDI.ICADISSecurities" />
    <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
    <host>
      <baseAddresses>
        <add baseAddress="http://localhost:1667/CADIS" />
      </baseAddresses>
    </host>
  </service>
  <behavior name="UDIBehaviour">
      <serviceMetadata httpGetEnabled="true" />
      <serviceDebug includeExceptionDetailInFaults="true" />
    </behavior>

[ServiceContract]
[ServiceKnownType(typeof(SecurityMasterAdapter))]
public interface ICADISSecurities :ISecurities<SecurityMasterAdapter>
{

}

I get "InvalidDataContractException Type 'System.Collections.Generic.List`1[T1]' cannot be exported as a schema type because it is an open generic type. You can only export a generic type if all its generic parameter types are actual types." if I host this contract.

I have read that it is good to avoid generics in ServiceContract. but is it possible to use T?


Solution

  • Your problem in this case is not T in ServiceContract but T1 used as DataContract. You can use T in service contract if you replace T with specific type during service contract implementation. For data contracts (operation parameters and return types) you can't use T at all. You always have to specify concrete type. Your service contract can be rewritten with usage of ServiceKnownTypeAttribute so that T1 is replaced with FI_CusipMaster and ServiceKnownType specifies all possible classes derived from FI_CusipMaster.

    Edit: Another way is not to use ServiceKnownType and use KnownTypeAttribute which has to be defined on FI_CusipMaster type.

    Best regards, Ladislav