private async Task SafeLog(DateTime requestTime,
                                   long responseMillis,
                                   int statusCode,
                                   string method,
                                   string path,
                                   string queryString,
                                   string requestBody,
                                   string responseBody,
                                   string ipAddress,
                                   ApplicationUser user)
        {
            // Do not log these events login, logout, getuserinfo...
            if ((path.ToLower().StartsWith("/api/account/")) ||
                (path.ToLower().StartsWith("/api/UserProfile/")))
            {
                return;
            }

            if (requestBody.Length > 256)
            {
                requestBody = $"(Truncated to 200 chars) {requestBody.Substring(0, 200)}";
            }

            // If the response body was an ApiResponse we should just save the Result object
            if (responseBody.Contains("\"result\":"))
            {
                try
                {
                    ApiResponse apiResponse = JsonConvert.DeserializeObject <ApiResponse>(responseBody);
                    responseBody = Regex.Replace(apiResponse.Result.ToString(), @"(""[^""\\]*(?:\\.[^""\\]*)*"")|\s+", "$1");
                }
                catch { }
            }

            if (responseBody.Length > 256)
            {
                responseBody = $"(Truncated to 200 chars) {responseBody.Substring(0, 200)}";
            }

            if (queryString.Length > 256)
            {
                queryString = $"(Truncated to 200 chars) {queryString.Substring(0, 200)}";
            }

            await _apiLogService.Log(new ApiLogItem
            {
                RequestTime       = requestTime,
                ResponseMillis    = responseMillis,
                StatusCode        = statusCode,
                Method            = method,
                Path              = path,
                QueryString       = queryString,
                RequestBody       = requestBody,
                ResponseBody      = responseBody ?? String.Empty,
                IPAddress         = ipAddress,
                ApplicationUserId = user == null ? Guid.Empty : user.Id
            });
        }
        public async Task InvokeAsync(HttpContext httpContext)
        {
            try
            {
                var request = httpContext.Request;
                if (IsSwagger(httpContext) || request.Path.StartsWithSegments(new PathString("/test")))
                {
                    await _next(httpContext);
                }
                else
                {
                    Stopwatch stopWatch   = Stopwatch.StartNew();
                    var       requestTime = DateTime.UtcNow;

                    var formattedRequest = await FormatRequest(request);

                    var originalBodyStream = httpContext.Response.Body;

                    using (var responseBody = new MemoryStream())
                    {
                        httpContext.Response.Body = responseBody;

                        try
                        {
                            var response = httpContext.Response;
                            response.Body = responseBody;
                            await _next.Invoke(httpContext);

                            string responseBodyContent = null;

                            if (httpContext.Response.StatusCode == (int)HttpStatusCode.OK)
                            {
                                responseBodyContent = await FormatResponse(response);
                                await HandleSuccessRequestAsync(httpContext, responseBodyContent, httpContext.Response.StatusCode);
                            }
                            else
                            {
                                await HandleNotSuccessRequestAsync(httpContext, httpContext.Response.StatusCode);
                            }

                            stopWatch.Stop();

                            #region Log Request / Response
                            if (_enableAPILogging)
                            {
                                try
                                {
                                    await responseBody.CopyToAsync(originalBodyStream);

                                    await _apiLogService.Log(new ApiLogItem
                                    {
                                        RequestTime    = requestTime,
                                        ResponseMillis = stopWatch.ElapsedMilliseconds,
                                        StatusCode     = response.StatusCode,
                                        Method         = request.Method,
                                        Path           = request.Path,
                                        QueryString    = request.QueryString.ToString(),
                                        RequestBody    = formattedRequest,
                                        ResponseBody   = responseBodyContent,
                                        IPAddress      = httpContext.Connection.RemoteIpAddress.ToString()
                                    });
                                }
                                catch (Exception ex)
                                {
                                    _logger.LogWarning("An Inner Middleware exception occurred on SafeLog: " + ex.Message);
                                }
                            }
                            #endregion
                        }
                        catch (System.Exception ex)
                        {
                            _logger.LogWarning("An Inner Middleware exception occurred: " + ex.Message);
                            await HandleExceptionAsync(httpContext, ex);
                        }
                        finally
                        {
                            responseBody.Seek(0, SeekOrigin.Begin);
                            await responseBody.CopyToAsync(originalBodyStream);
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                // We can't do anything if the response has already started, just abort.
                if (httpContext.Response.HasStarted)
                {
                    _logger.LogWarning("A Middleware exception occurred, but response has already started!");
                    throw;
                }

                await HandleExceptionAsync(httpContext, ex);

                throw;
            }
        }
        private async Task SafeLog(DateTime requestTime,
                                   long responseMillis,
                                   int statusCode,
                                   string method,
                                   string path,
                                   string queryString,
                                   string requestBody,
                                   string responseBody,
                                   string ipAddress,
                                   ApplicationUser user)
        {
            // Do not log these events login, logout, getuserinfo...

            if ((path.ToLower().StartsWith("/api/account/")) ||
                (path.ToLower().StartsWith("/api/UserProfile/")) ||
                (method.ToLower() == "get" && path.Count(c => c == '/') == 2)                 // Do not log 'GET all' events like: /api/todo
                )
            {
                return;
            }

            //Uncomment if truncation is needed
            //if (requestBody.Length > 256)
            //{
            //    requestBody = $"(Truncated to 200 chars) {requestBody.Substring(0, 200)}";
            //}

            // If the response body was an ApiResponse we should just save the Result object
            if (responseBody.Contains("\"result\":"))
            {
                try
                {
                    ApiResponse apiResponse = JsonConvert.DeserializeObject <ApiResponse>(responseBody);
                    responseBody = Regex.Replace(apiResponse.Result.ToString(), @"(""[^""\\]*(?:\\.[^""\\]*)*"")|\s+", "$1");
                }
                catch { }
            }

            //Uncomment if truncation is needed
            //if (responseBody.Length > 256)
            //{
            //    responseBody = $"(Truncated to 200 chars) {responseBody.Substring(0, 200)}";
            //}

            if (queryString.Length > 256)
            {
                queryString = $"(Truncated to 200 chars) {queryString.Substring(0, 200)}";
            }

            if (method.ToUpper() == "PUT")
            {
                JObject item = JObject.Parse(requestBody.Substring(requestBody.IndexOf('{')));
                var     resp = await _apiLogService.GetLastGet(path + "/" + item["id"].Value <string>(), user.Id);

                if (resp != null && resp.StatusCode == 200)
                {
                    //ApiLogItem oldItem = JsonConvert.DeserializeObject<ApiLogItem>(resp.Result.ToString());
                    responseBody = "[" + responseBody + "," + resp.ResponseBody + "]";
                }
            }
            await _apiLogService.Log(new ApiLogItem
            {
                RequestTime       = requestTime,
                ResponseMillis    = responseMillis,
                StatusCode        = statusCode,
                Method            = method,
                Path              = path,
                QueryString       = queryString,
                RequestBody       = requestBody,
                ResponseBody      = responseBody ?? String.Empty,
                IPAddress         = ipAddress,
                ApplicationUserId = user == null ? Guid.Empty : user.Id
            });
        }