[英]Deserializing JSON in REST Service
我在我的其他自托管服務中反序列化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個圖像:
你知道為什么我會變空嗎? 而不是像我在javascript中調用那樣的字符串“test”?
非常感謝您提前;)
編輯:
我在Fiddler上激活了HTTPS Decryption,現在按下“Yes”將證書安裝在受信任的ca上,而不是按下“no”,斷點被點擊,fiddler現在捕獲了一個選項請求,如下圖所示
這不應該是一個帖子請求而不是一個選項請求?? 也許那就是為什么我沒有看到json?
非常感謝
我想通了,問題是OPTIONS請求,我需要收到一個POST請求,所以我得到了JSON。
我向我的服務主機添加了一個行為屬性,以便它響應選項請求,允許wcf服務主機接收跨源請求。
所以我從這個問題的答案中添加了代碼( 作為Windows服務托管的c#WCF Restful Web服務的跨源資源共享 )問題,現在我在第一個Options請求之后得到一個POST請求:
如果鏈接不再可用,以下是問題的解決方案:
碼:
創建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());
謝謝大家的幫助;)
你有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);
附加:
你的json看起來不正確(從屏幕截圖)
我希望有一些簡單的東西:
{
"ACTPRDX": "test"
}
你可以在對對象進行字符串化后立即進行“提醒”嗎? 並顯示結果?
但是(一般情況下)......如果你的json搞砸了,Wcf服務方法的“自動伏都教”將無效。
.....
這可能是挑剔的,但試試這個:
注意連字符后面的大寫“T”。
xhr.setRequestHeader("Content-Type", "application/json;charset=UTF-8");
我剛剛在我的代碼中找到了這個:
var jsonObject = { ACTPRDX : "test" };
var whatToSendOverTheWire = JSON.stringify(jsonObject);
試試吧。
如上所述,你的json錯了。 修復是弄清楚它是如何搞砸的。
你實際上傳遞原始而不是預期的對象
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 - > order和input。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.