2011-04-05 21 views
8

Estaba buscando utilizar la plantilla WCF REST Service Application para alojar todos mis servicios web RESTful, sin embargo, también me gustaría poder exponer mis servicios WCF con un punto final SOAP.WCF 4 - Puntos finales Soap y REST

puedo conseguir fácilmente mis servicios REST WCF WCF trabaja en 4 usando el siguiente ejemplo: http://christopherdeweese.com/blog2/post/drop-the-soap-wcf-rest-and-pretty-uris-in-net-4

Es esto posible? Me imagino que debería haber una manera en el Global.asax de conectar puntos finales adicionales y especificar si uno está utilizando basicHttpBinding. ¿Debo utilizar la plantilla WCF REST Service Application y crear una aplicación de servicio estándar y conectarla a través de la configuración?

Gracias por cualquier ayuda.

+0

¿Has intentado agregar un servicio "normal" a esa plantilla? –

+0

¿Puedes aclarar que estás tratando de proporcionar 2 puntos finales, SOAP y REST o quieres un servicio RESTful que envíe SOAP? Mi respuesta cambiaría si te refieres a la primera porque creo que te refieres a la segunda. – Aliostad

+0

Mi objetivo es tener un solo servicio WCF que tenga 2 puntos finales, SOAP y REST. – Brandon

Respuesta

6

Aunque en la mayoría de los casos no mezclaría los puntos finales REST y SOAP, pero acepto que en ciertos casos es necesario. La respuesta a la pregunta: sí, es posible mezclarlos. Hay dos opciones que puede utilizar:

La llamada en Global.asax.cs que define la ruta para el extremo REST

`RouteTable.Routes.Add(new ServiceRoute("Service1", new WebServiceHostFactory(), typeof(Service1)))` 

define esencialmente un servicio a la dirección/Servicio1. Puede agregar un nuevo "servicio", utilizando la misma aplicación de servicio, pero el uso de una fábrica de host diferente de servicio (en lugar de utilizar WebServiceHostFactory, que define un extremo REST, que tendría que utilizar su propio):

public class SoapServiceHostFactory : ServiceHostFactory 
{ 
    protected override ServiceHost CreateServiceHost(Type serviceType, Uri[] baseAddresses) 
    { 
     ServiceHost host = base.CreateServiceHost(serviceType, baseAddresses); 
     ServiceMetadataBehavior smb = host.Description.Behaviors.Find<ServiceMetadataBehavior>(); 
     if (smb == null) 
     { 
      smb = new ServiceMetadataBehavior(); 
      host.Description.Behaviors.Add(smb); 
     } 

     smb.HttpGetEnabled = true; 
     host.AddServiceEndpoint(serviceType, new BasicHttpBinding(), "soap"); 
     return host; 
    } 
} 

Y en global.asax.cs, RegisterRoutes:

private void RegisterRoutes() 
    { 
     // Edit the base address of Service1 by replacing the "Service1" string below 
     RouteTable.Routes.Add(new ServiceRoute("Service1", new WebServiceHostFactory(), typeof(Service1))); 

     RouteTable.Routes.Add(new ServiceRoute("SoapService", new SoapServiceHostFactory(), typeof(Service1))); 
    } 
  • Si realmente quiere tener un servicio de "lógica" con dos puntos finales (que no recomendaría, ya que el enfoque anterior es bastante simple), puede vuelva a crear un ServiceHostFactory personalizado, luego en esa fábrica agregaría dos puntos finales: uno para REST (usando WebHttp) Binding/WebHttpBehavior), y uno para SOAP (utilizando BasicHttpBinding, por ejemplo).
+0

Esto es realmente perfecto ya que tengo un Global.asax que estoy conectando mis servicios REST. – Brandon

+0

Tengo un error: "El valor no se pudo agregar a la colección, ya que la colección ya contiene un elemento del mismo tipo: 'System.ServiceModel.Description.ServiceMetadataBehavior'. Esta colección solo admite una instancia de cada tipo. " ¿Qué está mal con esto? – fiberOptics

+0

El 'SoapServiceHostFactory' en este ejemplo agrega un' ServiceMetadataBehavior' a la descripción, pero en su caso ya lo tiene allí (tal vez provenga de un punto final predeterminado en la configuración). Actualicé el fragmento de código para trabajar incluso en este caso. – carlosfigueira

0

Tengo un servicio web ejecutándose donde los clientes requieren tanto acceso SOAP como REST. Puede definir sus plantillas de URL REST utilizando los atributos WebGet y WebInvoke.

[ServiceContract] 
public interface IService 
{ 
    [OperationContract] 
    [WebInvoke(BodyStyle = WebMessageBodyStyle.Bare, RequestFormat = WebMessageFormat.Xml, ResponseFormat = WebMessageFormat.Xml)] 
    RS DoSomething(RQ request); 
} 

[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)] 
public class Service : IService 
{ 
    public RS DoSomething(RQ rq) 
    { 
     return new RS(rq); 
    } 
} 

Después, simplemente un mapa de los puntos finales como se requiere en la configuración

<system.serviceModel> 
    <services> 
     <service name="Service" behaviorConfiguration="defaultBehavior"> 
     <endpoint address="soap11" binding="basicHttpBinding" contract="IService" behaviorConfiguration="soapBehavior" /> 
     <endpoint address="rest" binding="webHttpBinding" contract="IService" behaviorConfiguration="restBehavior"/> 
     </service> 
    </services> 
    <behaviors> 
     <endpointBehaviors> 
     <behavior name="restBehavior"> 
      <webHttp faultExceptionEnabled="true" /> 
     </behavior> 
     <behavior name="soapBehavior"> 
     </behavior> 
     </endpointBehaviors> 
     <serviceBehaviors> 
     <behavior name="defaultBehavior"> 
      <serviceMetadata httpGetEnabled="true" /> 
      <serviceDebug includeExceptionDetailInFaults="true" /> 
     </behavior> 
     </serviceBehaviors> 
    </behaviors> 
    </system.serviceModel> 
2

he tenido que añadir un constructor a la fábrica de carlosfigueira por lo que construye el punto final de la interfaz y no el propio Servicio:

public class SoapServiceHostFactory : ServiceHostFactory 
{ 
    private Type serviceInterfaceType; 

    public SoapServiceHostFactory(Type serviceInterfaceType) 
    { 
     this.serviceInterfaceType = serviceInterfaceType; 
    } 

    protected override ServiceHost CreateServiceHost(Type serviceType, Uri[] baseAddresses) 
    { 
     ServiceHost host = base.CreateServiceHost(serviceType, baseAddresses); 
     host.Description.Behaviors.Add(new ServiceMetadataBehavior { HttpGetEnabled = true }); 
     host.AddServiceEndpoint(serviceInterfaceType, new BasicHttpBinding(), "soap"); 
     return host; 
    } 
} 
+0

Gracias! También recibí una excepción como 'El tipo de contrato MyClassSvc no se atribuye a ServiceContractAttribute. Para definir un contrato válido, el tipo especificado (ya sea la interfaz de contrato o la clase de servicio) debe atribuirse a ServiceContractAttribute. "Es extraño porque mi servicio hereda de la interfaz y la interfaz tiene ese atributo. ¿Error de Framework? – DeepSpace101

Cuestiones relacionadas