Reputation: 10953
I was looking at using the WCF REST Service Application template to host all of my RESTful web services, however, I would also like to be able to expose out my WCF services with a SOAP endpoint.
I can easily get my WCF RESTful services working in WCF 4 using the following example: http://christopherdeweese.com/blog2/post/drop-the-soap-wcf-rest-and-pretty-uris-in-net-4
Is this possible? I would imagine there should be a way in the Global.asax to wire up additional endpoints and specify if one is using basicHttpBinding. Do I need to not use the WCF REST Service Application template and create a standard Service Application and wire it all up via the config?
Thanks for any assistance.
Upvotes: 8
Views: 8607
Reputation: 87218
Although in most cases I wouldn't mix REST and SOAP endpoints, but I agree that in certain cases it's necessary. The answer to the question: yes, it's possible to mix them. There are two options you can use:
The call in Global.asax.cs which defines the route for the REST endpoint
`RouteTable.Routes.Add(new ServiceRoute("Service1", new WebServiceHostFactory(), typeof(Service1)))`
defines essentially a service at the address /Service1. You can add a new "service", using the same service implementation, but using a different service host factory (instead of using WebServiceHostFactory, which defines a REST endpoint, you'd use your own):
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;
}
}
And in 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)));
}
Upvotes: 6
Reputation: 364
I had to add a constructor to carlosfigueira's factory so it builds the endpoint from the Interface and not the Service itself:
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;
}
}
Upvotes: 2
Reputation: 7264
I have a web service running where clients require both SOAP and REST access. You can define your REST URL templates using the WebGet and WebInvoke attributes.
[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);
}
}
Then simply map the endpoints as required in the config
<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>
Upvotes: 0