12

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.

Zaid Masud
  • 13,225
  • 9
  • 67
  • 88
azamsharp
  • 19,710
  • 36
  • 144
  • 222
  • 2
    Doesn't pull up anything? Could you try to post something helpful, and maybe include a question? – Kieren Johnstone Aug 11 '11 at 16:54
  • Check out WCF 4.0 - it has remedied **a lot** of configuration headaches! Read [A Developer's Intro to WCF 4](http://msdn.microsoft.com/en-us/library/ee354381.aspx) for extensive details. – marc_s Aug 11 '11 at 16:56

7 Answers7

11

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.

Anders Abel
  • 67,989
  • 17
  • 150
  • 217
5

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>
Community
  • 1
  • 1
BrandonZeider
  • 8,014
  • 2
  • 23
  • 20
1

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.

Josh
  • 44,706
  • 7
  • 102
  • 124
  • I changed it to the following [WebGet(ResponseFormat = WebMessageFormat.Json, UriTemplate = "KnownZombies")] public Zombie GetZombie() { return new Zombie() { Name = "Mohammad Azam"}; } but same results – azamsharp Aug 11 '11 at 17:05
1

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; }
}
carlosfigueira
  • 85,035
  • 14
  • 131
  • 171
0

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.

yantaq
  • 3,968
  • 2
  • 33
  • 34
  • There is a tag for enabling WebScript but not for disabling it so you would expect that not adding the tag would disable it. But it only got resolved when I added the clear tag: – Jos Mar 25 '13 at 13:01
0

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);
DIF
  • 2,470
  • 6
  • 35
  • 49
Walter
  • 1
0

Just use ASP.NET Web API instead of WCF

rpgmaker
  • 800
  • 1
  • 4
  • 7
  • +1 to cancel out the downvote. WCF is an extremely poor fit to the task of returning some JSON content to an HTTP request, everything will be much, much simpler if you use a tool which is actually suited to the task. – Carson63000 Jul 06 '12 at 04:42
  • 5
    While this may be good advice, it isn't an answer to a question. The little pop up when you write an answer specifically says to avoid making statements based on opinion. – sanpaco Aug 17 '12 at 19:19