Equivalent to Delphis GetDispatchInfo () on ROSDK.Net

net

(Jens) #1

How can I intercept the dispatch-info in .Net, to log the Client IP-Address or contents of the text-based messages (JSON,SOAP)?

Old Delphi code:

procedure TNewService.RORemoteDataModuleGetDispatchInfo(
  const aTransport: IROTransport; const aMessage: IROMessage);
var tcpinfo:IROTCPtransport;
begin
  if Supports(aTransport, IROTCPtransport, tcpinfo) then
  begin
    Session['ClientIp'] := tcpinfo.GetClientAddress;
    if aMessage is (IROJsonMessage) 
    (
         ....   // log the DataStream of aMessage
    );
  end;
end;

(antonk) #3

Hello

Implement the RemObjects.SDK.Server.IMessageAwareService interface service in your service like this:

public IMessage Message
{
  get
  {
    return null; // This is not used anyway
  }
  set
  {
    // Here value contains actual Message instance
    // this.ServerChannel contains channel info
  }
}

Regards


(Jens) #4

Hi Anton,

I’m still not sure how I can catch the whole “Message content stream” into a string (for example) of the JSON Message.

public IMessage Message
{
  get
  {
    return null; // This is not used anyway
  }
  set
  {

    string messageText;
    if (value is JsonMessage)
    {
        var msg = (JsonMessage)value;
        // messageText =msg.  ?????

    }
    else if (value is SoapMessage)
    {
        var msg = (SoapMessage)value;
        messageText =msg.InnerXML.ToString();
    }
    Log( LogDetail.Debug, "Got Message: " + messageText ?? "<empty Request>");
}

(antonk) #5

For SOAP message check out its MessageNode property.

Unfortunately it is not possible to access JSON message contents as a string without serializing this message back into a stream, which would corrupt this message’s internal state.


(Jens) #6

Any other chance to log/dump the raw JSON data, before the SDK tries to deserialize it back into a ComplexType?
Sometimes this can be helpful while troubleshooting, if a 3rd party tries to send invalid serialized data to our services.


(antonk) #7

Please try this code:

		var stream = message.GetStream();
		var dump = StreamHelpers.StreamToUtf8String(stream);
		System.Diagnostics.Debug.WriteLine(dump);

Btw it should work for both SOAP and JSON messages. However please be aware that the .GetStream method is rather resources-heavy.


(Jens) #8

Thank you. The resource usage doesn’t matter in this case. I’ll enable the “request logging” case by case, just to see what’s going wrong.

One last thing. :wink:
Now I’m able to log BIN, SOAP and JSON Messages but the “IMessageAwareService > Message > get { … }” will not be called on HttpApi Reqests. How can I log/dump the raw incoming Data on HttpApi?


(antonk) #9

Hello

Seems you’re using an old build of Remoting SDK. Support for the IMessageAwareService interface has been added to HTTP API at 17.04.2017

However the internal message instance used by HTTP API is a very special thing and it doesn’t implement the GetStream method. This code can help you dump the message content, but please remember that it should be never used in production:

		var requestParameters = message.GetType().GetField("_requestParameters", BindingFlags.NonPublic|BindingFlags.Instance).GetValue(message) as IDictionary<String, String>;
		if (requestParameters != null)
		{
			foreach (var p in requestParameters)
			{
				System.Diagnostics.Debug.WriteLine($"{p.Key}: {p.Value}");
			}
		}

		var contentMessage = message.GetType().GetField("_internalMessage", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(message) as IMessage;
		if (contentMessage != null)
		{
			var stream = contentMessage.GetStream();
			var dump = StreamHelpers.StreamToUtf8String(stream);
            // Actual request body is contained within the params node:
			System.Diagnostics.Debug.WriteLine(dump);
		}

HTTP API request consists of 2 parts: parameters passed via request URL and parameters passed via request body.


A more clean way to access request data (which will also work on older SDK versions) is to take the HttpApiDispatcher class and to override its method

    void Process(IHttpRequest request, IHttpResponse response, Stream requestData, Stream responseData)

Its request and requestData parameters provide full access to the incoming request.

Regards


(Jens) #10

Sorry, my bad. I tried this with a service, where the “Message property” was implemented, but where I missed to add the IMessageAwareService interface to the class definition.

Thank you.