/// <summary>
 /// Creates a new <see cref="WebPage"/> for rendering.
 /// </summary>
 /// <param name="error">The current error (null if not on an error-specific page).</param>
 /// <param name="settings">Current Exceptional settings.</param>
 /// <param name="store">The store to render.</param>
 /// <param name="baseURL">The base URL for the current request.</param>
 /// <param name="pageTitle">The title of the page.</param>
 protected WebPage(Error error, ExceptionalSettingsBase settings, ErrorStore store, string baseURL, string pageTitle)
 {
     Error       = error;
     Settings    = settings;
     Store       = store;
     BaseUrl     = baseURL.EndsWith("/") ? baseURL : baseURL + "/";
     PageTitle   = pageTitle;
     HeaderTitle = "Exceptions Log: " + settings.Store.ApplicationName.HtmlEncode();
 }
        /// <summary>
        /// Initializes a new instance of the <see cref="Error"/> class from a given <see cref="Exception"/> instance.
        /// </summary>
        /// <param name="e">The exception we intend to log.</param>
        /// <param name="settings">The settings this error is being logged with.</param>
        /// <param name="category">The category to associate with this exception.</param>
        /// <param name="applicationName">The application name to log as (used for overriding current settings).</param>
        /// <param name="rollupPerServer">Whether to log up per-server, e.g. errors are only duplicates if they have same stack on the same machine.</param>
        /// <param name="initialCustomData">The initial data dictionary to start with (generated by the user).</param>
        public Error(Exception e,
                     ExceptionalSettingsBase settings,
                     string category        = null,
                     string applicationName = null,
                     bool rollupPerServer   = false,
                     Dictionary <string, string> initialCustomData = null)
        {
            Exception = e ?? throw new ArgumentNullException(nameof(e));
            Settings  = settings;
            var baseException = e;

            // If it's not a .NET framework exception, usually more information is being added,
            // so use the wrapper for the message, type, etc.
            // If it's a .NET framework exception type, drill down and get the innermost exception.
            if (e.IsBCLException())
            {
                baseException = e.GetBaseException();
            }

            GUID            = Guid.NewGuid();
            ApplicationName = applicationName ?? settings.Store?.ApplicationName;
            Category        = category;
            MachineName     = Environment.MachineName;
            Type            = baseException.GetType().FullName;
            Message         = baseException.Message;
            Source          = baseException.Source;
            Detail          = e.ToString();
            CreationDate    = DateTime.UtcNow;
            DuplicateCount  = 1;
            CustomData      = initialCustomData;

            // Calculate the StackTrace if needed
            // TODO: Move this to generate Detail once instead of using .ToString()
            // Mirror CoreFX code for now, and then move to SourceLink supporting code after
            if (Settings.AppendFullStackTraces)
            {
                Detail += "\n\nFull Trace:\n\n" + new StackTrace(3, true);
            }

            ErrorHash = GetHash(rollupPerServer);

            var exCursor = e;

            while (exCursor != null)
            {
                AddData(exCursor);
                exCursor = exCursor.InnerException;
            }
            AddCustomData();
        }
 /// <summary>
 /// Creates an error listing page for rendering.
 /// </summary>
 /// <param name="store">The error store to use.</param>
 /// <param name="settings">Current Exceptional settings.</param>
 /// <param name="baseURL">The base URL for all links and items in the page.</param>
 /// <param name="errors">The list of errors to display on this page.</param>
 public ErrorListPage(ErrorStore store, ExceptionalSettingsBase settings, string baseURL, List <Error> errors)
     : base(null, settings, store, baseURL, "Error Log")
 {
     Errors = errors.OrderByDescending(e => e.LastLogDate ?? e.CreationDate).ToList();
 }
 /// <summary>
 /// Saves the given <paramref name="settings"/> as the global <see cref="Settings"/> available for use globally.
 /// These are intended to be used by global/background handlers where normal context access isn't available.
 /// </summary>
 /// <param name="settings">The settings object to set for background settings.</param>
 public static void Configure(ExceptionalSettingsBase settings) =>
 Settings = settings ?? throw new ArgumentNullException(nameof(settings));
 /// <summary>
 /// Creates an <see cref="ErrorDetailPage"/>.
 /// </summary>
 /// <param name="error">The error we're rendering details.</param>
 /// <param name="settings">Current Exceptional settings.</param>
 /// <param name="store">The store this error is from.</param>
 /// <param name="baseURL">The base URL for the current request.</param>
 /// <param name="guid">The id for the error (populate even if the error is null).</param>
 public ErrorDetailPage(Error error, ExceptionalSettingsBase settings, ErrorStore store, string baseURL, Guid guid)
     : base(error, settings, store, baseURL, "Error - " + (error?.Message ?? "Not Found"))
 {
     _guid = guid;
 }