【问题标题】:How do i make a self hosted wcf accept REST/JSON?如何让自托管 wcf 接受 REST/JSON?
【发布时间】:2019-08-19 06:44:41
【问题描述】:

我在几篇关于 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; 

在respose我得到了这个。

"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 项目,它工作得很好。这次我做不到。

【问题讨论】:

    标签: json rest wcf rest-client


    【解决方案1】:

    兄弟,我们需要使用 WebHttpBinding 来创建 Restful 风格的 WCF 服务。 这是一个例子。
    https://docs.microsoft.com/en-us/dotnet/framework/wcf/feature-details/how-to-create-a-basic-wcf-web-http-service
    当我们创建 Restful 风格的服务时,也需要 Webservicehost 来托管服务。或者,我们可以将 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属性,我们有Custom object参数时请注意数据格式。

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

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

    { “请求”:{“ID”:1}}

    详情
    Get the object is null using JSON in WCF Service
    如果有什么可以帮助的,请随时告诉我。

    【讨论】:

    • 但是现在我遇到了另一个问题...我简化了我的 BatchOrRows 类,以确保不是那个问题。现在我又添加了完整的类,它停止了分叉。如果我删除所有日期时间属性,它会起作用......知道如何解决这个问题吗?
    • 没关系...让它与stackoverflow.com/a/16468881/619791一起工作
    • 它适用于 http...但不适用于 https。是否需要进行很多更改才能使 https 也正常工作?
    • 免得评论里出现冗长的讨论,请发新帖,我会跟进的。
    • 我把它作为一个新问题发布了,我真的很希望你能帮到你! stackoverflow.com/questions/57678485/…
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-11-20
    • 2014-07-04
    • 1970-01-01
    • 2012-08-21
    • 2011-07-19
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多