In Drupal gibt es ein Module Services, hiermit lässt sich eine Drupalwebseite über eine Remote-Schnittstelle ansprechen. So können ohne Drupal selbst zu nutzen Beiträge erstellt werden. Eine simple Windows-Anwendung kann dann z.B. einen Beitrag in Drupal anlegen, welcher dann von Drupal verwaltet wird.
Zur Kommunikation kann man unter anderem dass XML-RPC Protokoll nutzen (andere lassen sich auch nutzen), somit kann man aus einer ganzen Hand von Programmiersprachen und Entwicklungsumgebungen auf seinen Drupal Beiträge zugreifen. So kann man mittels Visual Studio und VB.NET mit relativ wenig Quelltext auf eine Drupalseite Connecten und diverse Operationen durchführen
Fertige Bibliotheken
Möchte man nicht selber eine Schnittellen zu Drupal programmieren, kann man sich auch fertige Bibliotheken runterladen. Mittels einfacher Funktionsaufrufe kann man so einen node editieren / ändern, Dateien hochladen (inkl. CCK), Taxonomy-System nutzen, ... . Ich habe bisher zwei fertige Bibliotheken gefunden, welche beide in C# geschrieben sind. Einmal DrupalXmlRpc .NET (Entwicklerseite) und DrutNet - Drupal .NET API .
Drupal Services Module
Wir erwähnt stellt uns dass Drupal Module Services die nötige Schnittstelle bereit. Nach der Installation sollten wir die Drupal Module XMLRPC Server, Node Service und User Service aktivieren. Zusätzliche sollten wir einmal auf die Drupal Berechtigungen achten. Loggt man sich nicht mit dem admin Account ein muss man dem "Remote-User" die nötigen Services Rechte geben (z.B. node_service-Modul -> load node data.
Services mit .NET
Zum Ansprechen der Services-Schnittstelle mittels .NET brauchen wir die XML-RPC Funktionen, welche leider nicht im .NET Framework enthalten sind. Es muss also die XML-RPC.NET DLL nachgerüstet werden (Datei nicht mit dem Windows-ZIP Programm entpacken, sonst fehlt der bin Ordner).
Hat man ein Verweise auf CookComputing.XmlRpc gesetzt kann man loslegen, man sollte allerdings bedenken, dass VB.NET nicht unbedingt dafür geeignet und etwas umständlicher ist, es wäre einfache C# zu nutzen.
VB.NET Beispiel
Ich habe eine einfache Klassen um Lesen und Erstellen eines Drupal Node erstellt, die kurz aufzeigt wie man es macht. Zum Teil habe ich die vorhanden C# Beispiele Bibliotheken genutzt und portiert als auch ein paar VB.NET Optimierungen vorgenommen. Direkt auf der Drupal Seite gibt es auch ein paar Beispiele: Example: User login with API key using C#
Dim DrupalPage As New DrupalXmlRpcInterface
'connect to a Drupal page
DrupalPage.Connect()
'login to page; you need a valid account
DrupalPage.Login("admin", "yourpw")
'the the content of the node 17
MsgBox(DrupalPage.GetNode(17).Body)
'create a drupal node template, save it into drupal an return the generated nodeid (nid)
Dim NewNode As DrupalXmlRpcInterface.DrupalNode = DrupalXmlRpcInterface.CreateNodeTemplate("test", "testbody", "page")
Dim nid As Integer = DrupalPage.SaveNode(NewNode)
MsgBox(nid)DrupalXmlRpcInterface
Imports CookComputing.XmlRpc
Imports System.Reflection
''' <summary>
''' An simple example of using the "Drupal Services Module" to get some nodes or to create some new one
''' </summary>
''' <remarks></remarks>
Public Class DrupalXmlRpcInterface
<XmlRpcUrl("http://localhost/services/xmlrpc")> _
Interface IDrupalServices
<XmlRpcMethod("node.get")> Function NodeGet(ByVal nid As Integer, ByVal fields() As String) As DrupalNode
<XmlRpcMethod("node.save")> Function NodeSave(ByVal node As XmlRpcStruct)
<XmlRpcMethod("user.login")> Function Login(ByVal username As String, ByVal password As String)
End Interface
Private _IDrupalServices As IDrupalServices
Private _loggedInUser As String = ""
''' <summary>
''' If Service Module needs a Authenfication call it after connect
''' needs Drupal Module "User Service"
''' </summary>
''' <param name="Username"></param>
''' <param name="Password"></param>
''' <returns></returns>
''' <remarks></remarks>
Function Login(ByVal Username As String, ByVal Password As String)
Try
Dim l As XmlRpcStruct = _IDrupalServices.Login(Username, Password)
_loggedInUser = Username
Return True
Catch ex As Exception
MsgBox(ex.Message)
Return False
End Try
End Function
''' <summary>
''' Connect to a Drupal site with enabled Service Module
''' </summary>
''' <remarks></remarks>
Sub Connect()
_IDrupalServices = CType(XmlRpcProxyGen.Create(GetType(IDrupalServices)), IDrupalServices)
End Sub
''' <summary>
''' This will save a Drupal node
''' needs Drupal Module "Node Service"
''' </summary>
''' <param name="Node"></param>
''' <returns></returns>
''' <remarks></remarks>
Function SaveNode(ByVal Node As DrupalNode)
Dim XmlRpcNode As XmlRpcStruct = ConvertToXmlRpcStruct(Of DrupalNode)(Node)
Return _IDrupalServices.NodeSave(XmlRpcNode)
End Function
''' <summary>
''' Create a full Drupal node
''' needs Drupal Module "Node Service"
''' </summary>
''' <param name="nid"></param>
''' <param name="fields"></param>
''' <returns></returns>
''' <remarks></remarks>
Function GetNode(ByVal nid As Integer, Optional ByVal fields() As String = Nothing) As DrupalNode
If fields Is Nothing Then fields = New String() {}
Return _IDrupalServices.NodeGet(nid, fields)
End Function
''' <summary>
''' This will create a Drupal Node template that we can use to save it
''' </summary>
''' <param name="Title"></param>
''' <param name="Body"></param>
''' <param name="ContentType"></param>
''' <returns></returns>
''' <remarks></remarks>
Shared Function CreateNodeTemplate(ByVal Title As String, ByVal Body As String, ByVal ContentType As String) As DrupalNode
Dim b As New DrupalNode
b.Title = Title
b.Body = Body
b.ContentType = ContentType
Return b
End Function
''' <summary>
''' This Function will convert a Class with XmlRpcMember Functions to a XmlRpcStruct
''' It walks to all Properties of a Class which has values and convert it to a XmlRpcStruct Object
''' </summary>
''' <typeparam name="T"></typeparam>
''' <param name="node"></param>
''' <returns></returns>
''' <remarks></remarks>
Private Function ConvertToXmlRpcStruct(Of T As DrupalNode)(ByVal node As T) As XmlRpcStruct
Dim xStruct As New XmlRpcStruct()
Dim ext As New KrmSoftware.ClassExtender(node)
Try
For Each pi As PropertyInfo In node.[GetType]().GetProperties()
Try
Dim att As XmlRpcMemberAttribute = TryCast(Attribute.GetCustomAttribute(pi, GetType(XmlRpcMemberAttribute)), XmlRpcMemberAttribute)
Dim value As Object = ext.GetValue(pi.Name)
If value IsNot Nothing Then
xStruct.Add(att.Member, value)
End If
Catch ex As Exception
End Try
Next
Return xStruct
Catch ex As Exception
Throw ex
End Try
End Function
''' <summary>
''' A Drupal Node Object Class
''' </summary>
''' <remarks></remarks>
<XmlRpcMissingMapping(MappingAction.Ignore)> _
Public Class DrupalNode
Private _NodeID As String
Private _Title As String
Private _Body As String
Private _Author As String
Private _ContentType As String
Public Sub New()
For Each pi As PropertyInfo In Me.[GetType]().GetProperties()
If pi.PropertyType Is GetType(XmlRpcStruct()) Then
pi.SetValue(Me, New XmlRpcStruct(0) {}, New Object() {})
End If
Next
End Sub
<XmlRpcMember(Description:="The NodeID", Member:="nid")> _
Public Property NodeID() As String
Get
Return _NodeID
End Get
Set(ByVal value As String)
_NodeID = value
End Set
End Property
<XmlRpcMember(Description:="", Member:="title")> _
Public Property Title() As String
Get
Return _Title
End Get
Set(ByVal value As String)
_Title = value
End Set
End Property
<XmlRpcMember(Description:="", Member:="body")> _
Public Property Body() As String
Get
Return _Body
End Get
Set(ByVal value As String)
_Body = value
End Set
End Property
<XmlRpcMember(Description:="", Member:="name")> _
Public Property Author() As String
Get
Return _Author
End Get
Set(ByVal value As String)
_Author = value
End Set
End Property
<XmlRpcMember(Description:="", Member:="type")> _
Public Property ContentType() As String
Get
Return _ContentType
End Get
Set(ByVal value As String)
_ContentType = value
End Set
End Property
End Class
End Class
