gpt4 book ai didi

c# - 在 REST 服务中反序列化 JSON

转载 作者:太空狗 更新时间:2023-10-30 01:33:01 25 4
gpt4 key购买 nike

我在我的其余自托管服务中反序列化 json 时遇到问题。

我有一个使用 JSON 调用自托管 REST 的测试页面,代码如下:

<!DOCTYPE html>

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<script type="text/javascript">
function doFunction() {

xhr = new XMLHttpRequest();
var url = "https://localhost:1234/business/test/testing2/endpoint";
xhr.open("POST", url, true);
xhr.setRequestHeader("Content-type", "application/json");
xhr.onreadystatechange = function () {
if (xhr.readyState == 4 && xhr.status == 200) {
var json = JSON.parse(xhr.responseText);
alert(json);
}
}
var data = JSON.stringify({ testing : "test" });
xhr.send(data);
}

</script>
<title></title>
</head>
<body>
<form id="form1" runat="server">
<div>
<input id="clickMe" type="button" value="clickme" onclick="doFunction();" />
</div>
</form>

</body>
</html>

这是我的自托管服务的接口(interface)和契约(Contract):

[DataContract]
public class OperationInput
{
[DataMember]
public string testing { get; set; }

}

[DataContract]
public class OperationOutput
{
[DataMember]
public int Status { get; set; }

[DataMember]
public string Message { get; set; }

[DataMember]
public string AddInfo { get; set; }

[DataMember]
public string PartnerID { get; set; }

[DataMember]
public string SessionID { get; set; }
}

[ServiceContract]
interface IRegisterOperation
{
[OperationContract]
[WebInvoke(UriTemplate = "/endpoint",
RequestFormat = WebMessageFormat.Json,
ResponseFormat = WebMessageFormat.Json, Method = "*")]
OperationOutput Operation(OperationInput order);
}

下面是接口(interface)的实现:

public class RegisterOperation : IRegisterOperation
{

public OperationOutput Operation(OperationInput input)
{
System.IO.StreamWriter file = new System.IO.StreamWriter("c:\\testing.txt", false);
file.WriteLine(input.testing);
file.Close();

OperationOutput output = new OperationOutput();
output.Status = 200;
output.Message = "The action has been successfully recorded on NAVe";
output.AddInfo = "";


return output;
}
}

我正在使用此代码创建自托管:

host = new ServiceHost(implementationType, baseAddress);

ServiceEndpoint se = host.AddServiceEndpoint(endpointType, new WebHttpBinding(WebHttpSecurityMode.Transport), "");
se.Behaviors.Add(new WebHttpBehavior());

host.Open();

使用调试,我注意到它在我的服务中命中了断点,因此对 localhost 的调用正常但输入参数为空,如下图所示:

debugging on visual studio

这是在 fiddler 上使用 JSON 捕获 POST 请求的 2 张图像:

fiddler first image fiddler second image

你知道为什么我得到 null 吗?而不是像我在 javascript 中调用时那样使用字符串“test”?

非常感谢您;)

编辑:

我在 Fiddler 上激活了 HTTPS 解密,现在按"is"在受信任的 CA 上安装证书而不是按“否”,断点被击中,现在 fiddler 捕获了一个选项请求,如下图所示

Options request Raw tab of Options request JSON tab of Options request

这不应该是一个 post 请求而不是一个 options 请求吗??也许这就是我看不到 json 的原因?

非常感谢

最佳答案

我想通了,问题出在 OPTIONS 请求上,我需要接收 POST 请求,以便获得 JSON。

我向我的服务主机添加了一个行为属性,以便它响应允许 wcf 服务主机接收跨源请求的选项请求。

所以我添加了这个 (Cross Origin Resource Sharing for c# WCF Restful web service hosted as Windows service) 问题的答案中的代码,现在我在第一个选项请求后收到了一个 POST 请求:

如果链接不再可用,这里是问题的解决方案:

代码:

创建2个类如下:

  1. MessageInspector 实现 IDispatchMessageInspector
  2. BehaviorAttribute 实现了 AttributeIEndpointBehaviorIOperationBehavior

具有以下详细信息:

//MessageInspector Class
using System;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.ServiceModel.Dispatcher;
using System.ServiceModel.Description;
namespace myCorsService
{
public class MessageInspector : IDispatchMessageInspector
{
private ServiceEndpoint _serviceEndpoint;

public MessageInspector(ServiceEndpoint serviceEndpoint)
{
_serviceEndpoint = serviceEndpoint;
}

/// <summary>
/// Called when an inbound message been received
/// </summary>
/// <param name="request">The request message.</param>
/// <param name="channel">The incoming channel.</param>
/// <param name="instanceContext">The current service instance.</param>
/// <returns>
/// The object used to correlate stateMsg.
/// This object is passed back in the method.
/// </returns>
public object AfterReceiveRequest(ref Message request,
IClientChannel channel,
InstanceContext instanceContext)
{
StateMessage stateMsg = null;
HttpRequestMessageProperty requestProperty = null;
if (request.Properties.ContainsKey(HttpRequestMessageProperty.Name))
{
requestProperty = request.Properties[HttpRequestMessageProperty.Name]
as HttpRequestMessageProperty;
}

if (requestProperty != null)
{
var origin = requestProperty.Headers["Origin"];
if (!string.IsNullOrEmpty(origin))
{
stateMsg = new StateMessage();
// if a cors options request (preflight) is detected,
// we create our own reply message and don't invoke any
// operation at all.
if (requestProperty.Method == "OPTIONS")
{
stateMsg.Message = Message.CreateMessage(request.Version, null);
}
request.Properties.Add("CrossOriginResourceSharingState", stateMsg);
}
}

return stateMsg;
}

/// <summary>
/// Called after the operation has returned but before the reply message
/// is sent.
/// </summary>
/// <param name="reply">The reply message. This value is null if the
/// operation is one way.</param>
/// <param name="correlationState">The correlation object returned from
/// the method.</param>
public void BeforeSendReply(ref Message reply, object correlationState)
{
var stateMsg = correlationState as StateMessage;

if (stateMsg != null)
{
if (stateMsg.Message != null)
{
reply = stateMsg.Message;
}

HttpResponseMessageProperty responseProperty = null;

if (reply.Properties.ContainsKey(HttpResponseMessageProperty.Name))
{
responseProperty = reply.Properties[HttpResponseMessageProperty.Name]
as HttpResponseMessageProperty;
}

if (responseProperty == null)
{
responseProperty = new HttpResponseMessageProperty();
reply.Properties.Add(HttpResponseMessageProperty.Name,
responseProperty);
}

// Access-Control-Allow-Origin should be added for all cors responses
responseProperty.Headers.Set("Access-Control-Allow-Origin", "*");

if (stateMsg.Message != null)
{
// the following headers should only be added for OPTIONS requests
responseProperty.Headers.Set("Access-Control-Allow-Methods",
"POST, OPTIONS, GET");
responseProperty.Headers.Set("Access-Control-Allow-Headers",
"Content-Type, Accept, Authorization, x-requested-with");
}
}
}
}

class StateMessage
{
public Message Message;
}
}

//BehaviorAttribute Class
using System;
using System.ServiceModel.Channels;
using System.ServiceModel.Description;
using System.ServiceModel.Dispatcher;

namespace OpenBetRetail.NFCReaderService
{
public class BehaviorAttribute : Attribute, IEndpointBehavior,
IOperationBehavior
{
public void Validate(ServiceEndpoint endpoint) { }

public void AddBindingParameters(ServiceEndpoint endpoint,
BindingParameterCollection bindingParameters) { }

/// <summary>
/// This service modify or extend the service across an endpoint.
/// </summary>
/// <param name="endpoint">The endpoint that exposes the contract.</param>
/// <param name="endpointDispatcher">The endpoint dispatcher to be
/// modified or extended.</param>
public void ApplyDispatchBehavior(ServiceEndpoint endpoint,
EndpointDispatcher endpointDispatcher)
{
// add inspector which detects cross origin requests
endpointDispatcher.DispatchRuntime.MessageInspectors.Add(
new MessageInspector(endpoint));
}

public void ApplyClientBehavior(ServiceEndpoint endpoint,
ClientRuntime clientRuntime) { }

public void Validate(OperationDescription operationDescription) { }

public void ApplyDispatchBehavior(OperationDescription operationDescription,
DispatchOperation dispatchOperation) { }

public void ApplyClientBehavior(OperationDescription operationDescription,
ClientOperation clientOperation) { }

public void AddBindingParameters(OperationDescription operationDescription,
BindingParameterCollection bindingParameters) { }

}
}

在此之后,您需要做的就是将此消息检查器添加到服务端点行为。

ServiceHost host = new ServiceHost(typeof(myService), _baseAddress);
foreach (ServiceEndpoint EP in host.Description.Endpoints)
EP.Behaviors.Add(new BehaviorAttribute());

感谢大家的帮助;)

关于c# - 在 REST 服务中反序列化 JSON,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35276102/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com