0
votes

I'm trying to build a self-hosted WCF RESTful(Json) server. Follow some step by step tutorials, it returns error 400 after request http://192.168.1.250:18688/MyService/GetJSON in fiddler. Some said in this case, SVC file's modify is needed, but in fact there's no such file in self-hosted app.

How to fix it? Thank you!

Interface

namespace Contracts
{
    [ServiceContract]
    public interface IMyService
    {
        [OperationContract]
        [WebInvoke(Method = "GET", ResponseFormat = WebMessageFormat.Json, UriTemplate = "Ping")]
        bool Ping();
        [OperationContract]
        Dude GetDude();
        [OperationContract]
        [WebInvoke(Method = "GET", ResponseFormat = WebMessageFormat.Json, UriTemplate = "GetJSON")]//,BodyStyle=WebMessageBodyStyle.Bare)]
        string GetDudeJSON();
    }
}

Code

namespace Contracts
{
    [ServiceBehavior]   
    public class MyService:IMyService
    {
        public Dude Dummy { get; set; }
        public MyService()
        {
            Dummy = new Dude("Dude", 28);
        }


        public bool Ping()
        {
            return true;
        }

        public Dude GetDude()
        {
            return Dummy;
        }

       string IMyService.GetDudeJSON()
        {
            MemoryStream stream = new MemoryStream();
            DataContractJsonSerializer ser = new DataContractJsonSerializer(typeof(Dude));
            ser.WriteObject(stream,Dummy);
            stream.Position = 0;
            StreamReader reader = new StreamReader(stream);
          //  Console.WriteLine("Read:"+reader.ReadToEnd());
            return reader.ReadToEnd();
        }
    }
}

APP.config

<?xml version="1.0"?>
<configuration>
  <system.serviceModel>
    <services>
      <service name="Contracts.MyService" behaviorConfiguration="MEXBehavior">
        <endpoint address="" binding="basicHttpBinding" bindingConfiguration="httpBinding1" contract="Contracts.IMyService"></endpoint>
        <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"></endpoint>
        <host>
          <baseAddresses>        
            <add baseAddress="http://192.168.1.250:18688/MyService"/>
          </baseAddresses>
        </host>
      </service>
    </services>
    <!-- A behavior definition for MEX -->
    <behaviors>
      <serviceBehaviors>

        <behavior name="MEXBehavior">
          <serviceDebug includeExceptionDetailInFaults="true"/>
          <serviceMetadata/>
        </behavior>        
      </serviceBehaviors>
    </behaviors>
    <bindings>
      <basicHttpBinding>
        <binding name="httpBinding1"></binding>
      </basicHttpBinding>      
    </bindings>
  </system.serviceModel>

  <startup>
    <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/>
  </startup>
</configuration>

CLI Host

static void Main(string[] args)
        {
            ServiceHost _host = new ServiceHost(typeof(Contracts.MyService));
            _host.Open();         
            ChannelFactory<Contracts.IMyService> channel = new ChannelFactory<Contracts.IMyService>(
                                                                            new BasicHttpBinding(),
                                                                            new EndpointAddress("http://192.168.1.250:18688/MyService"));
            Contracts.IMyService client = channel.CreateChannel();   
            while (true)
            {
                ;
            }
        }
1
You should look at the HTTP requests and responses. If they don't provide an immediate answer, add them to the question. - Paul Turner

1 Answers

0
votes

basicHttpBinding is for SOAP based communication. For REST, you have to use webHttpBinding.

Change your service endpoint to this:

<endpoint address="" binding="webHttpBinding" contract="Contracts.IMyService" behaviorConfiguration="MyRestBehavior" />

You must have noticed, I've added a endpoint behavior configuration reference. Define it in your <behaviors> section:

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

Once you do that, there is no need to use DataContractJsonSerializer manually. You can change the interface to have:

Dude GetDudeJSON();

and implementation to:

Dude IMyService.GetDudeJSON()
{
    return new Dude("Dude", 28);
}

You will receive the object in JSON format automatically.

On a side note - your while (true) { ; } is really bad way of blocking - it will eat up your CPU cycles. Instead just use some blocking call like Console.ReadLine()