JSON deamination in REST service

I am having a json deserialization issue in my own self-service.

I have a test page that calls self-serving REST with JSON, here is the code:

<!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>

And here is my self-service interface and contracts:

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

And here is the implementation of the 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;
        }
    }

I create self-host using this code:

host = new ServiceHost(implementationType, baseAddress);

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

                host.Open();

Using debug, I notice that it hits a breakpoint inside my service, so calling localhost works, but the input parameter is NULL, as you can see in the image below:

visual studio debugging

Here are 2 images capturing a POST request with JSON on the violin:

fiddler first image fiddler second image

Do you have any idea why I am getting null? instead of the string "test", how do I do when called in javascript?

Thank you very much in advance;)

EDIT:

HTTPS Fiddler "", ca "", , ,

Request for parameters Raw Parameter Request Tab parameter request JSON tab

? , json?

+4
3

, OPTIONS, POST-, JSON.

-, , wcf .

, ( # WCF Restful web-, Windows), 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());

;)

+2

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"
}

"" , ? ?

( )... json , "auto voodoo" Wcf Service Method .

.....

nit-picky, :

"T" .

xhr.setRequestHeader("Content-Type", "application/json;charset=UTF-8");

:

        var jsonObject = { ACTPRDX : "test" };
        var whatToSendOverTheWire = JSON.stringify(jsonObject);

.

, json . , , .

+1

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 → .

0

Source: https://habr.com/ru/post/1627835/


All Articles