我在我的其他自托管服务中反序列化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>
以下是我自托管服务的界面和合同:
[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);
}
以下是界面的实现:
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的调用正在工作,但输入参数为null,如下图所示:
这是在fiddler上使用JSON捕获POST请求的2个图像:
你知道为什么我会变空吗?而不是字符串&#34; test&#34;就像我在javascript中调用一样?
非常感谢您提前;)
编辑:
我在Fiddler上激活了HTTPS Decryption,现在已经按下&#34;是&#34;在受信任的ca上安装证书而不是按下&#34; no&#34;,并且断点被命中,fiddler现在捕获了一个选项请求,如下图所示
这不是一个帖子请求而不是一个选项请求吗?也许这就是为什么我没有看到json?
非常感谢
答案 0 :(得分:2)
我明白了,问题是OPTIONS请求,我需要收到一个POST请求,所以我得到了JSON。
我向服务主机添加了一个行为属性,以便它响应选项请求,允许wcf服务主机接收跨源请求。
所以我在这个(Cross Origin Resource Sharing for c# WCF Restful web service hosted as Windows service)问题的答案中添加了代码,现在我在第一个选项请求后收到了POST请求:
如果该链接不再可用,则以下是问题的解决方案:
<强> CODE:强>
按如下方式创建2个类:
MessageInspector
正在实施IDispatchMessageInspector
。BehaviorAttribute
实施Attribute
,IEndpointBehavior
和IOperationBehavior
。具有以下细节:
//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());
感谢大家的帮助;)
答案 1 :(得分:1)
您有Method = "*"
我会试验:
Method = "POST"
....
[ServiceContract]
interface IRegisterOperation
{
OperationOutput Operation(OperationInput order);
像这样:
[OperationContract]
[WebInvoke(UriTemplate = "/registeroperation",
Method = "POST",
ResponseFormat = WebMessageFormat.Json,
BodyStyle = WebMessageBodyStyle.Bare)]
OperationOutput Operation(OperationInput order);
APPEND:
你的json看起来不正确(从屏幕截图中)
我希望有一些简单的东西:
{
"ACTPRDX": "test"
}
你能做一个&#34;警报&#34;在你对对象进行字符串化之后? 并显示结果?
但是(一般情况下)......如果你的json搞砸了,那么&#34;自动伏都教&#34; Wcf Service Method的工作没有成功。
.....
这可能是挑剔的,但试试这个:
注意资本&#34; T&#34;在连字符之后。
xhr.setRequestHeader("Content-Type", "application/json;charset=UTF-8");
我刚刚在我的代码中找到了这个:
var jsonObject = { ACTPRDX : "test" };
var whatToSendOverTheWire = JSON.stringify(jsonObject);
试试。
如上所述,你的json错了。修复是弄清楚它是如何搞砸的。
答案 2 :(得分:0)
您实际上是传递原语而不是预期的对象
var data = JSON.stringify({ ACTPRDX : "test" });
以上数据适用于方法:
public XYZ Something(string ACTPRDX)
您应该将对象发送到您的方法
var obj= new Object();
obj.ACTPRDX = "test";
var data = JSON.stringify({ order: obj});
接口和实现也有不同的名称参数OperationInput - &gt;订单和输入。