public static async Task <T> CipheriseRequest <T>(this string strRequestURI, HttpStatusCode eExpectedStatus, string strPostJSON, string strSessionID = null, UpdateOut <T> UpdateCB = null) where T : CipheriseError, new()
        {
            try
            {
                T OutData = default(T);  //Lambas cant capture the out/ref Data,  use a temp instead.
                ProcessJSONDelegate JSONDelegate = (HttpStatusCode eStatus, Stream stream) =>
                {
                    if (eExpectedStatus != eStatus)
                    {
                        String.Format("Invalid HTTP status code: '{0}'.  Expecting: '{1}'", eStatus.ToString(), eExpectedStatus.ToString()).TraceWarning();

                        bool           bRet = false;
                        CipheriseError E    = FromJSON <CipheriseError>(stream);
                        if ((E != null) && E.HasError())
                        {
                            E.GetError().TraceError("Cipherise JSON Error: ");

                            OutData = new T();
                            if (UpdateCB != null)
                            {
                                UpdateCB(ref OutData);
                            }
                            OutData.SetError(ref E);
                            bRet = true; //Caller must check T.HasError()
                        }
#if DEBUG
                        {
                            if (stream.CanSeek)
                            {
                                stream.Seek(0, SeekOrigin.Begin);
                            }
                            using (StreamReader streamReader = new StreamReader(stream))
                            {
                                string responseFromServer = streamReader.ReadToEnd();
                                responseFromServer.TraceError("Invalid response: ");
                                streamReader.Close();
                            }
                        }
#endif
                        return(bRet);
                    }

                    //bool bEmptyResponse2 = (OutData is EmptyResponse);
                    bool bEmptyResponse = (typeof(EmptyResponse).IsAssignableFrom(typeof(T)));
                    if (bEmptyResponse)
                    {
                        OutData = new T();  //return an empty response instead of NULL
                        if (UpdateCB != null)
                        {
                            UpdateCB(ref OutData);
                        }
                    }
                    else
                    {
#if DEBUG
                        {
                            byte[] aData = null;
                            using (MemoryStream ms = new MemoryStream())
                            {
                                stream.CopyTo(ms);
                                aData = ms.ToArray();
                                ms.Seek(0, SeekOrigin.Begin);

                                StreamReader reader = new StreamReader(ms);
                                reader.ReadToEnd().TraceVerbose("RESPONSE:  ");
                            }
                            stream = new MemoryStream(aData);
                        }
#endif  //DEBUG

                        bool bValid = false;
                        OutData = FromJSON <T>(stream);
                        if (OutData != null)
                        {
                            if (UpdateCB != null)
                            {
                                UpdateCB(ref OutData);
                            }

                            bValid = OutData.Validate();
                        }

                        if (bValid == false)
                        {
                            String.Format("Invalid data: '{0}'", typeof(T)).TraceError();
                            return(false);
                        }
                    }
                    return(true);
                };

                bool bRequest = await ForticodeRequest(strRequestURI, JSONDelegate, strPostJSON, strSessionID);

                if (bRequest)
                {
                    return(OutData);
                }
            }
            catch (Exception e) { e.CatchMessage().TraceError(); }
            return(null);
        }
        /// <exception cref="Exception"></exception>
        private static async Task <bool> ForticodeRequest(string strRequestURI, ProcessJSONDelegate ProcessJSON, string strPostJSON = null, string strSessionID = null)
        {
            HttpWebResponse response = null;

            try
            {
                strRequestURI.TraceVerbose("CONNECTING: ");
                HttpWebRequest request = (HttpWebRequest)WebRequest.Create(new System.Uri(strRequestURI, UriKind.Absolute));

                request.ContentType = "application/json";
                request.Method      = "GET";
                request.Accept      = "*/*";

                if (string.IsNullOrEmpty(strSessionID) == false)
                {
                    request.Headers.Add("sessionId", strSessionID);
                }

                if (strPostJSON != null)
                {
                    request.Method = "POST";
                    if (strPostJSON != "")
                    {
                        using (StreamWriter streamWriter = new StreamWriter(request.GetRequestStream()))
                        {
#if DEBUG
                            strPostJSON.TraceVerbose("SEND: ");
#endif  //DEBUG
                            streamWriter.Write(strPostJSON);
                        }
                    }
                }

                response = await request.GetResponseAsync() as HttpWebResponse;
            }
            catch (System.Net.WebException e)
            {
                if (e.Response is HttpWebResponse)
                {
                    response = (e.Response as HttpWebResponse);
                }

                else if (e.InnerException is System.Net.Sockets.SocketException)
                {
                    e.InnerException.Message.TraceWarning();
                }

                else if (!string.IsNullOrEmpty(e.Message))
                {
                    e.Message.TraceWarning();

                    System.Exception I = e;
                    while (I.InnerException != null)
                    {
                        if (!string.IsNullOrEmpty(I.InnerException.Message))
                        {
                            I.InnerException.Message.TraceWarning();
                        }

                        I = I.InnerException;
                    }
                }
                //else
                //    throw e;
            }

            bool bRet = false;
            if (response != null)
            {
                using (response)
                {
                    HttpStatusCode eStatus = response.StatusCode;
                    using (Stream stream = response.GetResponseStream())
                    {
                        bRet = ProcessJSON(eStatus, stream);
                    }
                }
            }
            return(bRet);
        }