fiberOptics
fiberOptics

Reputation: 7165

Combining WCF SOAP and REST

The REST project works fine, this can be accessed through this address:

http://localhost:8525/Device/Login?deviceID=testid&password=a&serialNum=testserial

I also have WCF SOAP project in my REST project, these two projects are separated in different folders, "SOAP" and "REST".

My problem is that, after I put this code:

private void RegisterRoutes()
{
    RouteTable.Routes.Add(new ServiceRoute("Device", new WebServiceHostFactory(), typeof(Rest.DeviceComponent)));              
}  

I can't access now the SOAP service which I was able to access before through this address:

http://localhost:8525/DeviceComponent.svc (using WCFTest Client)

Here is the WebConfig

<?xml version="1.0"?>
<configuration>
  <system.web>
    <compilation debug="true" targetFramework="4.0" />
  </system.web>
  <system.serviceModel>
    <behaviors>
      <serviceBehaviors>
        <behavior>
          <!-- 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="true"/>
        </behavior>
      </serviceBehaviors>
    </behaviors>
    <serviceHostingEnvironment multipleSiteBindingsEnabled="true" aspNetCompatibilityEnabled="true" />
    <standardEndpoints>
      <webHttpEndpoint>
        <!-- 
            Configure the WCF REST service base address via the global.asax.cs file and the default endpoint 
            via the attributes on the <standardEndpoint> element below
        -->
        <standardEndpoint name="" helpEnabled="true" automaticFormatSelectionEnabled="true"/>
      </webHttpEndpoint>
    </standardEndpoints>
  </system.serviceModel>
  <system.webServer>
    <modules runAllManagedModulesForAllRequests="true">
      <add name="UrlRoutingModule" type="System.Web.Routing.UrlRoutingModule, System.Web, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
    </modules>
    <handlers>
      <add name="UrlRoutingHandler" preCondition="integratedMode" verb="*" path="UrlRouting.axd"/>
    </handlers>
  </system.webServer>
</configuration>

And inside Global.asax.cs

private void RegisterRoutes()
{
    RouteTable.Routes.Add(new ServiceRoute("Device", new WebServiceHostFactory(), typeof(Rest.DeviceComponent)));
}    

SOAP sample contract

namespace TSDEVICE.SoapSVC.Interface
{
    [ServiceContract]
    public interface IDeviceComponent
    {
        [OperationContract]
        Session Login(string deviceID, string password, string serialNum, string ip);
        [OperationContract]
        bool Logout(DeviceSession session);
        [OperationContract]
        bool IsLatestVersion(DeviceSession session, int version);
        [OperationContract]
        byte[] DownloadLatest(DeviceSession details);
        [OperationContract]
        DateTime GetServerTime(DeviceSession session, long branchID);
        [OperationContract]
        bool AddDevice(UserSession session, Device deviceitem);
        [OperationContract]
        bool RemoveDevice(UserSession session, long deviceID);
    }
}  

And the REST part:

namespace TSDEVICE.Rest
{
    [ServiceContract]
    [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
    [ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall)]
    public class DeviceComponent
    {
        [WebInvoke(UriTemplate = "Login?deviceID={deviceID}&password={password}&serialNum={serialNum}", Method = "POST")]
        [OperationContract]
        public TMODELDEVICE.Entities.Session Login(string deviceID, string password, string serialNum)
        {
            string ip = HttpContext.Current.Request.ServerVariables["REMOTE_ADDR"];
            TMODELDEVICE.Logic.DeviceComponent restDC = new TMODELDEVICE.Logic.DeviceComponent();
            return restDC.Login(deviceID, password, serialNum, ip);
        }

        public string Sample()
        {
            return "Hello";
        }
    }
}  

I have to access SOAP and REST, how can I do that? Thanks a lot!

EDIT

When I try to "Set as Start page" the .svc file, I get this error:

Failed to add a service. Service metadata may not be accessible. Make sure your service is running and exposing metadata.  

EDIT 2

Now I found out the real problem.

When ASP.NET compatibility mode in the web.config == true, SOAP fail to work, while REST requires it. What should I do with this? Thanks

Upvotes: 2

Views: 2846

Answers (2)

Sean Mc
Sean Mc

Reputation: 83

While I appreciate the solutions listed above - I have a found it is far easier to manage/deploy if you don't over think the problem and follow a KISS principle.

Service Contract: IService.cs

namespace DontTazeMe.Bro
{
    [ServiceContract]
    public interface IService
    {
        [OperationContract]
        [WebGet]
        List<GeoMapData> GetToTheChopper();
    }
}

Implementation: Service.cs

namespace DontTazeMe.Bro
{
    public class WSDLService : IService
    {
        public List<GeoMapData> GetToTheChopper()
        {
            return ItsNotEasyBeingChessy.Instance.GetToTheChopperGeoData();
        }
    }

    public class RESTService : WSDLService
    {
        // Let's move along folks, nothing to see here...
        // Seriously though - there is no need to duplicate the effort made in
        // the WSDLService class as it can be inherited and by proxy implementing 
        // the appropriate contract
    }
}

Configuration

<system.serviceModel>
    <services>
      <!-- SOAP Service -->
      <service name="DontTazeMe.Bro.WSDLService">
        <endpoint address="" binding="basicHttpBinding" contract="DontTazeMe.Bro.IService">
          <identity>
            <dns value="localhost" />
          </identity>
        </endpoint>
        <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
        <host>
          <baseAddresses>
            <add baseAddress="http://localhost:8733/DontTazeMe.Bro/Service/" />
          </baseAddresses>
        </host>
      </service>
      <service name="DontTazeMe.Bro.RESTService">
        <endpoint address="" binding="webHttpBinding" contract="DontTazeMe.Bro.IService" behaviorConfiguration="Restful" />
        <host>
          <baseAddresses>
            <add baseAddress="http://localhost:8733/DontTazeMe.Bro/Rest/Service/" />
          </baseAddresses>
        </host>
      </service>
      <behaviors>
      <endpointBehaviors>
        <behavior name="Restful">
          <webHttp defaultOutgoingResponseFormat="Json" defaultBodyStyle="Wrapped" />
        </behavior>
      </endpointBehaviors>
      <serviceBehaviors>
        <behavior>
          <serviceMetadata httpGetEnabled="True" httpsGetEnabled="True"/>
          <serviceDebug includeExceptionDetailInFaults="False" />
        </behavior>
      </serviceBehaviors>
    </behaviors>
  </system.serviceModel>

This method works just fine without getting carried away with configuration

Upvotes: 0

Rajesh
Rajesh

Reputation: 7876

I have a REST project that as both REST and SOAP service being exposed. Now I placed an .svc file for the SOAP service to be accessed by some clients.

The below screenshot gives the folder structure of my project, the route configuration in global.asax, Output accessing the Rest Service and accessing the .svc file (SOAP service)

sample screenshot

UPDATE: Please find my web.Config (My application is hosted on IIS):

web.config

Please find my class that implements my interface ISampleService:

class

Upvotes: 3

Related Questions