如何使自托管 wcf 接受 REST/JSON?

How do i make a self hosted wcf accept REST/JSON?

我在 SO 上的几篇文章中读到,可以创建接受 JSON 作为输入的自托管 wcf REST 服务。但是我无法让它工作,我似乎一遍又一遍地用头撞同一块石头:(

这是我无法正常工作的非常基本的代码。 我在 VS 2017 中使用 .net 4.6.1

[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();
}

然后我用这个代码连接

        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; 

我把这个拿回来了。

"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'."

我无法让它工作!我尝试过不同的客户端实现,但结果相同。 在每个答案中,我都检查说只使用

[WebInvoke(Method = "POST", BodyStyle = WebMessageBodyStyle.Wrapped, RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json)]

而且我应该很好。但它不起作用,我有点沮丧,因为这是我能想到的最简单的例子。

那我做错了什么?

我以前使用过相同类型的实现,但对于 SOAP 项目,它工作得很好。这次我做不到了。

兄弟,我们需要使用 WebHttpBinding 来创建 Restful 风格的 WCF 服务。 这是一个例子。
https://docs.microsoft.com/en-us/dotnet/framework/wcf/feature-details/how-to-create-a-basic-wcf-web-http-service
Webservicehost也是我们创建Restful风格的服务时需要承载的服务。或者,我们可以向主机添加 WebHttpBehavior 端点行为,如下所示。

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();
    }
}

结果。

此外,对于BodyStyle=WebMessageBodyStyle.Wrapped属性,我们有自定义对象参数时请注意数据格式。

[WebInvoke(Method = "POST", BodyStyle = WebMessageBodyStyle.Wrapped, RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json)]
[OperationContract]
bool Save(BatchOfRows request);

假设BatchOfRows 有一个ID 属性。根据您的定义,Json 数据应该是。

{ “request”:{“ID”:1}}

详情。

如果有什么我可以帮忙的,请随时告诉我。