Sergiu
Sergiu

Reputation: 53

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

Upvotes: 3

Views: 1599

Answers (2)

Eli Dadia
Eli Dadia

Reputation: 11

Jan's answer is not quite right. If you are using the cook xmlrpc library all you would need to do is this:

        XmlRpcStruct postStruct = new XmlRpcStruct();
        postStruct.Add("type", "article");
        postStruct.Add("title", "wohoo another test");

        XmlRpcStruct postBodyStructParams = new XmlRpcStruct();
        postBodyStructParams.Add("value", "My body yaaay");
        postBodyStructParams.Add("format", "filtered_html");

        XmlRpcStruct[] postBodyStructParamsArr = new XmlRpcStruct[1];
        postBodyStructParamsArr[0] = postBodyStructParams;

        XmlRpcStruct postBodyStruct = new XmlRpcStruct();
        postBodyStruct.Add("und", postBodyStructParamsArr);

        postStruct.Add("body", postBodyStruct);

Unfortunately, the body params need to be an array of struct under the "und" key with only one value. I blame this on the sloppiness of the drupal xmlrpc API.

Upvotes: 0

Clive
Clive

Reputation: 36955

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!

Upvotes: 3

Related Questions