azamsharp
azamsharp

Reputation: 20086

WCF Configuration Hell?

I hate WCF setup with endpoints, behaviors etc. I believe all these things should be performed automatically. All I want to do is to return JSON result from my WCF service. Here is my configuration:

<system.serviceModel>
<bindings>
  <webHttpBinding>
    <binding name="default"/>
  </webHttpBinding>
</bindings>
<services>
  <service name="HighOnCodingWebApps.ZombieService"
     behaviorConfiguration="MyServiceTypeBehaviors">
    <endpoint address="" binding="webHttpBinding"
      bindingConfiguration="default"
      contract="HighOnCodingWebApps.IZombieService"
      behaviorConfiguration="webScriptEnablingBehavior"/>
  </service>
</services>

<behaviors>
  <endpointBehaviors>
    <behavior name="webScriptEnablingBehavior">
      <enableWebScript/>
    </behavior>
  </endpointBehaviors>

  <serviceBehaviors>
    <behavior name="MyServiceTypeBehaviors">
      <serviceMetadata httpGetEnabled="true"/>


    </behavior>
  </serviceBehaviors>
</behaviors>

<serviceHostingEnvironment aspNetCompatibilityEnabled="false"/>

And I have the following service implementation:

public class ZombieService : IZombieService
    {
        [WebInvoke(Method = "GET",
                    ResponseFormat = WebMessageFormat.Json,
                    UriTemplate = "KnownZombies")]
        public Zombie GetZombie()
        {
           return new Zombie() { Name = "Mohammad Azam"};
        }
    }

    public class Zombie
    {
        public string Name { get; set; }
    }

When I visit http://localhost:22059/ZombieService/KnownZombies says the following message:

Endpoints using 'UriTemplate' cannot be used with 'System.ServiceModel.Description.WebScriptEnablingBehavior'.

If I remove the WebScriptEnablingBehavior from the web.config I get the following error:

The message with To 'http://localhost:22059/ZombieService.svc/KnownZombies' cannot be processed at the receiver, due to an AddressFilter mismatch at the EndpointDispatcher. Check that the sender and receiver's EndpointAddresses agree.

UPDATE 1:

I updated the configuration to this:

 <system.serviceModel>
    <bindings>
      <webHttpBinding>
        <binding name="default"/>
      </webHttpBinding>
    </bindings>
    <services>
      <service name="HighOnCodingWebApps.ZombieService"
         behaviorConfiguration="MyServiceTypeBehaviors">
        <endpoint address="http://localhost:22059/ZombieService.svc" binding="webHttpBinding"
          bindingConfiguration="default"
          contract="HighOnCodingWebApps.IZombieService"
          />
      </service>
    </services>

    <behaviors>
      <endpointBehaviors>
        <behavior name="SomeBehavior">
          <webHttp />
        </behavior>
      </endpointBehaviors>
      <serviceBehaviors>
        <behavior name="MyServiceTypeBehaviors">

          <serviceMetadata httpGetEnabled="true"/>
        </behavior>
      </serviceBehaviors>
    </behaviors>

  </system.serviceModel>

Now when I visit http://localhost:22059/ZombieService.svc/KnownZombies I get the following message in the browser:

The message with To 'http://localhost:22059/ZombieService.svc/KnownZombies' cannot be processed at the receiver, due to an AddressFilter mismatch at the EndpointDispatcher. Check that the sender and receiver's EndpointAddresses agree.

Upvotes: 12

Views: 14570

Answers (7)

Walter
Walter

Reputation: 1

In your WebGet or WebInvoke Specify your BodyStyle to WrappedRequest, then remove the UriTemplate. When Invoking your service use the function name.

Hope it helps.

Example:

    [OperationContract]
    [WebInvoke(Method = "POST",
        BodyStyle = WebMessageBodyStyle.WrappedRequest,
        RequestFormat = WebMessageFormat.Json,
        ResponseFormat = WebMessageFormat.Json)]
    void register(string name, string surname);

Upvotes: 0

rpgmaker
rpgmaker

Reputation: 790

Just use ASP.NET Web API instead of WCF

Upvotes: 0

yantaq
yantaq

Reputation: 4048

I am using .net framework 4, VS2010. I made a dummy mistake in my global.asax.cs that instead of creating an instance of WebServiceHostFactory I punched WebScriptServiceHostFactory through intellSense. As a result I got the same error:

Endpoints using 'UriTemplate' cannot be used with 'System.ServiceModel.Description.WebScriptEnablingBehavior'.

I corrected the instance to WebServiceHostFactory in my global.asax.cs, I don't see the error anymore.

Upvotes: 0

carlosfigueira
carlosfigueira

Reputation: 87258

I personally don't like all of the configuration options that WCF offers (I've ranted about it before), and in your case you don't need to use configuration at all. For a simple service to return JSON, you can use a service host factory, and there's one which does exactly that (set up a webHttpBinding/webHttp behavior endpoint), the System.ServiceModel.Activation.WebServiceHostFactory. In your case, you can:

  • Remove everything from config (really, you don't need config at all)
  • Update your .svc file to reference that factory (see below)

That's it. Here's what the .svc should look like:

<%@ ServiceHost Language="C#" Service="HighOnCodingWebApps.ZombieService" Factory="System.ServiceModel.Activation.WebServiceHostFactory" %>

One more thing: I noticed that your class isn't decorated with [ServiceContract], but you have a [WebGet] attribute in your method in the class. If the interface (IZombieService) is the one decorated with [ServiceContract], then the method in the interface should be the one decorated with [WebGet]. You can also bypass the interface completely and decorate the ZombieService class with `[ServiceContract] as well.

[ServiceContract]
public class ZombieService
{
    [WebGet(ResponseFormat = WebMessageFormat.Json,
            UriTemplate = "KnownZombies")]
    public Zombie GetZombie()
    {
       return new Zombie() { Name = "Mohammad Azam"};
    }
}

public class Zombie
{
    public string Name { get; set; }
}

Upvotes: 1

BrandonZeider
BrandonZeider

Reputation: 8152

Take a look at this SO question.

Edit: Since you're not specifying an address for your service, try hitting: http://localhost:22059/ZombieService.svc/KnownZombies (with the .svc).

I also think you need the <webHttp /> behavior added to your specified endpoint behavior.

Edit: Try changing your endpoint definition to this:

<service 
  name="HighOnCodingWebApps.ZombieService"
  behaviorConfiguration="MyServiceTypeBehaviors">

  <endpoint 
    address="" 
    binding="webHttpBinding"
    behaviorConfiguration="SomeBehavior"
    bindingConfiguration="default"
    contract="HighOnCodingWebApps.IZombieService" />

</service>

Upvotes: 5

Josh
Josh

Reputation: 44916

You are using the WebInvokeAttribute which tells WCF by default to accept POST as the verb. Since you are trying to access it via a GET action, it is being ignored.

Use WebGetAttribute instead.

Per MSDN:

If you want a service operation to respond to GET, use the WebGetAttribute instead.

Upvotes: 1

Anders Abel
Anders Abel

Reputation: 69270

Have you tried the WCF SvcConfigEditor? It is available from the Tools menu in Visual Studio. Open your web/app.config with SvcConfigEditor to get GUI help on getting everything right.

Upvotes: 11

Related Questions