tags:

views:

91

answers:

2

I have written a service that I would like expose both via rest and soap. Everything I read about WCF 4.0 says that I just need to expose 2 endpoints with differing behaviors to do this. But I cannot get it to work.

Here is my service contract:

[ServiceContract]
public interface MyService
{
    [OperationContract]
    [WebGet(UriTemplate="data/{value}")]
    string GetData(string value);
}

Here is my web.config:

<?xml version="1.0"?>
<configuration>

    <system.web>
        <compilation debug="true" targetFramework="4.0" />
    </system.web>
    <system.serviceModel>

        <services>
            <service name="MyService">
                <endpoint name="mex" address="mex" binding="mexHttpBinding" contract="MyService"/>
                <endpoint address="rest" behaviorConfiguration="restBehavior" binding="webHttpBinding" contract="MyService" />
                <endpoint address="soap" behaviorConfiguration="soapBehavior" binding="basicHttpBinding" contract="MyService" />
            </service>
        </services>

        <behaviors>

            <serviceBehaviors>
                <behavior>
                    <serviceMetadata httpGetEnabled="true"/>
                    <serviceDebug includeExceptionDetailInFaults="true"/>
                </behavior>
            </serviceBehaviors>

            <endpointBehaviors>
                <behavior name="restBehavior">
                    <webHttp automaticFormatSelectionEnabled="true" helpEnabled="true" />
                </behavior>
                <behavior name="soapBehavior" />
            </endpointBehaviors>

        </behaviors>

        <serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true"/>

    </system.serviceModel>

    <system.webServer>
        <modules runAllManagedModulesForAllRequests="true" />
    </system.webServer>

</configuration>

I am using routing to define my service url:

public class Global : System.Web.HttpApplication
    {
        protected void Application_Start(object sender, EventArgs e)
        {
            RouteTable.Routes.Add(new ServiceRoute("dns", new ServiceHostFactory(), typeof(MyService)));
        }
    }

Is there something that I am doing wrong here? I could really use some help.

+1  A: 

How are you hosting your WCF service?? In IIS, you need a virtual directory and a MyService.svc file somewhere to enable service activation.

If you remove the ServiceRoute for now (to simplify matters), you should be able to reach your SOAP service endpoint at:

http://YourServer:Port/YourVirtualDirectory/YourService.svc/soap

and your REST service should be at

http://YourServer:Port/YourVirtualDirectory/YourService.svc/rest/data/{value}

(where you supply some arbitrary value for {value}).

What exactly is not working in your case??

You can try and test your SOAP endpoints using the WCF Test Client, while you should be able to hit the REST url in any browser.

marc_s
I am hosting in IIS.The problem that i see if that the soap endpoint is only accessible if it is configured at the root url:Eitherhttp://YourServer:Port/YourVirtualDirectory/YourService.svcorhttp://YourServer:Port/YourVirtualDirectory/YourService(depending on whether I use the service route).But if I configure it that way then the rest endpoints aren't accessible for some reason. Alternatively if I configure as originally described only the rest endpoints are accessible and the soap endpoint returns me a 400 error.
Troy
I tried adding an entirely new service file (.svc) to my project. Using the same config as above it sorta worked...both rest and soap service worked fine from the .svc url, but the soap service was only accessible from the root. The /soap address configured was not respected.
Troy
A: 

I never found the "right" way to do this in configuration but was able to use the routing engine to accomplish this.

My global asax file now looks like this:

public class Global : System.Web.HttpApplication
    {
        protected void Application_Start(object sender, EventArgs e)
        {
            RouteTable.Routes.Add(new ServiceRoute("my/soap", new ServiceHostFactory(), typeof(MyService)));
            RouteTable.Routes.Add(new ServiceRoute("my/rest", new WebServiceHostFactory(), typeof(MyService)));
        }
    }

and my config like this: (to enable the rest help pages)

<system.serviceModel>

    <standardEndpoints>
        <webHttpEndpoint>
            <standardEndpoint automaticFormatSelectionEnabled="true" helpEnabled="true"/>
        </webHttpEndpoint>
    </standardEndpoints>

    <serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true"/>

</system.serviceModel>

<system.webServer>
    <modules runAllManagedModulesForAllRequests="true" />
</system.webServer>

I like that this is in line with the asp.net MVC model more and requires little config. Additionally doing it this way allowed me to remove the .svc files from my project entirely which is also a plus IMO.

Troy