REST methods not accessible when hosting wcf servi

2019-08-02 21:39发布

问题:

I have a WCF REST service that exposes a method in class GreetService:

[ServiceContract]
public class GreetService
{
    [WebGet(UriTemplate = "greet/{name}")]
    public String GreetName(string name)
    {
        return "Hello " + name;
    }
}

Also, I registered a route in Global.asax:

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

Now when i run this directly from visual studio, I am able to leverage the UriTemplate and invoke this method using a GET call to http://localhost:5432/GreetService/greet/JohnDoe

However, after deploying this to IIS7 by creating a Greet.svc file for it, I am observing the following behavior:

  • I can call http://localhost:5432/Greet.svc and it says that a service has been created
  • I can point wcftestclient to http://localhost:5432/Greet.svc?wsdl to generate a test client which can call GreetName() directly
  • However, I can't call http://localhost:5432/Greet.svc/GreetService/greet/JohnDoe nor http://localhost:5432/Greet.svc/greet/JohnDoe although I expected to be able to since I specified an empty relative endpoint address in the corresponding web.config file prior to hosting it in IIS7.

Any ideas why the WebGetAttribute is not working in IIS? Or is there something else I am doing wrong?

EDIT: This is the ServiceModel part of my web.config file which resides in the directory that IIS uses:

<system.serviceModel>
    <!-- <serviceHostingEnvironment 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>

EDIT 2: For completeness' sake here is my full web.config file:

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

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

  <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"
         type="System.Web.HttpForbiddenHandler, 
         System.Web, Version=4.0.0.0, Culture=neutral, 
         PublicKeyToken=b03f5f7f11d50a3a" />
    </handlers>
  </system.webServer>

  <system.serviceModel>
     <!--<serviceHostingEnvironment 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>

</configuration>

回答1:

If you've defined your route to be:

new ServiceRoute("GreetService", .....

then you should be able to call your service at

http://localhost:5432/YourVirtualDirectory/GreetService/greet/JohnDoe

and if your web app is deployed to your IIS root (not in a virtual directory), that would be:

http://localhost:5432/GreetService/greet/JohnDoe

When defining a ServiceRoute, that's done to get rid of having to specify the Greet.svc file, really - the ServiceRoute entry already contains all the information IIS needs to instantiate your service and call it - no need for having the *.svc file involved in your URL (the svc file basically contains the same info your ServiceRoute entry has).



回答2:

Change the line in your global.asax.cs to read:

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

and put the following in your web.config right under the root <configuration> node:

  <system.webServer>
    <modules runAllManagedModulesForAllRequests="true">
      <add name="UrlRoutingModule"
           type="System.Web.Routing.UrlRoutingModule, 
          System.Web.Routing, Version=4.0.0.0, 
          Culture=neutral, 
          PublicKeyToken=31BF3856AD364E35" />

    </modules>
    <handlers>
      <add name="UrlRoutingHandler"
         preCondition="integratedMode"
         verb="*" path="UrlRouting.axd"
         type="System.Web.HttpForbiddenHandler, 
         System.Web, Version=4.0.0.0, Culture=neutral, 
         PublicKeyToken=b03f5f7f11d50a3a" />
    </handlers>
  </system.webServer>

(do make sure you're using the right .NET version) and see what that does for you.



回答3:

NOTE: please post the web.config, at least the system.servicemodel part.

You normally use either the Route-based configuration or a .svc file, not both, but that's orthogonal to your problem. FWIW, you should be able to kill the .svc file once you get the service working and just use the route.

Since you're able to generate WSDL and call it, that sounds like you might not have webhttp as an endpoint behavior?

Make sure you have an endpoint behavior defined like this (can be a diff name of course)

    <endpointBehaviors> 
        <behavior name="webHttpBehavior"> 
            <webHttp /> 
        </behavior> 
    </endpointBehaviors> 

and then make sure your service endpoint includes behaviorConfiguration="webHttpBehavior"



回答4:

The problem is machine config missing the following section

<configSections>
    <sectionGroup name="system.serviceModel" type="System.ServiceModel.Configuration.ServiceModelSectionGroup, System.ServiceModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
        <section name="standardEndpoints" type="System.ServiceModel.Configuration.StandardEndpointsSection, System.ServiceModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"/>
    </sectionGroup>
</configSections>

Add it on top of web.config (after the opening tag of <configuration> ) should fix this problem.