Example #1
0
        /// <summary>
        /// Gets a ClientTimings object from a <see cref="ResultRequest"/>.
        /// </summary>
        /// <param name="request">The request to convert.</param>
        /// <returns>A <see cref="ClientTimings"/> object.</returns>
        public static ClientTimings FromRequest(ResultRequest request)
        {
            var result = new ClientTimings()
            {
                RedirectCount = request.RedirectCount ?? 0,
                Timings       = new List <ClientTiming>(request.Performance?.Count + request.Probes?.Count ?? 0)
            };

            if (request.Performance?.Count > 0)
            {
                foreach (var t in request.Performance)
                {
                    if (t.Name?.EndsWith("End") == true)
                    {
                        continue;
                    }
                    result.Timings.Add(t);
                }
            }
            if (request.Probes?.Count > 0)
            {
                result.Timings.AddRange(request.Probes);
            }
            // Noise
            result.Timings.RemoveAll(t => t.Start < 0 || t.Duration < 0);
            // Sort for storage later
            result.Timings.Sort((a, b) => a.Start.CompareTo(b.Start));

            // TODO: Collapse client start/end timings? Probably...
            return(result);
        }
        /// <summary>
        /// Returns either JSON or full page HTML of a previous <c>MiniProfiler</c> session,
        /// identified by its <c>"?id=GUID"</c> on the query.
        /// </summary>
        /// <param name="context">The context to get a profiler response for.</param>
        private async Task <string> GetSingleProfilerResultAsync(HttpContext context)
        {
            Guid          id;
            ResultRequest clientRequest = null;
            // When we're rendering as a button/popup in the corner, it's an AJAX/JSON request.
            // If that's absent, we're rendering results as a full page for sharing.
            bool jsonRequest = context.Request.Headers["Accept"].FirstOrDefault()?.Contains("application/json") == true;

            // Try to parse from the JSON payload first
            if (jsonRequest &&
                context.Request.ContentLength > 0 &&
                ResultRequest.TryParse(context.Request.Body, out clientRequest) &&
                clientRequest.Id.HasValue)
            {
                id = clientRequest.Id.Value;
            }
            else if (Guid.TryParse(context.Request.Query["id"], out id))
            {
                // We got the guid from the querystring
            }
            else if (Options.StopwatchProvider != null)
            {
                // Fall back to the last result
                id = (await Options.Storage.ListAsync(1).ConfigureAwait(false)).FirstOrDefault();
            }

            if (id == default(Guid))
            {
                return(NotFound(context, jsonRequest ? null : "No GUID id specified on the query string"));
            }

            var profiler = await Options.Storage.LoadAsync(id).ConfigureAwait(false);

            string user = Options.UserIdProvider?.Invoke(context.Request);

            await Options.Storage.SetViewedAsync(user, id).ConfigureAwait(false);

            if (profiler == null)
            {
                return(NotFound(context, jsonRequest ? null : "No MiniProfiler results found with Id=" + id.ToString()));
            }

            bool needsSave = false;

            if (profiler.ClientTimings == null && clientRequest?.TimingCount > 0)
            {
                profiler.ClientTimings = ClientTimings.FromRequest(clientRequest);
                needsSave = true;
            }

            if (!profiler.HasUserViewed)
            {
                profiler.HasUserViewed = true;
                needsSave = true;
            }

            if (needsSave)
            {
                await Options.Storage.SaveAsync(profiler).ConfigureAwait(false);
            }

            if (!AuthorizeRequest(context, isList: false, message: out string authorizeMessage))
            {
                context.Response.ContentType = "application/json";
                return(@"""hidden"""); // JSON
            }

            if (jsonRequest)
            {
                context.Response.ContentType = "application/json";
                return(profiler.ToJson());
            }
            else
            {
                context.Response.ContentType = "text/html; charset=utf-8";
                return(Render.SingleResultHtml(profiler, context.Request.PathBase + Options.RouteBasePath.Value.EnsureTrailingSlash()));
            }
        }