Search code examples
c#wcfrestwcf-binding

WCF Json Rest service not hitting the Methods


I am writing a WCF service, (json REST) and I have it working fine when using the wcftestclient.exe

When I run that test tool it triggers my break points while debugging and everything works as expected.

but, when using a browser to navigate to the the service and method, no break point is triggered. it seems as though the request isnt even getting to the code.

I receieve no errors on when navigating with web browser to the service, it just doesn't get any data, or trigger the break points.

Apologies if this is a duplicate, I have read and tried many many different configurations found in answers to similar questions, but nothing seems to work.

Many thanks for any help, I've posted my code below.

Martyn

I have setup: ServiceContract

[OperationContract]
[WebGet(BodyStyle = WebMessageBodyStyle.Bare, ResponseFormat = WebMessageFormat.Json)]
List<Country> GetAllCountries();

The Service CLass:

    public List<Country> GetAllCountries()
    {
        ControlServiceRepository rep = new ControlServiceRepository();
        return rep.GetAllCountries().ToList() ;
    }

and my web config

<system.web>
    <compilation debug="true" targetFramework="4.0" />
  </system.web>
  <system.serviceModel>
    <services>
      <service name="OmniData" behaviorConfiguration="ServiceConfig">
        <!-- Service Endpoints -->
        <host>
          <baseAddresses>
            <add baseAddress="http://localhost:55641/"/>
          </baseAddresses>
        </host>
        <endpoint address="" binding="webHttpBinding" contract="ControlService.IOmniData" behaviorConfiguration="rest" />
      </service>
    </services>
      <behaviors>
        <endpointBehaviors>
          <behavior name="rest">
            <webHttp helpEnabled="true"/>
          </behavior>
        </endpointBehaviors>
        <serviceBehaviors>
          <behavior name="ServiceConfig">
            <serviceMetadata httpGetEnabled="true"/>
            <serviceDebug includeExceptionDetailInFaults="false"/>
          </behavior>
        <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="false"/>
        </behavior>
      </serviceBehaviors>
    </behaviors>
    <serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
    <standardEndpoints>
      <webHttpEndpoint>
        <standardEndpoint name="" helpEnabled="true" automaticFormatSelectionEnabled="false" defaultOutgoingResponseFormat="Json"/>
      </webHttpEndpoint>
    </standardEndpoints>
  </system.serviceModel>
 <system.webServer>
    <modules runAllManagedModulesForAllRequests="true"/>
  </system.webServer>

Solution

  • I got this working in the end by deleting all the end points in the config and using

    RouteTable.Routes.Add(new ServiceRoute("", new WebServiceHostFactory(), typeof(OmniData)));
    

    if anyone else has issues, this is even easier than setting up end points because you can just specify the type of responses and end points within the classes themselves.

    so:

    Add a global.asax if one does exist and include this:

    protected void Application_Start(object sender, EventArgs e)
            {
                RouteTable.Routes.Add(new ServiceRoute("", new WebServiceHostFactory(), typeof(OmniData)));
            }
    

    decorate your Service class with

    [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
    

    here is mine:

    [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
    public class OmniData : IOmniData
    {
      public Country[] GetAllCountries()
      {
        ControlServiceRepository rep = new ControlServiceRepository();
        return rep.GetAllCountries().ToArray() ;
      }
    }
    

    then the interface you setup your endpoing and types using WebGet or WebInvoke

    public interface IOmniData
        {
            [OperationContract]
            [WebGet(UriTemplate = "OmniData/GetAllCountries", ResponseFormat = WebMessageFormat.Json, BodyStyle = WebMessageBodyStyle.Bare)]
            Country[] GetAllCountries();
        }
    

    the UriTemplate is the end point, so to access the method you would use: http://MyService.com/OmniData/GetAllCountries

    and finally, web config

    <system.serviceModel>
        <serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true"/>
        <standardEndpoints>
          <webHttpEndpoint>
            <standardEndpoint name="" helpEnabled="true" automaticFormatSelectionEnabled="false"/>
          </webHttpEndpoint>
        </standardEndpoints>
        <services>
          <service name="OmniData">
            <!-- Service Endpoints -->
            <host>
              <baseAddresses>
                <add baseAddress="http://localhost:55641"/>
              </baseAddresses>
            </host>
            <endpoint address="" binding="webHttpBinding" contract="ControlService.IOmniData" behaviorConfiguration="rest" />
          </service>
        </services>
        <behaviors>
          <endpointBehaviors>
            <behavior name="rest">
              <webHttp />
            </behavior>
          </endpointBehaviors>
          <serviceBehaviors>
            <behavior name="Default">
              <serviceMetadata httpGetEnabled="true"/>
            </behavior>
          </serviceBehaviors>
        </behaviors>
      </system.serviceModel>
    

    Alot of help from here

    but, importantly for what I wanted, json results, you need to make sure: automaticFormatSelectionEnabled="false" is in there so it will use the response format specified in the interface. Otherwise you end up with XML instead.

    hopefully this helps someone else

    And thanks again for fiddler!

    Martyn