Welcome to the Second Life Forums Archive

These forums are CLOSED. Please visit the new forums HERE

C# XMLRPC Example

JustAnother Millhouse
Registered User
Join date: 26 Dec 2004
Posts: 31
02-10-2005 20:18
I decided to cook up some sample code for using C#/.NET just to give some people with the burning desire to talk to their SL objects a basis to start on.

The code itself is nothing special, .NET makes it pretty easy to actually POST to the webservice. I wrote it in SharpDevelop (a freeware .NET coding environment thats not half bad) and compiled it with Mono. Also tested it with the MS compiler and framework v1.1 without problem.

Below the actual class library I am attaching a driver which implements the other half of the equation for the sample code found on the wiki

Before anyone goes on any while "well you should have coded it this way" session please note that this was written to be easy to read/understand. It is by no means designed for high performance, if I wanted that I wouldn't have used GetElementsByTagName in my xml calls, along with any number of other changes (Error handing for the webservice post, error handling for data-types, UriEncoding of sent data). Please use this code simply to understand how the process works and I hope it leads to someone coding something really cool.


CODE

// C# XMLRPC FOR SL Example by JustAnother Millhouse
// 2/10/2005

// Released to the SL public for whatever use they so please. If you make something nifty with it
// let me know, I'm always interested in seeing cool stuff.



using System;
using System.Text;
using System.Xml;
using System.Net;

namespace XMLRPC
{

//
public class XmlRPCResponseException : Exception
{
private string mMessage;
private int mErrorCode;

public string FaultMessage
{
get{ return this.mMessage; }
}

public int FaultCode
{
get{ return this.mErrorCode; }
}

public XmlRPCResponseException(string msg, int val)
{
this.mMessage = msg;
this.mErrorCode = val;
}

public override string ToString()
{
return base.ToString() + this.mMessage + " : " + this.mErrorCode;
}
}

public class XmlRPCRequest
{
public XmlRPCRequest()
{

}

// some public values to hold request/response
public string Channel;
public int IntValue;
public string StringValue;


public void SendXMLRPC()
{

//setup a webclient
WebClient web = new WebClient();

//build XML to send as request
byte[] byteArray = Encoding.ASCII.GetBytes(BuildRequest());

//post to server
byte[] responseArray = web.UploadData("http://xmlrpc.secondlife.com/cgi-bin/xmlrpc.cgi","POST",byteArray);
string serverResponse = Encoding.ASCII.GetString(responseArray);

//parse response
ParseResponse(serverResponse);
}

private string BuildRequest()
{
//use stringbuilder to build the XML request we are going to send to
//the server.
StringBuilder sb = new StringBuilder();
sb.Append("<?xml version=\"1.0\"?>");
sb.Append("<methodCall>");
sb.Append(" <methodName>llRemoteData</methodName>");
sb.Append(" <params>");
sb.Append(" <param>");
sb.Append(" <value>");
sb.Append(" <struct>");
sb.Append(" <member>");
sb.Append(" <name>Channel</name>");
sb.AppendFormat(" <value><string>{0}</string></value>",Channel);
sb.Append(" </member>");
sb.Append(" <member>");
sb.Append(" <name>IntValue</name>");
sb.AppendFormat(" <value><int>{0}</int></value>",IntValue);
sb.Append(" </member>");
sb.Append(" <member>");
sb.Append(" <name>StringValue</name>");
sb.AppendFormat(" <value><string>{0}</string></value>",StringValue);
sb.Append(" </member>");
sb.Append(" </struct>");
sb.Append(" </value>");
sb.Append(" </param>");
sb.Append(" </params>");
sb.Append("</methodCall>");
return sb.ToString();
}

// parse response, if there is a fault string, throw an exception with faultCode
private void ParseResponse(string response)
{
XmlDocument tempDom = new XmlDocument();

try
{
//load up our response xml into a DOM document
tempDom.LoadXml(response);
}
catch
{
// if we cannot load up response into XML dom then bad things happened
// throw generic exception
throw new Exception("Corrupt XML response received from server.");
}

// if a fault occured, throw an exception
if(tempDom.GetElementsByTagName("name")[0].InnerText.ToLower() == "faultstring")
{
throw new XmlRPCResponseException(tempDom.GetElementsByTagName("string")[0].InnerText, Int32.Parse(tempDom.GetElementsByTagName("int")[0].InnerText));
}
else
{
this.Channel = tempDom.GetElementsByTagName("string")[0].InnerText;
this.StringValue = tempDom.GetElementsByTagName("string")[1].InnerText;
this.IntValue = Int32.Parse(tempDom.GetElementsByTagName("int")[0].InnerText);
}
}
}
}



Sample Driver

CODE

using System;

namespace XMLRPC
{
/// <summary>
/// Summary description for Class1.
/// </summary>
class Class1
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main(string[] args)
{
XmlRPCRequest s = new XmlRPCRequest();

s.Channel = "88733d7d-c46f-bef5-3a6f-f7eb59ecfb13"; // set the UUID the script from the wiki outputs to you here
s.IntValue = 4;
s.StringValue = "How are you?";

s.SendXMLRPC();

Console.WriteLine(s.StringValue);
Console.ReadLine();
}
}
}
Strangeweather Bomazi
has no clever catchphrase
Join date: 29 Jan 2005
Posts: 116
02-11-2005 10:52
Very cool! I do a lot of C# development, but I haven't yet tried to write anything to communicate with SL -- I can't wait to try this out. Thanks!
Tcoz Bach
Tyrell Victim
Join date: 10 Dec 2002
Posts: 973
02-11-2005 18:13
You can also just grab the .Net XMLRPC library (which does some nice things) from CookComputing. It's free plug 'n play assembly. Saves you the effort of whacking together the protocol yourself.
_____________________
** ...you want to do WHAT with that cube? **
JustAnother Millhouse
Registered User
Join date: 26 Dec 2004
Posts: 31
02-12-2005 11:05
From: Tcoz Bach
You can also just grab the .Net XMLRPC library (which does some nice things) from CookComputing. It's free plug 'n play assembly. Saves you the effort of whacking together the protocol yourself.


Ran that for awhile and just got tired of the overhead of having an entire library to do soemthing so simple which is why I hacked my own up. But you are 100% correct theirs is a nice system that does far more than mine.
JustAnother Millhouse
Registered User
Join date: 26 Dec 2004
Posts: 31
02-12-2005 13:53
From: Tcoz Bach
You can also just grab the .Net XMLRPC library (which does some nice things) from CookComputing. It's free plug 'n play assembly. Saves you the effort of whacking together the protocol yourself.


Agreed, great library and is what I actually use. But to prevent the need of 3rd party i cooked that thing up above.
Sitting Lightcloud
Registered User
Join date: 13 May 2004
Posts: 109
02-12-2005 22:32
Awesome! Thank you so very much for sharing this!
_____________________

Sitting Lightcloud
Registered User
Join date: 13 May 2004
Posts: 109
02-12-2005 22:34
Awesome, thank you so very much for sharing this in a great format I might add.
_____________________

Sitting Lightcloud
Registered User
Join date: 13 May 2004
Posts: 109
02-13-2005 01:09
Thank you so much for posting this in sucha great format!
_____________________

Sitting Lightcloud
Registered User
Join date: 13 May 2004
Posts: 109
02-14-2005 05:30
Great sample thanks for sharing!
_____________________

CamperDave Proudfoot
(_)|33P\ 1337 $xor
Join date: 16 Sep 2004
Posts: 205
Dumb Question
03-01-2005 15:05
How shouldI compile this?

I mean, 2 separate exe's, 1 exe, 1 dll (code pt 1) 1 exe driver ect.... :confused:
_____________________
The PWNED SHOP!


List of Cool Things I've done first... I think
  1. Put on sale a key mod that makes SL more like an FPS
  2. Made my own custom attachment points - looking for a good use
  3. Found "secret" login screen.
  4. Created a way to call Java methods from LSL --> Thread
JustAnother Millhouse
Registered User
Join date: 26 Dec 2004
Posts: 31
03-03-2005 13:48
From: CamperDave Proudfoot
How shouldI compile this?

I mean, 2 separate exe's, 1 exe, 1 dll (code pt 1) 1 exe driver ect.... :confused:



Two class files contained inside the same EXE. The first was named: XmlRPCRequest.cs
the 2nd was named: Class1.cs (the generic one created from a new Console application wizard). The one thing to make sure of us your namespacing, if you create a new project that uses a different namespace than my example code you will need to include a "using XMLRPC;" at the top of your Class1.cs.

The attached ZIP file contains a full working solution for the sample code I have already provided. The only thing that is missing is the in-game LSL scripting required to power this. That code can be found at: http://secondlife.com/badgeo/wakka.php?wakka=XMLRPC

If after all of this you're still totally cornfused, find me in-game and I will do what I can to assist.

EDIT - Added SharpDevelop combine files for those who lack visual studio.net.

JA
CliffordB Hightower
Registered User
Join date: 9 Feb 2006
Posts: 4
Thank You
07-08-2006 17:43
Hey, this is the Rosetta stone that I have been looking for to help me out with in and out of game communication. As far as the c# coding standards gestapo, don't ever worry about those types slowing you down. Without people like you innovating they would never have the base code to get anal over.

Thanks again.
Max Wunderland
Registered User
Join date: 22 Nov 2006
Posts: 1
Cool
11-28-2006 04:26
I'm have been working as a .NET-programmer for about 4 years, and before that I worked as a J2EE/Java programmer for several years and also have experience with C++ and other languages.

I really like .NET now-a-days, so it's cool to see that there are other C#-programmers in SL.