Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

WCF REST and SOAP Service without WebServiceHostFactory

Tags:

rest

soap

wcf

Despite reading a number of posts eg (This one seems popular) I can't seem to expose my service as multiple endpoints that are compatible with both the SOAP and REST protocol - my problem seems to be with the

  Factory="System.ServiceModel.Activation.WebServiceHostFactory"

element in the Service code behind page.

If I leave it out, my SOAP endpoint works grand, but my JSON endpoint is not found. If I put the line in, my REST endpoint sings like bird and the the SOAP endpoint is results in "Endpoint not found" on the Service.svc page.

My operations appear to set up in the standard way eg:

    [OperationContract]
    [WebGet(UriTemplate = "/GetData", ResponseFormat = WebMessageFormat.Json, BodyStyle = WebMessageBodyStyle.Bare)]
    string GetData();

And the configuration file

 <endpoint address="rest" binding="webHttpBinding" contract=".IMeterService" behaviorConfiguration="REST" />

 <endpoint address="soap" binding="wsHttpBinding" contract="IMeterService" bindingConfiguration="secureBasic" />

 <behavior name="REST">
      <webHttp />
 </behavior>

How can I achieve this? Is there a way to set up the REST endpoint without the System.ServiceModel.Activation.WebServiceHostFactory attribute?

Thanks in advance.

like image 575
Simian Avatar asked Sep 23 '11 15:09

Simian


1 Answers

If you don't specify any factory in the .svc file, all the endpoints will come from the web.config file - WCF will try to find a <system.serviceModel / service> element whose name attribute matches the fully-qualified name of the service class. If it doesn't find one, then it will add a default endpoint (using basicHttpBinding, unless you changed the default mapping). That appears to be what you're facing. Confirm that the "name" attribute of the <service> element matches the value of the Service attribute in the .svc file, and you should have the two endpoints working out fine.

Another thing you can try to do is to enable tracing in the service (level = Information) to see which endpoints were actually opened on the service. The image below:

SvcTraceViewer image

The server for this example is nothing major:

namespace MyNamespace
{
    [ServiceContract]
    public interface ITest
    {
        [OperationContract]
        string Echo(string text);
    }
    public class Service : ITest
    {
        public string Echo(string text)
        {
            return text;
        }
    }
}

The Service.svc doesn't have factory specified:

<% @ServiceHost Service="MyNamespace.Service" Language="C#" debug="true" %>

And the web.config defines two endpoints, which are shown in the traces:

<configuration>
    <system.diagnostics>
        <sources>
            <source name="System.ServiceModel" switchValue="Information, ActivityTracing"
                propagateActivity="true">
                <listeners>
                    <add type="System.Diagnostics.DefaultTraceListener" name="Default">
                        <filter type="" />
                    </add>
                    <add name="ServiceModelTraceListener">
                        <filter type="" />
                    </add>
                </listeners>
            </source>
        </sources>
        <sharedListeners>
            <add initializeData="C:\temp\web_tracelog.svclog" type="System.Diagnostics.XmlWriterTraceListener, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
                name="ServiceModelTraceListener" traceOutputOptions="Timestamp">
                <filter type="" />
            </add>
        </sharedListeners>
        <trace autoflush="true"/>
    </system.diagnostics>
    <system.serviceModel>
        <behaviors>
            <endpointBehaviors>
                <behavior name="Web">
                    <webHttp />
                </behavior>
            </endpointBehaviors>
        </behaviors>
        <services>
            <service name="MyNamespace.Service">
                <endpoint address="basic" binding="basicHttpBinding" bindingConfiguration=""
                    name="basic" contract="MyNamespace.ITest" />
                <endpoint address="web" behaviorConfiguration="Web" binding="webHttpBinding"
                    bindingConfiguration="" name="web" contract="MyNamespace.ITest" />
            </service>
        </services>
    </system.serviceModel>
</configuration>

Notice that there's an extra listener shown in the listener, it's the "help page" from WCF (the one which tells, when you browse to it, that the service doesn't have metadata enabled).

You can try either to compare this setup with yours, or start with this simple one, then start adding component from yours until you hit the issue. That will help isolate the problem.

Good luck!

like image 117
carlosfigueira Avatar answered Sep 28 '22 16:09

carlosfigueira