Not logged in. · Lost password · Register
Forum: MatriX and XmppDotNet RSS
not sure how to call a XMPP API using MatriX vNext
Siyit #1
Member since Jan 2020 · 6 posts
Group memberships: Members
Show profile · Link to this post
Subject: Matrix vNext : how to send request for IqType.Set in .Net Core/C#
I'm new to XMPP. I've been trying to use MatriX vNext to call XMPP API. I checked 'ag-software.net' and forum. Only found brief code samples and even the most relevant ones are for 'IqType.Get'. I did manage to create xmppClient and connected to the XMPP Server successfully. However, I couldn't figure out how to send my request. If I understood correctly, below is the way to send Iq type requests and handle the response but I'm not sure how to mount the payload and extract the result from the response.

  1. xmppClient
  2.     .XmppXElementStream
  3.         .Where(el =>
  4.         el.OfType<Iq>
  5.         && el.Cast<T>().Type == IqType.Get
  6.         && el.Cast<T>().Query.OfType<Ping>())
  7.     .Subscribe(el =>
  8.     {
  9.         // handle and reply to incoming pings
  10.         var iq = xmppXElement.Cast<T>();
  11.  
  12.         var resIq = Factory.GetElement<T>();
  13.         resIq.Id    = iq.Id;
  14.         resIq.To    = iq.From;
  15.         resIq.Type  = IqType.Result;
  16.  
  17.         await xmppClient.SendAsync(resIq);
  18.     });
  19.  
  20.  
  21. // connect, secure, authenticate and bind
  22. await xmppClient.ConnectAsync();

Could you please show me an example for this. I'm tying to send the XML below:

Example Request:
  1. <iq from="username.apikey@api.coredial.com"
  2. id="rpc-1"
  3. to="service.api.coredial.com"
  4. type="set">
  5. <query xmlns="jabber:iq:rpc">
  6. <methodCall>
  7. <methodName>pbx.originate</methodName>
  8. <params>
  9. <param>
  10. <value>
  11. <int>77</int>
  12. </value>
  13. </param>
  14. <param>
  15. <value>
  16. <string>2101</string>
  17. </value>
  18. </param>
  19. </params>
  20. </methodCall>
  21. </query>
  22. </iq>

Example Response:
  1. <iq from="service.api.coredial.com"
  2. id="rpc-1"
  3. to="admin.apikey@api.coredial.com/resource"
  4. type="result">
  5. <query xmlns="jabber:iq:rpc">
  6. <methodResponse>
  7. <params>
  8. <param>
  9. <value>
  10. <boolean>1</boolean>
  11. </value>
  12. </param>
  13. </params>
  14. </methodResponse>
  15. </query>
  16. </iq>
This post was edited on 2020-01-17, 15:50 by Alex.
Avatar
Alex #2
Member since Feb 2003 · 4449 posts · Location: Germany
Group memberships: Administrators, Members
Show profile · Link to this post
Hello Siyit,

there are different ways to achieve what you are looking for.

You can use SendIqAsync function and await the response. This is described here in the docs:
https://www.matrix-xmpp.io/docs/info-query

And is a code snippet for it:
  1. // construct the iq query
  2. var vcardRequest = new VcardIq { Type = IqType.Get, To = "bob@example.com" };
  3.  
  4. // send the request and await the resposne
  5. var resultIq = await xmppClient.SendIqAsync(vcardRequest);
  6.  
  7. // check for success or failure
  8. if (resultIq.Type == IqType.Result)
  9. {
  10.     // server returned a result (sucsess)
  11.     // => process the vCard here
  12. }
  13. else if (resultIq.Type == IqType.Error)
  14. {
  15.     // server returned an error
  16.     // => handle error
  17. }

In the above example of course you have to build the iq object as defined in your Xml and use IqType.Set instead of IqType.Get.
Set and Get iq types both always have a response which needs to preserve the id attribute of your request. The id is what MatriX internal is using to await the response and return it to you.

The second option is just sending your request IQ without awaiting the response and Subscribe to the packets you are looking for in the XmppXElementStream. You already posted a code snippet for that from our docs.

The third option would be sending the request without awaiting the response and write a handler which you add to the pipeline and is filtering all incoming packets to match a predicate as descibed here:
https://www.matrix-xmpp.io/docs/handlers

Option 1 is the easiest. You have to find your preferred option depending on your use case and code design.

Let me know if this answers your question.

Alex
Siyit #3
Member since Jan 2020 · 6 posts
Group memberships: Members
Show profile · Link to this post
Hi Alex,

Thanks a lot for your quick response and the detailed explanation. With your help, I got it working now.
Siyit #4
Member since Jan 2020 · 6 posts
Group memberships: Members
Show profile · Link to this post
In reply to post #2
Hi Alex,

I think I'm gonna have to use the sample code I posted as an example because i need to subscribe as well. 'SendIqAsync(iq)' worked fine just to get success/failure. The real result I need comes only by subscribing. TypeOf(Iq), i got it,,but not Cast<T> and <ping>...
Anyway, in my case I described, how do I use the .XmppXElementStream and .subscribe ?? I assume the first part sends the request and the 'subscribe' part waits for the result. If so, then where does the request payload come in / where to add the Iq.Query?

Could you please help me understand with a detailed example.

Many thanks,
This post was edited on 2020-01-22, 05:08 by Siyit.
Avatar
Alex #5
Member since Feb 2003 · 4449 posts · Location: Germany
Group memberships: Administrators, Members
Show profile · Link to this post
Sorry, but I don't understand your question, can you please elaborate?

When you use SendIqAsync you can await the response. The result will be your Iq including the whole payload.
When you subscribe to packets its the same. It will give you always the complete XMPP stanza as is, including the payload when there is one.

just dump the stanza to the console in your test code to inspect it. Or use the debugger and step through for learning.

Sample 1:
  1. xmppClient
  2.     .XmppXElementStream
  3.         .Where(el =>
  4.         el.OfType<Iq>
  5.         && el.Cast<T>().Type == IqType.Get)
  6.     .Subscribe(el =>
  7.     {
  8.         // print the matching stanza
  9.         Console.WriteLine(el.ToString());
  10.     });

Sample 2:
  1. // construct the iq query
  2. var vcardRequest = new VcardIq { Type = IqType.Get, To = "bob@example.com" };
  3.  
  4. // send the request and await the resposne
  5. var resultIq = await xmppClient.SendIqAsync(vcardRequest);
  6.  
  7. // print the result
  8. Console.WriteLine(resultIq.ToString());
This post was edited on 2020-01-22, 10:11 by Alex.
Siyit #6
Member since Jan 2020 · 6 posts
Group memberships: Members
Show profile · Link to this post
Hi Alex,

1. for sample 2, I assign my XmppXElement data to Iq.Query as in

  1. var vcardRequest = new VcardIq { Type = IqType.Get, To = "bob@example.com" , Query = "<query><callmethod>xxx</callmethod></query>"};

And then

var resultIq = await xmppClient.SendIqAsync(vcardRequest);

So that I can send the payload which is assigned to 'Iq.Query'.

My question is : in the Sample 1, Where and how do I assign the query (<query><callmethod>xx</callmethod><query>) which is the payload i wanna send with the request???? And what's <T>? and what's the 'el.Cast' all about?
This post was edited 2 times, last on 2020-01-23, 10:56 by Alex.
Siyit #7
Member since Jan 2020 · 6 posts
Group memberships: Members
Show profile · Link to this post
In reply to post #5
If the Sample 1 works exactly the same as Sample 2, then the result will be the same. in my case it will return 'true/false' only. However, I need to subscribe to get 'callId' which only happens after the first call is done regardless it's successful or not. every status update triggered by the first call will  return certain update to the subscriber.

My question is: how do I subscribe to wait for that 'callId' to come to me? How does subscription work if we use it independently? because now after the first request is done, I need to subscribe and expect the information I need to arrive. By that I mean this time there is no request sending.
This post was edited on 2020-01-23, 00:10 by Siyit.
Siyit #8
Member since Jan 2020 · 6 posts
Group memberships: Members
Show profile · Link to this post
In reply to post #5
third question: after subscription, events will be published to me as they occur. How do receive it?
Avatar
Alex #9
Member since Feb 2003 · 4449 posts · Location: Germany
Group memberships: Administrators, Members
Show profile · Link to this post
In reply to post #6
Quote by Siyit:
So that I can send the payload which is assigned to 'Iq.Query'.

My question is : in the Sample 1, Where and how do I assign the query (<query><callmethod>xx</callmethod><query>) which is the payload i wanna send with the request???? And what's <T>? and what's the 'el.Cast' all about?

you should create XMPP protocol classes for all those packets (Xml elements) if they do not exist already in MatriX.
This is described here in the docs:
https://www.ag-software.net/matrix-xmpp-sdk/matrix-develop…

Also, Iq is derived from System.Xml.Linq.XElement.. So you could build your payload with XElement functionality as well.
See also:
https://docs.microsoft.com/en-us/dotnet/api/system.xml.lin…
Avatar
Alex #10
Member since Feb 2003 · 4449 posts · Location: Germany
Group memberships: Administrators, Members
Show profile · Link to this post
In reply to post #8
Quote by Siyit:
third question: after subscription, events will be published to me as they occur. How do receive it?

your subscription is replacing the event. In the subscribe method there is an Action which gets invoked whenever a matching packet comes in.

When you are not familiar with Reactive programming yet then please read more about it here:
Close Smaller – Larger + Reply to this post:
Verification code: VeriCode Please enter the word from the image into the text field below. (Type the letters only, lower case is okay.)
Smileys: :-) ;-) :-D :-p :blush: :cool: :rolleyes: :huh: :-/ <_< :-( :'( :#: :scared: 8-( :nuts: :-O
Special characters: