/// <summary>
        /// Analyse the package code for a single consignment. Calculate totals for the consignment based on that.
        /// Prepare for iterating the xml package elements one by one.
        /// </summary>
        /// <param name="PackageCode"></param>
        /// <param name="OutsideEU"></param>
        /// <param name="InvoiceValue"></param>
        public void MakePackages(string PackageCode, bool OutsideEU, double InvoiceValue, MyXMLDocument mydoc)
        {
            //start fresh
            PackageMultiples  = new Dictionary <string, PackageMultiple>();
            this.OutsideEU    = OutsideEU;
            this.InvoiceValue = InvoiceValue;
            this.mydoc        = mydoc;
            this.TotalItems   = 0;
            this.TotalWeight  = 0;
            this.TotalVolume  = 0;

            //analyse package code
            string[] symbols = PackageCode.Split('+');
            foreach (string s in symbols)
            {
                PackageDimensionsStore.PackageDimensions pak;
                if (!PackageDimensionsDict.TryGetValue(s, out pak))
                {
                    throw new InvalidOperationException("TNTPackageAnalyser: symbol " + s + ", as occuring in " + PackageCode + ", not found in Package Dimensions Dictionary.");
                }
                if (!PackageMultiples.ContainsKey(s))
                {
                    PackageMultiples.Add(s, new PackageMultiple(s, 1, pak));
                }
                else
                {
                    PackageMultiples[s].AddOne();
                }
                TotalItems++;
                TotalWeight += pak.weight;
                TotalVolume += pak.volume;
            }
            ItemInvoiceValue = InvoiceValue / TotalItems;
        }
        /// <summary>
        /// Navigate to a new position, relative to the navigation position of 'this' document.
        /// Returns new MyXMLDocument, it has no effects on the original one.
        /// </summary>
        /// <param name="xpath">relative XPath expression identifying a single node: the new navigation position</param>
        /// <returns>A partial clone of this doc, focussed on the new navigation position</returns>
        public MyXMLDocument Navigate(XPathExpression xpath)
        {
            MyXMLDocument doc2 = PartialClone();

            doc2.nav = nav.SelectSingleNode(xpath);
            return(doc2);
        }
        /// <summary>
        /// Lookup a Consignment by Id and make it current: ready for further reading.
        /// This one has a weaker assumption: either CREATE or SHIP must be there to have Consignments
        /// </summary>
        /// <param name="Id">Either a ConRef or a ConNumber, depending on the type of Id chosen, see constructor</param>
        /// <returns>success?</returns>
        public bool FindConsignmentById(string Id)
        {
            if (!hasCreate && !hasShip)
            {
                throw new InvalidOperationException("TNTResult: no CREATE and no SHIP element, therefore no consignment info.");
            }
            bool OK = true;

            if (hasCreate)
            {
                curCreate = createIndex.GetChildByIndexValue(Id);
                OK        = OK && (curCreate != null);
            }
            if (hasBook)
            {
                curBook = bookIndex.GetChildByIndexValue(Id);
                OK      = OK && (curBook != null);
            }
            if (hasShip)
            {
                curShip = shipIndex.GetChildByIndexValue(Id);
                OK      = OK && (curShip != null);
            }
            return(OK);
        }
        /// <summary>
        /// Transform an xml-document to a HttpContent request message that accords to the TNT spec.
        /// It has to be application/x-www-form-urlencoded !
        /// It has to contain one key-value pair, "xml_in" being the key and the whole xml-string the value (urlencoded of course).
        /// The whole thing should be in UTF-8.
        /// </summary>
        /// <param name="xml">Xmldocument to send</param>
        private HttpContent BuildWWWFormUrlEncoded(MyXMLDocument xml)
        {
            Byte[] bytes;
            //First we get the xml to a stream... to make the XmlWriter believe it is boss of encoding (UTF-8)
            using (MemoryStream ms = new MemoryStream())
            {
                xml.ToStream(ms, new UTF8Encoding(false, true), indent: true);
                bytes = ms.ToArray();  //not exactly the streaming + async philosophy, but we have to do some strange stuff
            }
            //Then we get the stream into a bytes array to enable us to do URL-encoding
            Byte[] bytes2 = HttpUtility.UrlEncodeToBytes(bytes);
            //We create an un-encoded namevaluepair, with bytes2 als the value
            string prolog = "xml_in=";

            Byte[] bytes3 = Encoding.UTF8.GetBytes(prolog);
            //Concatenate: bytes3 + bytes2
            Byte[] bytes4 = new byte[bytes3.Length + bytes2.Length];
            Buffer.BlockCopy(bytes3, 0, bytes4, 0, bytes3.Length);
            Buffer.BlockCopy(bytes2, 0, bytes4, bytes3.Length, bytes2.Length);
            //...all of this because we had to do URLEncoding at an unusual time, after writing the xml
            HttpContent content = new ByteArrayContent(bytes4);

            content.Headers.ContentType = new MediaTypeHeaderValue("application/x-www-form-urlencoded");
            return(content);
        }
Exemplo n.º 5
0
 public TNTShipRequest(DateTime CollectionDate, RequestTypes requestType, TNTPackageAnalyser pa, bool Debug = false)
 {
     this.reqestType = requestType;
     this.pa         = pa;
     this.Debug      = Debug;
     this.xml        = new MyXMLDocument();
     dateformatinfo  = new DateTimeFormatInfo(); //neutral culture, it has / as date separator
     MakeFixedElements(CollectionDate);
 }
        /// <summary>
        /// Constructor
        /// </summary>
        /// <param name="doc">MyXMLDocument that has a navigator focussed on the node whose children we want to index</param>
        /// <param name="multiChildName">Name of a node that may occur multiple times under the given node</param>
        public MyXMLChildIndex(MyXMLDocument doc, string multiChildName, XPathExpression propertyXPath)
        {
            this.index = new Dictionary <string, MyXMLDocument>();
            var iter = new MyXMLChildEnumerable(doc, multiChildName);

            foreach (MyXMLDocument node in iter)
            {
                string key = node.nav.SelectSingleNode(propertyXPath).Value;
                index.Add(key, node);
            }
        }
        /// <summary>
        /// Checks for unpleasant HTTP status codes as well as other problems with the response.
        /// All errors found here are fatal: they break the chain of async processes.
        /// </summary>
        /// <param name="content">HttpContent for Posting to TNT</param>
        /// <param name="expectXml">Do we expect the response to be XML?</param>
        private async Task <PostResults> PostAsync(HttpContent content, bool expectXml)
        {
            HttpResponseMessage resp = null;

            try
            {
                resp = await client.PostAsync(new Uri(TARGET_URL), content);
            }
            catch (Exception e)
            {
                FirePostError(0, "PostAsync Exception: " + e.Message);
                throw e;  //just to stop the flow
            }
            if (!resp.IsSuccessStatusCode)
            {
                FirePostError(0, "HTTP error status " + resp.StatusCode + ": " + resp.ReasonPhrase);
                throw new InvalidOperationException("HTTP error status " + resp.StatusCode + ": " + resp.ReasonPhrase);
            }
            //xml checks
            if (expectXml)
            {
                MyXMLDocument xdoc = null;
                Stream        st   = await resp.Content.ReadAsStreamAsync();

                try
                {
                    TextReader rd      = new StreamReader(st, new UTF8Encoding(false, true));
                    XmlReader  XReader = XmlReader.Create(rd);
                    xdoc = new MyXMLDocument(XReader, readOnly: true);
                    if (
                        xdoc.NodeExists("/runtime_error") ||
                        xdoc.NodeExists("/parse_error")
                        )
                    {
                        string errormsg = xdoc.GetStringValue("//error_reason/text()");
                        FirePostError(0, "Errormessage sent by TNT: " + errormsg);
                        throw new InvalidOperationException("Errormessage sent by TNT: " + errormsg);
                    }
                }
                catch (Exception e)
                {
                    FirePostError(0, "Problem parsing xml " + e.Message);
                    throw e;
                }
                return(new PostResults(null, xdoc));
            }
            else
            {
                string c = await resp.Content.ReadAsStringAsync();

                return(new PostResults(c, null));
            }
        }
        //...other activities...

        /// <summary>
        /// Constructor
        /// </summary>
        /// <param name="doc">MyXMLDocument that contains the TNT Result, XML already parsed</param>
        /// <param name="indexBy">Shall we index the document by ConRef or by ConNumber?</param>
        public TNTResult(MyXMLDocument doc, IndexBy indexBy)
        {
            this.doc = doc;
            this.OK  = Initialize(indexBy);
        }
 /// <summary>
 /// Constructor
 /// </summary>
 /// <param name="reader">XmlReader that contains the TNT result</param>
 /// <param name="indexBy">Shall we index the document by ConRef or by ConNumber?</param>
 public TNTResult(XmlReader reader, IndexBy indexBy)
 {
     this.doc = new MyXMLDocument(reader, readOnly: true);
     this.OK  = Initialize(indexBy);
 }
 public PostResults(string Content, MyXMLDocument Xml)
 {
     this.Content = Content;
     this.Xml     = Xml;
 }