Reputation: 734
I have read here on SO in several posts that it is possible to create a selfhosted wcf REST service that accepts JSON as input. But i cant get it to work, im banging my head against the same rock over and over it seems :(
This is my very basic code that i cant get working. Im using .net 4.6.1 in VS 2017
[ServiceContract]
public interface IService1
{
//[WebInvoke(Method = "POST", UriTemplate = "Save")]
[WebInvoke(Method = "POST", BodyStyle = WebMessageBodyStyle.Wrapped, RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json)]
[OperationContract]
bool Save(BatchOfRows request);
}
public bool Save(BatchOfRows request)
{
return true;
}
Uri baseAddress = new Uri("http://localhost:8000/");
// Step 2: Create a ServiceHost instance.
var selfHost = new ServiceHost(typeof(Service1), baseAddress);
try
{
// Step 3: Add a service endpoint.
selfHost.AddServiceEndpoint(typeof(IService1), new WSHttpBinding(), "");
// Step 4: Enable metadata exchange.
ServiceMetadataBehavior smb = new ServiceMetadataBehavior();
smb.HttpGetEnabled = true;
smb.HttpsGetEnabled = false;
selfHost.Description.Behaviors.Add(smb);
// Step 5: Start the service.
selfHost.Open();
Console.WriteLine("The service is ready.");
// Close the ServiceHost to stop the service.
Console.WriteLine("Press <Enter> to terminate the service.");
Console.WriteLine();
Console.ReadLine();
selfHost.Close();
}
catch (CommunicationException ce)
{
Console.WriteLine("An exception occurred: {0}", ce.Message);
selfHost.Abort();
}
I then connect with this code
string url = @"http://127.0.0.1:8000";
var client = new RestClient(url);
var request = new RestRequest("Save", Method.POST);
var b = new BatchOfRows();
b.CaseTableRows.Add(new AMCaseTableRow { PROJID = "proj1", CASEID = "case1" });
b.CaseTableRows.Add(new AMCaseTableRow { PROJID = "proj2", CASEID = "case2", DEVICEID = "device2" });
var stream1 = new MemoryStream();
var ser = new DataContractJsonSerializer(typeof(BatchOfRows));
ser.WriteObject(stream1, b);
stream1.Flush();
stream1.Position = 0;
StreamReader reader = new StreamReader(stream1);
string payload = reader.ReadToEnd();
request.AddParameter("Save",payload);
var response = client.Post(request);
var content = response.Content;
In the respose i get this back.
"StatusCode: UnsupportedMediaType, Content-Type: , Content-Length: 0)"
Content: ""
ContentEncoding: ""
ContentLength: 0
ContentType: ""
Cookies: Count = 0
ErrorException: null
ErrorMessage: null
Headers: Count = 3
IsSuccessful: false
ProtocolVersion: {1.1}
RawBytes: {byte[0]}
Request: {RestSharp.RestRequest}
ResponseStatus: Completed
ResponseUri: {http://127.0.0.1:8000/Save}
Server: "Microsoft-HTTPAPI/2.0"
StatusCode: UnsupportedMediaType
StatusDescription: "Cannot process the message because the content type 'application/x-www-form-urlencoded' was not the expected type 'application/soap+xml; charset=utf-8'."
I cant get it to work! I have tried with different client implementations with the same result. In every answer i check it sais to just use
[WebInvoke(Method = "POST", BodyStyle = WebMessageBodyStyle.Wrapped, RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json)]
And i should be good. But its not working and im getting abit frustrated as this is the simplest example i can think of.
So what am i doing wrong?
I have used the same type of implementation before, but for a SOAP project, and that is working just fine. I cant do that this time.
Upvotes: 0
Views: 425
Reputation: 7522
Bro, we need to use WebHttpBinding to create Restful style WCF service.
Here is an example.
https://learn.microsoft.com/en-us/dotnet/framework/wcf/feature-details/how-to-create-a-basic-wcf-web-http-service
Webservicehost is also need to host the service when we create the Restful style service. Alternatively, we could add WebHttpBehavior endpoint behavior to the host, like below.
static void Main(string[] args)
{
Uri uri = new Uri("http://localhost:9999");
WebHttpBinding binding = new WebHttpBinding();
using (ServiceHost sh=new ServiceHost(typeof(MyService),uri))
{
ServiceEndpoint se=sh.AddServiceEndpoint(typeof(IService),binding,"");
se.EndpointBehaviors.Add(new WebHttpBehavior());
sh.Open();
Console.WriteLine("Service is ready....");
Console.ReadLine();
sh.Close();
}
}
Result.
Besides, For the BodyStyle=WebMessageBodyStyle.Wrapped attribute, Please pay attention to the data format when we have the Custom object parameter.
[WebInvoke(Method = "POST", BodyStyle = WebMessageBodyStyle.Wrapped, RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json)]
[OperationContract]
bool Save(BatchOfRows request);
Assumed that the BatchOfRows has one ID property. Based on your definition, the Json Data should be.
{ “request”:{“ID”:1}}
For details.
Get the object is null using JSON in WCF Service
Feel free to let me know if there is anything I can help with.
Upvotes: 1