Search code examples
c#web-servicesdrupalxml-rpc

using c# to create node in drupal


i need to make a ("webservice") c# app that can create/update/delete nodes for/from drupal 7 using xmlrpc. everytime i run my app i get errors from the xmlrpc files(library). I tried to find code/documentation for C# using xmlrpc to connect to drupal, but in vain. I would be nice if you could point me in the right direction, or share some c# code with me.

{
[XmlRpcUrl("http://testing/testserver")]
public interface IDrupalServices
{
    [XmlRpcMethod("node.get")]
    XmlRpcStruct NodeLoad(int nid, string[] field);
    [XmlRpcMethod("node.save")]
    void NodeSave(XmlRpcStruct node);
}

public partial class Form1 : Form
{

    public Form1()
    {
        InitializeComponent();

        IDrupalServices drupal = XmlRpcProxyGen.Create<IDrupalServices>();

        int nid = 227;
        string[] fields = new string[] { };

        XmlRpcStruct node = drupal.NodeLoad(nid, fields);

        string teaser = node["teaser"].ToString();
        welcomeTxt.Text = teaser;
    }

    private void button1_Click(object sender, EventArgs e)
    {
        string title = txtTitle.Text;
        string body = txtBody.Text;

        IDrupalServices drupal = XmlRpcProxyGen.Create<IDrupalServices>();

        XmlRpcStruct node = new XmlRpcStruct();

        node["id"] = 1001;
        node["title"] = title;
        node["body"] = body;
        node["teaser"] = body;
        node["format"] = 1;
        node["type"] = "webservice";
        node["promote"] = false;

        drupal.NodeSave(node);
        MessageBox.Show("The post was been created!");

    }
}
}

After i run this i get the error: Server returned a fault exception: [-32601] Server error. Requested method node.get not specified. - in the XmlRpcSerializer.cs

Thank you, Florin


Solution

  • If you're using Drupal 7 you must be using Services 3 which doesn't have a node.get method (or node.save as it happens). They've been replaced with node.retrieve and node.create & node.update respectively.

    You can view all of the available methods in the resources/node_resource.inc file in the Services module folder.

    UPDATE

    Internally the node is submitted using drupal_execute which is the function used to submit a form. Since the body is a field in Drupal it's expected to be a multi-dimensional array in this format (PHP version):

    $data["body"][$language][0]["value"]
    

    The $language will either be the specific language for the node, or und for undefined language (unless you're dealing with a multi-lingual site und is usually the way to go). You'd need to build an array similar to that in your C# code and Drupal should save it.

    ANOTHER UPDATE

    The Java XML-RPC client example for Services uses a HashMap type to do this so my best guess is you could use a Dictionary (albeit one that seems unnecessarily complicated):

    var innerValue = new Dictionary<string, string>();
    innerValue.Add("value", txtBody.Text);
    
    var language = new Dictionary<int, Dictionary<string, string>>();
    language.Add(0, innerValue);
    
    var body = new Dictionary<string, Dictionary<int, Dictionary<string, string>>>();
    body.Add("und", language);
    
    node["body"] = body;
    

    It's been a few years since I've coded in C# so forgive any errors in there. Also I'm pretty sure it could be declared more efficiently but I've forgotten most of the language to be honest!