OTRS-RPC (SOAP) über .Net c# [Solved]

English! place to talk about development, programming and coding
Post Reply
Afra
Znuny newbie
Posts: 3
Joined: 06 Oct 2010, 16:41
Znuny Version: 2.4.5

OTRS-RPC (SOAP) über .Net c# [Solved]

Post by Afra »

Hi Leute,

ich bin gerade daran den OTRS-RPC Service zu nutzen um einen neuen Artikel zu erstellen. Leider habe ich mit meinem momentanen Fortschritt noch das Problem das ich keine Antwort vom Service bekomme, und dass das erstellte Ticket noch nicht dem entspricht was ich erwarten würde. Vielleicht kann mir ja einer von euch weiterhelfen und sagen warum ich keine Antwort von dem Service bekomme. Anbei der von mir verwendete Code (hilft vielleicht auch dem einen oder anderen dabei in diesem Thema weiterzukommen). Über jeden von euch gelieferten Tip oder Anmerkung bin ich jetzt schon dankbar ;)

Gruß,
Afra

Code: Select all

using System;
using System.Net;
using System.Xml;
using System.IO;
using System.Collections;
using System.Reflection;

namespace ConsoleApplication1
{
    class Program
    {
        #region fields
        /// <summary>
        /// File path vars.
        /// </summary>
        private static String errorFilePath = "C:\\OTRS_RPC\\otrserror.xml";
        private static String requestfilepath = "C:\\OTRS_RPC\\{0}_otrsrequest_Service{1}.xml";
        private static String responsefilepath = "C:\\OTRS_RPC\\{0}_otrsanswer_Service{1}.xml";
        private static String dateTimeFormat = "yyyyMMddTHHmmss";
        #region SERVICE_TICKETNUMBER
        private const int SERVICE_TICKETNUMBER = 1;
        /// <summary>
        /// This soap request tells otrs to count up the ticket number.
        /// Format params:
        /// {0}: username
        /// {1}: password
        /// </summary>
        private static String SOAP_TICKETNUMBER = @"<?xml version=""1.0"" encoding=""utf-8""?>
  <soap:Envelope xmlns:xsd=""http://www.w3.org/2001/XMLSchema"" soap:encodingStyle=""http://schemas.xmlsoap.org/soap/encoding/"" xmlns:soap=""http://schemas.xmlsoap.org/soap/envelope/"">
    <soap:Body>
      <Dispatch xmlns=""/Core"">
        <c-gensym4>{0}</c-gensym4>
        <c-gensym6>{1}</c-gensym6>

        <c-gensym8>TicketObject</c-gensym8>
        <c-gensym10>TicketCreateNumber</c-gensym10>
      </Dispatch>
    </soap:Body>
  </soap:Envelope>";
        #endregion
        #region SERVICE_CREATETICKET
        private const int SERVICE_CREATETICKET = 2;
        /// <summary>
        /// This soap request tells otrs to create a new ticket.
        /// Format params:
        /// {0}: username
        /// {1}: password
        /// {2}: ticket number
        /// {3}: ticket title
        /// {4}: queue name
        /// {5}: lock status
        /// {6}: priority id
        /// {7}: ticket state
        /// {8}: customer user
        /// {9}: owner id
        /// {10}: user id
        /// </summary>
        private static String SOAP_CREATETICKET = @"<?xml version=""1.0"" encoding=""utf-8""?>
  <soap:Envelope xmlns:xsd=""http://www.w3.org/2001/XMLSchema"" soap:encodingStyle=""http://schemas.xmlsoap.org/soap/encoding/"" xmlns:soap=""http://schemas.xmlsoap.org/soap/envelope/"">
    <soap:Body>
      <Dispatch xmlns=""/Core"">
        <c-gensym13>{0}</c-gensym13>
        <c-gensym15>{1}</c-gensym15>

        <c-gensym17>TicketObject</c-gensym17>
        <c-gensym19>TicketCreate</c-gensym19>

        <c-gensym21>TN</c-gensym21>
        <c-gensym23>{2}</c-gensym23>

        <c-gensym25>Title</c-gensym25>
        <c-gensym27>{3}</c-gensym27>

        <c-gensym29>Queue</c-gensym29>
        <c-gensym31>{4}</c-gensym31>

        <c-gensym33>Lock</c-gensym33>
        <c-gensym35>{5}</c-gensym35>

        <c-gensym37>PriorityID</c-gensym37>
        <c-gensym39>{6}</c-gensym39>

        <c-gensym41>State</c-gensym41>
        <c-gensym43>{7}</c-gensym43>

        <c-gensym45>CustomerUser</c-gensym45>
        <c-gensym47>{8}</c-gensym47>

        <c-gensym49>OwnerID</c-gensym49>
        <c-gensym51>{9}</c-gensym51>

        <c-gensym57>UserID</c-gensym57>
        <c-gensym59>{10}</c-gensym59>
      </Dispatch>
    </soap:Body>
  </soap:Envelope>";
        #endregion
        #region SERVICE_CREATETICKETARTICLE
        private const int SERVICE_CREATETICKETARTICLE = 3;
        /// <summary>
        /// This soap request tells otrs to create a new article for a specific ticket.
        /// Format params:
        /// {0}: username
        /// {1}: password
        /// {2}: ticket number
        /// {3}: article type
        /// {4}: sender type
        /// {5}: from
        /// {6}: to
        /// {7}: cc
        /// {8}: reply to
        /// {9}: subject
        /// {10}: body
        /// {11}: MessageID
        /// {12}: Charset
        /// {13}: HistoryType
        /// {14}: HistoryComment
        /// {15}: UserID
        /// {16}: NoAgentNotify
        /// {17}: Type
        /// {18}: Loop
        /// </summary>
        private static String SOAP_CREATETICKETARTICLE = @"<?xml version=""1.0"" encoding=""utf-8""?>
  <soap:Envelope xmlns:xsd=""http://www.w3.org/2001/XMLSchema"" soap:encodingStyle=""http://schemas.xmlsoap.org/soap/encoding/"" xmlns:soap=""http://schemas.xmlsoap.org/soap/envelope/"">
    <soap:Body>
      <Dispatch xmlns=""/Core"">
        <c-gensym62>{0}</c-gensym62>
        <c-gensym64>{1}</c-gensym64>

        <c-gensym66>TicketObject</c-gensym66>
        <c-gensym68>ArticleSend</c-gensym68>

        <c-gensym70>TicketID</c-gensym70>
        <c-gensym72>{2}</c-gensym72>

        <c-gensym74>ArticleType</c-gensym74>
        <c-gensym76>{3}</c-gensym76>

        <c-gensym78>SenderType</c-gensym78>
        <c-gensym80>{4}</c-gensym80>

        <c-gensym82>From</c-gensym82>
        <c-gensym84>{5}</c-gensym84>

        <c-gensym86>To</c-gensym86>
        <c-gensym88>{6}</c-gensym88>

        <c-gensym90>Cc</c-gensym90>
        <c-gensym92>{7}</c-gensym92>

        <c-gensym94>ReplyTo</c-gensym94>
        <c-gensym96>{8}</c-gensym96>

        <c-gensym98>Subject</c-gensym98>
        <c-gensym100>{9}</c-gensym100>

        <c-gensym102>Body</c-gensym102>
        <c-gensym104>{10}</c-gensym104>

        <c-gensym106>MessageID</c-gensym106>
        <c-gensym108>{11}</c-gensym108>

        <c-gensym110>Charset</c-gensym110>
        <c-gensym112>{12}</c-gensym112>

        <c-gensym114>HistoryType</c-gensym114>
        <c-gensym116>{13}</c-gensym116>

        <c-gensym118>HistoryComment</c-gensym118>
        <c-gensym120>{14}</c-gensym120>

        <c-gensym122>UserID</c-gensym122>
        <c-gensym124>{15}</c-gensym124>

        <c-gensym126>NoAgentNotify</c-gensym126>
        <c-gensym128>{16}</c-gensym128>

        <c-gensym130>Type</c-gensym130>
        <c-gensym132>{17}</c-gensym132>

        <c-gensym134>Loop</c-gensym134>
        <c-gensym136>{18}</c-gensym136>
      </Dispatch>
    </soap:Body>
  </soap:Envelope>";
        #endregion
        #endregion

        static void Main(string[] args)
        {
            /*
             * Pre's: Activate and set user and pw in otrs admin interface Core::SOAP
             * Install SOAP::Lite Perl module on the otrs host
             */
            //setting 
            String url = "http://otrs-adress/otrs/rpc.pl";
            String username = "root";
            String password = "root";
            String ticketNo = "28843";

            //allow unsafe header parsing
            //setAllowUnsafeHeaderParsing();
            //ticketnumber++
            ArrayList data = new ArrayList();
            data.Add(username);
            data.Add(password);
            serviceCall(url, SERVICE_TICKETNUMBER, data);
            //create ticket
            data.Clear();
            data.Add(username); //username
            data.Add(password); //password
            data.Add(ticketNo); //ticket number
            data.Add("RPC Test Ticket"); //ticket title
            data.Add("Postmaster"); //queue name
            data.Add("unlock"); //lock status
            data.Add("2"); //priority id
            data.Add("New"); //ticket state
            data.Add("a@b.de"); //customer user
            data.Add("1"); //owner id (1 is root)
            data.Add("1"); //user id (1 is root)
            //serviceCall(url, SERVICE_CREATETICKET, data);
            //create article for a ticket
            data.Clear();
            data.Add(username); //username
            data.Add(password); //password
            data.Add(ticketNo); //ticket number
            data.Add("email-external"); //article type
            data.Add("agent"); //sender type
            data.Add("a@b.de"); //from
            data.Add("a@b.de"); //to
            data.Add(""); //cc
            data.Add(""); //reply to
            data.Add("Test Ticket using RPC"); //subject
            data.Add("Herewith I declare this ticket articled!"); //body
            data.Add(""); //MessageID
            data.Add("ISO-8859-15"); //Charset
            data.Add("NewTicket"); //HistoryType
            data.Add("Created through RPC service"); //HistoryComment
            data.Add("1"); //UserID
            data.Add("0"); //NoAgentNotify
            data.Add("text/plain"); //Type
            data.Add("0"); //Loop
            //serviceCall(url, SERVICE_CREATETICKETARTICLE, data);
        }
        /// <summary>
        /// Set the HttpWebRequest config to allow unsafe header parsing.
        /// </summary>
        /// <returns></returns>
        public static bool setAllowUnsafeHeaderParsing()
        {
            //Get the assembly that contains the internal class
            Assembly aNetAssembly = Assembly.GetAssembly(typeof(System.Net.Configuration.SettingsSection));
            if (aNetAssembly != null)
            {
                //Use the assembly in order to get the internal type for the internal class
                Type aSettingsType = aNetAssembly.GetType("System.Net.Configuration.SettingsSectionInternal");
                if (aSettingsType != null)
                {
                    //Use the internal static property to get an instance of the internal settings class.
                    //If the static instance isn't created allready the property will create it for us.
                    object anInstance = aSettingsType.InvokeMember("Section",
                      BindingFlags.Static | BindingFlags.GetProperty | BindingFlags.NonPublic, null, null, new object[] { });

                    if (anInstance != null)
                    {
                        //Locate the private bool field that tells the framework is unsafe header parsing should be allowed or not
                        FieldInfo aUseUnsafeHeaderParsing = aSettingsType.GetField("useUnsafeHeaderParsing", BindingFlags.NonPublic | BindingFlags.Instance);
                        if (aUseUnsafeHeaderParsing != null)
                        {
                            aUseUnsafeHeaderParsing.SetValue(anInstance, true);
                            return true;
                        }
                    }
                }
            }
            return false;
        }
        /// <summary>
        /// Returns a HttpWebRequest for otrs soap action.
        /// </summary>
        /// <param name="url"></param>
        /// <returns></returns>
        public static HttpWebRequest createWebRequest(string url)
        {
            HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(url);
            webRequest.Headers.Add("SOAP:Action");
            webRequest.ContentType = "text/xml;charset=\"utf-8\"";
            webRequest.Accept = "text/xml";
            webRequest.Method = "POST";
            webRequest.Proxy = WebRequest.DefaultWebProxy;
            return webRequest;
        }
        /// <summary>
        /// Performs a service call to the otrs system.
        /// </summary>
        /// <param name="url"></param>
        /// <param name="service"></param>
        /// <param name="data"></param>
        /// <returns></returns>
        public static XmlDocument serviceCall(string url, int service, ArrayList data)
        {
            HttpWebRequest request = createWebRequest(url);

            XmlDocument soapEnvelopeXml = getSoapXml(service, data);

            //write request to file
            XmlWriter xw = XmlWriter.Create(String.Format(requestfilepath, DateTime.Now.ToString(dateTimeFormat), service);
            soapEnvelopeXml.WriteContentTo(xw);
            xw.Flush();
            xw.Close();

            using (Stream stream = request.GetRequestStream())
            {
                soapEnvelopeXml.Save(stream);
            }

            IAsyncResult asyncResult = request.BeginGetResponse(null, null);

            asyncResult.AsyncWaitHandle.WaitOne();

            string soapResult = String.Empty;
            try
            {
                using (WebResponse webResponse = request.EndGetResponse(asyncResult))
                using (StreamReader rd = new StreamReader(webResponse.GetResponseStream()))
                {
                    soapResult = rd.ReadToEnd();
                }
            }
            catch (WebException e)
            {
                if (e.Status == WebExceptionStatus.ProtocolError)
                {
                    WebResponse eresp = e.Response;
                    using (StreamReader sr = new StreamReader(eresp.GetResponseStream()))
                    {
                        String sresp = "\r\n<" + DateTime.Now.ToString(dateTimeFormat) + ">\r\n" + sr.ReadToEnd();
                        File.AppendAllText(errorFilePath, sresp);
                    }
                }
            }

            //write answer to file
            File.WriteAllText(String.Format(responsefilepath,DateTime.Now.ToString(dateTimeFormat),service), soapResult);

            XmlDocument resp = new XmlDocument();

            try
            {
                resp.LoadXml(soapResult);
            }
            catch (Exception) { }

            return resp;
        }
        /// <summary>
        /// Returns an XmlDocument for the stated service.
        /// </summary>
        /// <param name="service"></param>
        /// <param name="data"></param>
        /// <returns></returns>
        private static XmlDocument getSoapXml(int service, ArrayList data)
        {
            XmlDocument retVal = new XmlDocument();

            switch (service)
            {
                case SERVICE_TICKETNUMBER:
                    {
                        String soapenv = String.Format(SOAP_TICKETNUMBER, 
                            data[0].ToString()
                            , data[1].ToString());
                        retVal.LoadXml(soapenv);
                        return retVal;
                    }
                case SERVICE_CREATETICKET:
                    {
                        String soapenv = String.Format(SOAP_CREATETICKET, 
                            data[0].ToString()
                            , data[1].ToString()
                            , data[2].ToString()
                            , data[3].ToString()
                            , data[4].ToString()
                            , data[5].ToString()
                            , data[6].ToString()
                            , data[7].ToString()
                            , data[8].ToString()
                            , data[9].ToString()
                            , data[10].ToString());
                        retVal.LoadXml(soapenv);
                        return retVal;
                    }
                case SERVICE_CREATETICKETARTICLE:
                    {
                        String soapenv = String.Format(SOAP_CREATETICKETARTICLE,
                            data[0].ToString()
                            , data[1].ToString()
                            , data[2].ToString()
                            , data[3].ToString()
                            , data[4].ToString()
                            , data[5].ToString()
                            , data[6].ToString()
                            , data[7].ToString()
                            , data[8].ToString()
                            , data[9].ToString()
                            , data[10].ToString()
                            , data[11].ToString()
                            , data[12].ToString()
                            , data[13].ToString()
                            , data[14].ToString()
                            , data[15].ToString()
                            , data[16].ToString()
                            , data[17].ToString()
                            , data[18].ToString());
                        retVal.LoadXml(soapenv);
                        return retVal;
                    }
                default:{
                    throw new Exception("InvalidServiceException: The requested service does not exist.");
                }
            }
        }

    }
}
Last edited by Afra on 06 Oct 2010, 20:09, edited 1 time in total.
Afra
Znuny newbie
Posts: 3
Joined: 06 Oct 2010, 16:41
Znuny Version: 2.4.5

Re: OTRS-RPC (SOAP) über .Net c#

Post by Afra »

Hallo mal wieder,

mit einiger Geduld konnte ich nun meine Probleme lösen. Hier nun das fertige Beispiel wie man über c# den OTRS-RPC anspricht. Damit kann ein Ticket und ein Article erstellt werden. Eine Garantie fürs Funktionieren gibts aber nicht ;)
Viel Spaß damit,
Afra

Code: Select all

using System;
using System.Collections;
using System.IO;
using System.Net;
using System.Reflection;
using System.Xml;

namespace ConsoleApplication1
{
    class Program
    {
        #region fields
        /// <summary>
        /// File path vars.
        /// </summary>
        private static String errorFilePath = "C:\\OTRS_RPC\\otrserror.xml";
        private static String requestfilepath = "C:\\OTRS_RPC\\{0}_otrsrequest_Service{1}.xml";
        private static String responsefilepath = "C:\\OTRS_RPC\\{0}_otrsanswer_Service{1}.xml";
        private static String dateTimeFormat = "yyyyMMddTHHmmss";
        #region SERVICE_TICKETNUMBER
        private const int SERVICE_TICKETNUMBER = 1;
        /// <summary>
        /// This soap request tells otrs to count up the ticket number.
        /// Format params:
        /// {0}: username
        /// {1}: password
        /// </summary>
        private static String SOAP_TICKETNUMBER = @"<?xml version=""1.0"" encoding=""utf-8""?>
  <soap:Envelope xmlns:xsi=""http://www.w3.org/2001/XMLSchema-instance"" xmlns:soapenc=""http://schemas.xmlsoap.org/soap/encoding/"" xmlns:xsd=""http://www.w3.org/2001/XMLSchema"" soap:encodingStyle=""http://schemas.xmlsoap.org/soap/encoding/"" xmlns:soap=""http://schemas.xmlsoap.org/soap/envelope/"">
    <soap:Body>
      <Dispatch xmlns=""/Core"">
        <c-gensym4 xsi:type=""xsd:string"">{0}</c-gensym4>
        <c-gensym6 xsi:type=""xsd:string"">{1}</c-gensym6>

        <c-gensym8 xsi:type=""xsd:string"">TicketObject</c-gensym8>
        <c-gensym10 xsi:type=""xsd:string"">TicketCreateNumber</c-gensym10>
      </Dispatch>
    </soap:Body>
  </soap:Envelope>";
        #endregion
        #region SERVICE_CREATETICKET
        private const int SERVICE_CREATETICKET = 2;
        /// <summary>
        /// This soap request tells otrs to create a new ticket.
        /// Format params:
        /// {0}: username
        /// {1}: password
        /// {2}: ticket number
        /// {3}: ticket title
        /// {4}: queue name
        /// {5}: lock status
        /// {6}: priority id
        /// {7}: ticket state
        /// {8}: customer user
        /// {9}: owner id
        /// {10}: user id
        /// </summary>
        private static String SOAP_CREATETICKET = @"<?xml version=""1.0"" encoding=""utf-8""?>
  <soap:Envelope xmlns:xsi=""http://www.w3.org/2001/XMLSchema-instance"" xmlns:soapenc=""http://schemas.xmlsoap.org/soap/encoding/"" xmlns:xsd=""http://www.w3.org/2001/XMLSchema"" soap:encodingStyle=""http://schemas.xmlsoap.org/soap/encoding/"" xmlns:soap=""http://schemas.xmlsoap.org/soap/envelope/"">
    <soap:Body>
      <Dispatch xmlns=""/Core"">
        <c-gensym13 xsi:type=""xsd:string"">{0}</c-gensym13>
        <c-gensym15 xsi:type=""xsd:string"">{1}</c-gensym15>

        <c-gensym17 xsi:type=""xsd:string"">TicketObject</c-gensym17>
        <c-gensym19 xsi:type=""xsd:string"">TicketCreate</c-gensym19>
<!--
        <c-gensym21 xsi:type=""xsd:string"">TN</c-gensym21>
        <c-gensym23 xsi:type=""xsd:long"">{2}</c-gensym23>
-->
        <c-gensym25 xsi:type=""xsd:string"">Title</c-gensym25>
        <c-gensym27 xsi:type=""xsd:string"">{3}</c-gensym27>

        <c-gensym29 xsi:type=""xsd:string"">Queue</c-gensym29>
        <c-gensym31 xsi:type=""xsd:string"">{4}</c-gensym31>

        <c-gensym33 xsi:type=""xsd:string"">Lock</c-gensym33>
        <c-gensym35 xsi:type=""xsd:string"">{5}</c-gensym35>

        <c-gensym37 xsi:type=""xsd:string"">PriorityID</c-gensym37>
        <c-gensym39 xsi:type=""xsd:int"">{6}</c-gensym39>

        <c-gensym41 xsi:type=""xsd:string"">State</c-gensym41>
        <c-gensym43 xsi:type=""xsd:string"">{7}</c-gensym43>

        <c-gensym45 xsi:type=""xsd:string"">CustomerID</c-gensym45>
        <c-gensym47 xsi:type=""xsd:string"">{8}</c-gensym47>

        <c-gensym49 xsi:type=""xsd:string"">CustomerUser</c-gensym49>
        <c-gensym51 xsi:type=""xsd:string"">{9}</c-gensym51>

        <c-gensym53 xsi:type=""xsd:string"">OwnerID</c-gensym53>
        <c-gensym55 xsi:type=""xsd:int"">{10}</c-gensym55>

        <c-gensym57 xsi:type=""xsd:string"">UserID</c-gensym57>
        <c-gensym59 xsi:type=""xsd:int"">{11}</c-gensym59>
      </Dispatch>
    </soap:Body>
  </soap:Envelope>";
        #endregion
        #region SERVICE_CREATETICKETARTICLE
        private const int SERVICE_CREATETICKETARTICLE = 3;
        /// <summary>
        /// This soap request tells otrs to create a new article for a specific ticket.
        /// Format params:
        /// {0}: username
        /// {1}: password
        /// {2}: ticket number
        /// {3}: article type
        /// {4}: sender type
        /// {5}: from
        /// {6}: to
        /// {7}: cc
        /// {8}: reply to
        /// {9}: subject
        /// {10}: body
        /// {11}: MessageID
        /// {12}: Charset
        /// {13}: HistoryType
        /// {14}: HistoryComment
        /// {15}: UserID
        /// {16}: NoAgentNotify
        /// {17}: MimeType
        /// {18}: Loop
        /// </summary>
        private static String SOAP_CREATETICKETARTICLE = @"<?xml version=""1.0"" encoding=""utf-8""?>
  <soap:Envelope xmlns:xsi=""http://www.w3.org/2001/XMLSchema-instance"" xmlns:soapenc=""http://schemas.xmlsoap.org/soap/encoding/"" xmlns:xsd=""http://www.w3.org/2001/XMLSchema"" soap:encodingStyle=""http://schemas.xmlsoap.org/soap/encoding/"" xmlns:soap=""http://schemas.xmlsoap.org/soap/envelope/"">
    <soap:Body>
      <Dispatch xmlns=""/Core"">
        <c-gensym62 xsi:type=""xsd:string"">{0}</c-gensym62>
        <c-gensym64 xsi:type=""xsd:string"">{1}</c-gensym64>

        <c-gensym66 xsi:type=""xsd:string"">TicketObject</c-gensym66>
        <c-gensym68 xsi:type=""xsd:string"">ArticleSend</c-gensym68>

        <c-gensym70 xsi:type=""xsd:string"">TicketID</c-gensym70>
        <c-gensym72 xsi:type=""xsd:int"">{2}</c-gensym72>

        <c-gensym74 xsi:type=""xsd:string"">ArticleType</c-gensym74>
        <c-gensym76 xsi:type=""xsd:string"">{3}</c-gensym76>

        <c-gensym78 xsi:type=""xsd:string"">SenderType</c-gensym78>
        <c-gensym80 xsi:type=""xsd:string"">{4}</c-gensym80>

        <c-gensym82 xsi:type=""xsd:string"">From</c-gensym82>
        <c-gensym84 xsi:type=""xsd:string"">{5}</c-gensym84>

        <c-gensym86 xsi:type=""xsd:string"">To</c-gensym86>
        <c-gensym88 xsi:type=""xsd:string"">{6}</c-gensym88>

        <c-gensym90 xsi:type=""xsd:string"">Cc</c-gensym90>
        <c-gensym92 xsi:type=""xsd:string"">{7}</c-gensym92>

        <c-gensym94 xsi:type=""xsd:string"">ReplyTo</c-gensym94>
        <c-gensym96 xsi:type=""xsd:string"">{8}</c-gensym96>

        <c-gensym98 xsi:type=""xsd:string"">Subject</c-gensym98>
        <c-gensym100 xsi:type=""xsd:string"">{9}</c-gensym100>

        <c-gensym102 xsi:type=""xsd:string"">Body</c-gensym102>
        <c-gensym104 xsi:type=""xsd:string"">{10}</c-gensym104>

        <c-gensym106 xsi:type=""xsd:string"">MessageID</c-gensym106>
        <c-gensym108 xsi:type=""xsd:string"">{11}</c-gensym108>

        <c-gensym110 xsi:type=""xsd:string"">Charset</c-gensym110>
        <c-gensym112 xsi:type=""xsd:string"">{12}</c-gensym112>

        <c-gensym114 xsi:type=""xsd:string"">HistoryType</c-gensym114>
        <c-gensym116 xsi:type=""xsd:string"">{13}</c-gensym116>

        <c-gensym118 xsi:type=""xsd:string"">HistoryComment</c-gensym118>
        <c-gensym120 xsi:type=""xsd:string"">{14}</c-gensym120>

        <c-gensym122 xsi:type=""xsd:string"">UserID</c-gensym122>
        <c-gensym124 xsi:type=""xsd:int"">{15}</c-gensym124>

        <c-gensym126 xsi:type=""xsd:string"">NoAgentNotify</c-gensym126>
        <c-gensym128 xsi:type=""xsd:int"">{16}</c-gensym128>

        <c-gensym130 xsi:type=""xsd:string"">MimeType</c-gensym130>
        <c-gensym132 xsi:type=""xsd:string"">{17}</c-gensym132>

        <c-gensym134 xsi:type=""xsd:string"">Loop</c-gensym134>
        <c-gensym136 xsi:type=""xsd:int"">{18}</c-gensym136>
      </Dispatch>
    </soap:Body>
  </soap:Envelope>";
        #endregion
        #endregion

        static void Main(string[] args)
        {
            /*
             * Pre's: Activate and set user and pw in otrs admin interface Core::SOAP
             * Install SOAP::Lite Perl module on the otrs host
             */
            //setting 
            String url = "http://otrs-address/otrs/rpc.pl";
            String username = "root";
            String password = "root";

            //allow unsafe header parsing
            setAllowUnsafeHeaderParsing();
            //init data array
            ArrayList data = new ArrayList();
            #region ticketnumber++
            data.Add(username);
            data.Add(password);
            //XmlDocument s1Answer = serviceCall(url, SERVICE_TICKETNUMBER, data);
            //String s1XPath = "*/*/*/*";
            //String counterTicketNo = s1Answer.SelectSingleNode(s1XPath).InnerText; //typeof(Int)
            #endregion
            #region create ticket
            data.Clear();
            data.Add(username); //username
            data.Add(password); //password
            data.Add(String.Empty); //ticket number
            data.Add("RPC Test Ticket"); //ticket title
            data.Add("Postmaster"); //queue name
            data.Add("unlock"); //lock status
            data.Add("2"); //priority id
            data.Add("New"); //ticket state
            data.Add("a@b.de"); //customer id
            data.Add("a@b.de"); //customer user
            data.Add("1"); //owner id (1 is root)
            data.Add("1"); //user id (1 is root)
            XmlDocument s2Answer = serviceCall(url, SERVICE_CREATETICKET, data);
            String s2XPath = "*/*/*/*";
            String createdTicketId = s2Answer.SelectSingleNode(s2XPath).InnerText; //typeof(Int)
            #endregion
            #region create article for a ticket
            data.Clear();
            data.Add(username); //username
            data.Add(password); //password
            data.Add(createdTicketId); //ticket number
            data.Add("email-external"); //article type
            data.Add("agent"); //sender type
            data.Add("a@b.de"); //from
            data.Add("a@b.de"); //to
            data.Add(""); //cc
            data.Add(""); //reply to
            data.Add("Test Ticket using RPC"); //subject
            data.Add("Herewith I declare this ticket articled!"); //body
            data.Add(""); //MessageID
            data.Add("ISO-8859-15"); //Charset
            data.Add("NewTicket"); //HistoryType
            data.Add("Created through RPC service"); //HistoryComment
            data.Add("1"); //UserID
            data.Add("0"); //NoAgentNotify
            data.Add("text/plain"); //MimeType
            data.Add("0"); //Loop
            XmlDocument s3Answer = serviceCall(url, SERVICE_CREATETICKETARTICLE, data);
            String s3XPath = "*/*/*/*";
            String createdArticleId = s3Answer.SelectSingleNode(s3XPath).InnerText; //typeof(Int)
            #endregion
        }
        /// <summary>
        /// Set the HttpWebRequest config to allow unsafe header parsing.
        /// </summary>
        /// <returns></returns>
        public static bool setAllowUnsafeHeaderParsing()
        {
            //Get the assembly that contains the internal class
            Assembly aNetAssembly = Assembly.GetAssembly(typeof(System.Net.Configuration.SettingsSection));
            if (aNetAssembly != null)
            {
                //Use the assembly in order to get the internal type for the internal class
                Type aSettingsType = aNetAssembly.GetType("System.Net.Configuration.SettingsSectionInternal");
                if (aSettingsType != null)
                {
                    //Use the internal static property to get an instance of the internal settings class.
                    //If the static instance isn't created allready the property will create it for us.
                    object anInstance = aSettingsType.InvokeMember("Section",
                      BindingFlags.Static | BindingFlags.GetProperty | BindingFlags.NonPublic, null, null, new object[] { });

                    if (anInstance != null)
                    {
                        //Locate the private bool field that tells the framework is unsafe header parsing should be allowed or not
                        FieldInfo aUseUnsafeHeaderParsing = aSettingsType.GetField("useUnsafeHeaderParsing", BindingFlags.NonPublic | BindingFlags.Instance);
                        if (aUseUnsafeHeaderParsing != null)
                        {
                            aUseUnsafeHeaderParsing.SetValue(anInstance, true);
                            return true;
                        }
                    }
                }
            }
            return false;
        }
        /// <summary>
        /// Returns a HttpWebRequest for otrs soap action.
        /// </summary>
        /// <param name="url"></param>
        /// <returns></returns>
        public static HttpWebRequest createWebRequest(string url)
        {
            HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(url);
            webRequest.Headers.Add("SOAPAction", "/Core#Dispatch");
            webRequest.ContentType = "text/xml;charset=\"utf-8\"";
            webRequest.Accept = "text/xml";
            webRequest.Method = "POST";
            webRequest.Proxy = WebRequest.DefaultWebProxy;
            return webRequest;
        }
        /// <summary>
        /// Performs a service call to the otrs system.
        /// </summary>
        /// <param name="url"></param>
        /// <param name="service"></param>
        /// <param name="data"></param>
        /// <returns></returns>
        public static XmlDocument serviceCall(string url, int service, ArrayList data)
        {
            HttpWebRequest request = createWebRequest(url);

            XmlDocument soapEnvelopeXml = getSoapXml(service, data);

            //write request to file
            XmlWriter xw = XmlWriter.Create(String.Format(requestfilepath, DateTime.Now.ToString(dateTimeFormat), service));
            soapEnvelopeXml.WriteContentTo(xw);
            xw.Flush();
            xw.Close();

            using (Stream stream = request.GetRequestStream())
            {
                soapEnvelopeXml.Save(stream);
            }

            IAsyncResult asyncResult = request.BeginGetResponse(null, null);

            asyncResult.AsyncWaitHandle.WaitOne();

            string soapResult = String.Empty;
            try
            {
                using (WebResponse webResponse = request.EndGetResponse(asyncResult))
                using (StreamReader rd = new StreamReader(webResponse.GetResponseStream()))
                {
                    soapResult = rd.ReadToEnd();
                }
            }
            catch (WebException e)
            {
                WebResponse eresp = e.Response;
                using (StreamReader sr = new StreamReader(eresp.GetResponseStream()))
                {
                    String sresp = "\r\n<" + DateTime.Now.ToString(dateTimeFormat) + ">\r\n" + sr.ReadToEnd();
                    File.AppendAllText(errorFilePath, sresp);
                }
            }

            //write answer to file
            File.WriteAllText(String.Format(responsefilepath,DateTime.Now.ToString(dateTimeFormat),service), soapResult);

            XmlDocument resp = new XmlDocument();

            try
            {
                resp.LoadXml(soapResult);
            }
            catch (Exception) { }

            return resp;
        }
        /// <summary>
        /// Returns an XmlDocument for the stated service.
        /// </summary>
        /// <param name="service"></param>
        /// <param name="data"></param>
        /// <returns></returns>
        private static XmlDocument getSoapXml(int service, ArrayList data)
        {
            XmlDocument retVal = new XmlDocument();

            switch (service)
            {
                case SERVICE_TICKETNUMBER:
                    {
                        String soapenv = String.Format(SOAP_TICKETNUMBER, 
                            data[0].ToString()
                            , data[1].ToString()
                            );
                        retVal.LoadXml(soapenv);
                        return retVal;
                    }
                case SERVICE_CREATETICKET:
                    {
                        String soapenv = String.Format(SOAP_CREATETICKET, 
                            data[0].ToString()
                            , data[1].ToString()
                            , data[2].ToString()
                            , data[3].ToString()
                            , data[4].ToString()
                            , data[5].ToString()
                            , data[6].ToString()
                            , data[7].ToString()
                            , data[8].ToString()
                            , data[9].ToString()
                            , data[10].ToString()
                            , data[11].ToString()
                            );
                        retVal.LoadXml(soapenv);
                        return retVal;
                    }
                case SERVICE_CREATETICKETARTICLE:
                    {
                        String soapenv = String.Format(SOAP_CREATETICKETARTICLE,
                            data[0].ToString()
                            , data[1].ToString()
                            , data[2].ToString()
                            , data[3].ToString()
                            , data[4].ToString()
                            , data[5].ToString()
                            , data[6].ToString()
                            , data[7].ToString()
                            , data[8].ToString()
                            , data[9].ToString()
                            , data[10].ToString()
                            , data[11].ToString()
                            , data[12].ToString()
                            , data[13].ToString()
                            , data[14].ToString()
                            , data[15].ToString()
                            , data[16].ToString()
                            , data[17].ToString()
                            , data[18].ToString()
                            );
                        retVal.LoadXml(soapenv);
                        return retVal;
                    }
                default:{
                    throw new Exception("InvalidServiceException: The requested service does not exist.");
                }
            }
        }

    }
}
mlembke
Znuny newbie
Posts: 1
Joined: 14 Nov 2010, 23:55
Znuny Version: 3.0

Re: OTRS-RPC (SOAP) über .Net c# [Solved]

Post by mlembke »

Hallo Afra,

vielen Dank für den tollen Artikel. Der hat mir einen guten Einstieg geliefert.
Ich habe allerdings noch ein Problem mit den Artikeln.
Ich bin nicht in der Lage, ein Attachment mit hoch zu laden.

Hast Du das hinbekommen?

mfg.
Markus
Afra
Znuny newbie
Posts: 3
Joined: 06 Oct 2010, 16:41
Znuny Version: 2.4.5

Re: OTRS-RPC (SOAP) über .Net c# [Solved]

Post by Afra »

Hallo Markus,

ich habe das noch nicht versucht. Aber ich bin dazu übergegangen für Methoden welche ich nicht erfolgreich aufrufen konnte mein eigenes Perlmodul zu schreiben welche meine Parameter übernimmt und dann über einen Perl-Aufruf an das entsprechende Objekt weiterreicht. Vermutlich werde ich demnächst auch dazu gezwungen sein per RPC Attachments hinzuzufügen, aber solange ich noch darauf verzichten kann werde ich das tun ;)
Falls ich demnächst einmal die Zeit finde das auszuprobieren dann lasse ich euch meine Ergebnisse wissen.

Grüße,
Afra
kristov
Znuny newbie
Posts: 7
Joined: 10 Jan 2011, 14:21
Znuny Version: 2.4

Re: OTRS-RPC (SOAP) über .Net c# [Solved]

Post by kristov »

hello
I write a component in c# otrs to the bug reporter tried your code does not work correctly. After checking the error is by
" using (WebResponse webResponse = request.EndGetResponse(asyncResult)) "

in log error <?xml version="1.0" encoding="UTF-8"?><soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" soap:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xmlns:soap="http://schemas.xmlsoap.org/soap/envelop ... pplication failed during request deserialization:
no element found at line 1, column 0, byte -1 at F:at F:/OTRS/perl/site/lib/XML/Parser.pm line 187
/v</faultstring></soap:Fault></soap:Body></soap:Envelope>
please help urgently

ps
Can be a server configuration error? This server is installed on Widnows....

please help me ...
kristov
Znuny newbie
Posts: 7
Joined: 10 Jan 2011, 14:21
Znuny Version: 2.4

Re: OTRS-RPC (SOAP) über .Net c# [Solved]

Post by kristov »

hello
error, which I was due to server configuration
above code is working ... but
not send an email with the addition of a ticket to the queue
maybe someone knows how to solve this problem
thanks
UweKeim
Znuny newbie
Posts: 1
Joined: 28 May 2012, 18:50
Znuny Version: 3.1.5
Location: Göppingen
Contact:

"Internal Server Error 500"

Post by UweKeim »

Dank Afras coolem Code habe auch ich mich durchkämpfen können.

Bei mir trat interessanterweise ein Fehler "HTTP 500 Internal Server Error" auf, den ich durch einen schlichten Neustart des Rechner lösen konnte.

(Ich hatte alles in einer VMware mit Windows XP installiert und nach der OTRS-Installation nicht neu gebootet)

Ggf. hilft mein Kommentar hier ja mal einem Leidensgenossen.
MiniCroissant
Znuny newbie
Posts: 1
Joined: 11 Jun 2012, 11:21
Znuny Version: 3.1.5

Re: OTRS-RPC (SOAP) über .Net c# [Solved]

Post by MiniCroissant »

Hallo, ich habe es nun nach den Code-Beispielen endlich auch geschafft mir eine funktionierende Library zu erstellen. Allerdings habe ich es noch nicht hinbekommen die Ticketnummer (nicht die Ticket ID) zurück zu bekommen. Nach langem googeln habe ich diesen XML request hier gefunden:

Code: Select all

<SOAP:Envelope xmlns:SOAP-ENV=""http://schemas.xmlsoap.org/soap/envelope/"" xmlns:ns1=""Core"" xmlns:xsd=""http://www.w3.org/2001/XMLSchema"" xmlns:xsi=""http://www.w3.org/2001/XMLSchema-instance"" xmlns:SOAP-ENC=""http://schemas.xmlsoap.org/soap/encoding/"" SOAP-ENV:encodingStyle=""http://schemas.xmlsoap.org/soap/encoding/"">
  <SOAP:Body>
    <Dispatch xmlns=""/Core"">
      <TicketID xsi:type=""xsd:string"">{0}</TicketID>  
        <c-gensym8 xsi:type=""xsd:string"">TicketObject</c-gensym8>
        <c-gensym10 xsi:type=""xsd:string"">TicketNumberLookup</c-gensym10>
    </Dispatch>
  </SOAP:Body>
</SOAP:Envelope>"
Nachdem ich ein Ticket erstellt habe sende ich die empfangene Ticket ID mit dem oberen Request los, aber ich bekomme keine Antwort :( Hoffe mir kann da jemand weiter helfen.
leon
Znuny newbie
Posts: 7
Joined: 30 Oct 2012, 09:12
Znuny Version: 3.1.5

Re: OTRS-RPC (SOAP) über .Net c#

Post by leon »

Hey Leute,
Ich weiß nicht, ob hier noch irgendwer reinguckt, aber ich hoffe es einfach mal, da ich diesen Code bei mir zum Laufen bringen möchte.
Ich habe den Code erstmal so übernommen wie er ist und hab eben meine entsprechenden Daten eingetragen. Das Problem ist jetzt aber, dass ich damit kein Ticket erstellt bekomme. Meine s2Answer sieht folgendermaßen aus:

Code: Select all

<?xml version="1.0" encoding="UTF-8"?>
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" 
    xmlns:xsd="http://www.w3.org/2001/XMLSchema"
    soap:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
    xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
    <soap:Body>
        <DispatchResponse xmlns="/Core" xsi:nil="true" />
    </soap:Body>
</soap:Envelope>
Ich bekomme also ein true zurück. Da müsste ja eigentlich die TicketID stehen.
Wenn ich die TicketID eines schon exsistierenen Tickets manuell setze, dann kann ich diesem Ticket einen neuerstellten Artikel zuordnen und bekomme bei der s3Answer auch die entsprechende ArtikelID.
Kann mir da jemand behilflich sein?
leon
Znuny newbie
Posts: 7
Joined: 30 Oct 2012, 09:12
Znuny Version: 3.1.5

Re: OTRS-RPC (SOAP) über .Net c# [Solved]

Post by leon »

Okay mein Problem hat sich gelöst. Die Parameter wurden falsch übergeben.
Mich würde das mit dem Attachment allerdings auch noch interessieren. Hat sich das schon mal wer angeguckt und kann da weiterhelfen?
Ich hoffe mal, dass hier überhaupt noch wer reinguckt :D
leon
Znuny newbie
Posts: 7
Joined: 30 Oct 2012, 09:12
Znuny Version: 3.1.5

Re: OTRS-RPC (SOAP) über .Net c# [Solved]

Post by leon »

So meine Probleme sind alle weg und das hier nur zur Ergänzung.
Ein Bild (hier: PNG-Datei) als Attachment:

Code: Select all

#region SERVICE_ATTACHMENT
private const int SERVICE_ARTICLEWRITEATTACHMENT = 5;
            /// <summary>
            /// Mit diesem soap-Aufruf wird einem spezifischem Artikel ein Anhang zugefügt (hier Bildschirmfoto)
            /// {0}: soap_username : z.B.: TestSoapUser
            /// {1}: soap_password : z.B.: TestPasswort
            /// {2}: content : z.B.: Ein Bildschirmfoto als string (unten erklärt)
            /// {3}: content type : z.B.: "image/png"
            /// {4}: filename : z.B.: "Screenshot.png"
            /// {5}: articleID : z.B.: "XXXX" Die entsprechende Artikelnummer
            /// {6}: userID : z.B.: "1" (1 ist root)
            /// </summary>
            private static String SOAP_ARTICLEWRITEATTACHMENT = @"<?xml version=""1.0"" encoding=""utf-8""?>
      <soap:Envelope xmlns:xsi=""http://www.w3.org/2001/XMLSchema-instance"" xmlns:soapenc=""http://schemas.xmlsoap.org/soap/encoding/"" xmlns:xsd=""http://www.w3.org/2001/XMLSchema"" soap:encodingStyle=""http://schemas.xmlsoap.org/soap/encoding/"" xmlns:soap=""http://schemas.xmlsoap.org/soap/envelope/"">
          <soap:Body>
              <Dispatch xmlns=""/Core"">
                  <c-gensym142 xsi:type=""xsd:string"">{0}</c-gensym142>
                  <c-gensym144 xsi:type=""xsd:string"">{1}</c-gensym144>

                  <c-gensym146 xsi:type=""xsd:string"">TicketObject</c-gensym146>
                  <c-gensym148 xsi:type=""xsd:string"">ArticleWriteAttachment</c-gensym148>

                  <c-gensym150 xsi:type=""xsd:string"">Content</c-gensym150>
                  <c-gensym152 xsi:type=""soapenc:base64"">{2}</c-gensym152>

                  <c-gensym154 xsi:type=""xsd:string"">ContentType</c-gensym154>
                  <c-gensym156 xsi:type=""xsd:string"">{3}</c-gensym156>

                  <c-gensym158 xsi:type=""xsd:string"">Filename</c-gensym158>
                  <c-gensym160 xsi:type=""xsd:string"">{4}</c-gensym160>

                  <c-gensym162 xsi:type=""xsd:string"">ArticleID</c-gensym162>
                  <c-gensym164 xsi:type=""xsd:string"">{5}</c-gensym164>

                  <c-gensym166 xsi:type=""xsd:string"">UserID</c-gensym166>
                  <c-gensym168 xsi:type=""xsd:string"">{6}</c-gensym168>
              </Dispatch>
          </soap:Body>
      </soap:Envelope>";
    #endregion
Da Content ein string sein muss:

Code: Select all

string screenShot = System.Convert.ToBase64String(System.IO.File.ReadAllBytes("C:\\xxx"));
Und dann screenShot für {2} setzen.
;)
Und natürlich muss bei getSoapXml(...) ein weiterer case hinzugrfüht werden:

Code: Select all

case SERVICE_ARTICLEWRITEATTACHMENT:
                    {
                        String soapenv = String.Format(SOAP_ARTICLEWRITEATTACHMENT,
                            data[0].ToString()
                            , data[1].ToString()
                            , data[2].ToString()
                            , data[3].ToString()
                            , data[4].ToString()
                            , data[5].ToString()
                            , data[6].ToString()
                            );
                        retVal.LoadXml(soapenv);
                        return retVal;
                    }
johnleee
Znuny newbie
Posts: 1
Joined: 06 Dec 2012, 12:05
Znuny Version: 20095

Re: OTRS-RPC (SOAP) über .Net c# [Solved]

Post by johnleee »

In the SysConfig (Framework -> Core::Log) you can see whether your OTRS uses SysLog or a File based log. If a file is used in the same subgroup of the SysConfig you can find the location of that file.
pitter
Post Reply