configureApp) : base(factory)
+ {
+ _configureApp = configureApp;
+ }
+
+ public override void Configure(IApplicationBuilder app) => _configureApp(app);
+ }
+}
\ No newline at end of file
diff --git a/src/Hosting/Hosting/src/Startup/ExceptionPage/Views/ErrorPage.Designer.cs b/src/Hosting/Hosting/src/Startup/ExceptionPage/Views/ErrorPage.Designer.cs
new file mode 100644
index 0000000000..52a6db45d3
--- /dev/null
+++ b/src/Hosting/Hosting/src/Startup/ExceptionPage/Views/ErrorPage.Designer.cs
@@ -0,0 +1,1055 @@
+namespace Microsoft.AspNetCore.Hosting.Views
+{
+#line 1 "ErrorPage.cshtml"
+using System
+
+#line default
+#line hidden
+ ;
+#line 2 "ErrorPage.cshtml"
+using System.Globalization
+
+#line default
+#line hidden
+ ;
+#line 3 "ErrorPage.cshtml"
+using System.Linq
+
+#line default
+#line hidden
+ ;
+#line 4 "ErrorPage.cshtml"
+using System.Net
+
+#line default
+#line hidden
+ ;
+#line 5 "ErrorPage.cshtml"
+using System.Reflection
+
+#line default
+#line hidden
+ ;
+#line 6 "ErrorPage.cshtml"
+using Microsoft.AspNetCore.Hosting.Views
+
+#line default
+#line hidden
+ ;
+ using System.Threading.Tasks;
+
+ internal class ErrorPage : Microsoft.Extensions.RazorViews.BaseView
+ {
+#line 9 "ErrorPage.cshtml"
+
+ public ErrorPage(ErrorPageModel model)
+ {
+ Model = model;
+ }
+
+ public ErrorPageModel Model { get; set; }
+
+#line default
+#line hidden
+ #line hidden
+ public ErrorPage()
+ {
+ }
+
+ #pragma warning disable 1998
+ public override async Task ExecuteAsync()
+ {
+ WriteLiteral("\r\n");
+#line 17 "ErrorPage.cshtml"
+
+ Response.ContentType = "text/html; charset=utf-8";
+ var location = string.Empty;
+
+#line default
+#line hidden
+
+ WriteLiteral("\r\n\r\n \r\n \r\n ");
+#line 25 "ErrorPage.cshtml"
+ Write(Resources.ErrorPageHtml_Title);
+
+#line default
+#line hidden
+ WriteLiteral(@"
+
+
+
+ ");
+#line 226 "ErrorPage.cshtml"
+ Write(Resources.ErrorPageHtml_UnhandledException);
+
+#line default
+#line hidden
+ WriteLiteral("
\r\n");
+#line 227 "ErrorPage.cshtml"
+
+
+#line default
+#line hidden
+
+#line 227 "ErrorPage.cshtml"
+ foreach (var errorDetail in Model.ErrorDetails)
+ {
+
+#line default
+#line hidden
+
+ WriteLiteral(" ");
+#line 229 "ErrorPage.cshtml"
+ Write(errorDetail.Error.GetType().Name);
+
+#line default
+#line hidden
+ WriteLiteral(": ");
+#line 229 "ErrorPage.cshtml"
+ Output.Write(HtmlEncodeAndReplaceLineBreaks(errorDetail.Error.Message));
+
+#line default
+#line hidden
+
+ WriteLiteral("
\r\n");
+#line 230 "ErrorPage.cshtml"
+
+
+#line default
+#line hidden
+
+#line 230 "ErrorPage.cshtml"
+
+ var firstFrame = errorDetail.StackFrames.FirstOrDefault();
+ if (firstFrame != null)
+ {
+ location = firstFrame.Function;
+ }
+
+
+#line default
+#line hidden
+
+#line 236 "ErrorPage.cshtml"
+
+ if (!string.IsNullOrEmpty(location) && firstFrame != null && !string.IsNullOrEmpty(firstFrame.File))
+ {
+
+#line default
+#line hidden
+
+ WriteLiteral(" ");
+#line 239 "ErrorPage.cshtml"
+ Write(location);
+
+#line default
+#line hidden
+ WriteLiteral(" in ");
+#line 239 "ErrorPage.cshtml"
+ Write(System.IO.Path.GetFileName(firstFrame.File));
+
+#line default
+#line hidden
+ WriteLiteral(", line ");
+#line 239 "ErrorPage.cshtml"
+ Write(firstFrame.Line);
+
+#line default
+#line hidden
+ WriteLiteral("
\r\n");
+#line 240 "ErrorPage.cshtml"
+ }
+ else if (!string.IsNullOrEmpty(location))
+ {
+
+#line default
+#line hidden
+
+ WriteLiteral(" ");
+#line 243 "ErrorPage.cshtml"
+ Write(location);
+
+#line default
+#line hidden
+ WriteLiteral("
\r\n");
+#line 244 "ErrorPage.cshtml"
+ }
+ else
+ {
+
+#line default
+#line hidden
+
+ WriteLiteral(" ");
+#line 247 "ErrorPage.cshtml"
+ Write(Resources.ErrorPageHtml_UnknownLocation);
+
+#line default
+#line hidden
+ WriteLiteral("
\r\n");
+#line 248 "ErrorPage.cshtml"
+ }
+
+ var reflectionTypeLoadException = errorDetail.Error as ReflectionTypeLoadException;
+ if (reflectionTypeLoadException != null)
+ {
+ if (reflectionTypeLoadException.LoaderExceptions.Length > 0)
+ {
+
+#line default
+#line hidden
+
+ WriteLiteral(" Loader Exceptions:
\r\n \r\n");
+#line 257 "ErrorPage.cshtml"
+
+
+#line default
+#line hidden
+
+#line 257 "ErrorPage.cshtml"
+ foreach (var ex in reflectionTypeLoadException.LoaderExceptions)
+ {
+
+#line default
+#line hidden
+
+ WriteLiteral(" - ");
+#line 259 "ErrorPage.cshtml"
+ Write(ex.Message);
+
+#line default
+#line hidden
+ WriteLiteral("
\r\n");
+#line 260 "ErrorPage.cshtml"
+ }
+
+#line default
+#line hidden
+
+ WriteLiteral("
\r\n");
+#line 262 "ErrorPage.cshtml"
+ }
+ }
+ }
+
+#line default
+#line hidden
+
+ WriteLiteral(" \r\n
\r\n");
+#line 267 "ErrorPage.cshtml"
+
+
+#line default
+#line hidden
+
+#line 267 "ErrorPage.cshtml"
+
+ var exceptionCount = 0;
+ var stackFrameCount = 0;
+ var exceptionDetailId = "";
+ var frameId = "";
+
+
+#line default
+#line hidden
+
+ WriteLiteral(" ");
+#line 273 "ErrorPage.cshtml"
+ foreach (var errorDetail in Model.ErrorDetails)
+ {
+
+
+#line default
+#line hidden
+
+#line 275 "ErrorPage.cshtml"
+
+ exceptionCount++;
+ exceptionDetailId = "exceptionDetail" + exceptionCount;
+
+
+#line default
+#line hidden
+
+#line 278 "ErrorPage.cshtml"
+
+
+#line default
+#line hidden
+
+ WriteLiteral(" - \r\n
");
+#line 280 "ErrorPage.cshtml"
+ Write(errorDetail.Error.GetType().Name);
+
+#line default
+#line hidden
+ WriteLiteral(": ");
+#line 280 "ErrorPage.cshtml"
+ Write(errorDetail.Error.Message);
+
+#line default
+#line hidden
+ WriteLiteral("
\r\n \r\n");
+#line 282 "ErrorPage.cshtml"
+
+
+#line default
+#line hidden
+
+#line 282 "ErrorPage.cshtml"
+ foreach (var frame in errorDetail.StackFrames)
+ {
+
+
+#line default
+#line hidden
+
+#line 284 "ErrorPage.cshtml"
+
+ stackFrameCount++;
+ frameId = "frame" + stackFrameCount;
+
+
+#line default
+#line hidden
+
+#line 287 "ErrorPage.cshtml"
+
+
+#line default
+#line hidden
+
+ WriteLiteral(" - \r\n");
+#line 289 "ErrorPage.cshtml"
+
+
+#line default
+#line hidden
+
+#line 289 "ErrorPage.cshtml"
+ if (string.IsNullOrEmpty(frame.File))
+ {
+
+#line default
+#line hidden
+
+ WriteLiteral("
");
+#line 291 "ErrorPage.cshtml"
+ Write(frame.Function);
+
+#line default
+#line hidden
+ WriteLiteral("
\r\n");
+#line 292 "ErrorPage.cshtml"
+ }
+ else
+ {
+
+#line default
+#line hidden
+
+ WriteLiteral(" ");
+#line 295 "ErrorPage.cshtml"
+ Write(frame.Function);
+
+#line default
+#line hidden
+ WriteLiteral(" in ");
+#line 295 "ErrorPage.cshtml"
+ Write(System.IO.Path.GetFileName(frame.File));
+
+#line default
+#line hidden
+ WriteLiteral("
\r\n");
+#line 296 "ErrorPage.cshtml"
+ }
+
+#line default
+#line hidden
+
+ WriteLiteral("\r\n");
+#line 298 "ErrorPage.cshtml"
+
+
+#line default
+#line hidden
+
+#line 298 "ErrorPage.cshtml"
+ if (frame.Line != 0 && frame.ContextCode.Any())
+ {
+
+#line default
+#line hidden
+
+ WriteLiteral(" \r\n \r\n");
+#line 302 "ErrorPage.cshtml"
+
+
+#line default
+#line hidden
+
+#line 302 "ErrorPage.cshtml"
+ if (frame.PreContextCode.Any())
+ {
+
+#line default
+#line hidden
+
+ WriteLiteral("
\r\n");
+#line 305 "ErrorPage.cshtml"
+
+
+#line default
+#line hidden
+
+#line 305 "ErrorPage.cshtml"
+ foreach (var line in frame.PreContextCode)
+ {
+
+#line default
+#line hidden
+
+ WriteLiteral(" - ");
+#line 307 "ErrorPage.cshtml"
+ Write(line);
+
+#line default
+#line hidden
+ WriteLiteral("
\r\n");
+#line 308 "ErrorPage.cshtml"
+ }
+
+#line default
+#line hidden
+
+ WriteLiteral("
\r\n");
+#line 310 "ErrorPage.cshtml"
+ }
+
+#line default
+#line hidden
+
+ WriteLiteral("\r\n
\r\n");
+#line 313 "ErrorPage.cshtml"
+
+
+#line default
+#line hidden
+
+#line 313 "ErrorPage.cshtml"
+ foreach (var line in frame.ContextCode)
+ {
+
+#line default
+#line hidden
+
+ WriteLiteral(" - ");
+#line 315 "ErrorPage.cshtml"
+ Write(line);
+
+#line default
+#line hidden
+ WriteLiteral("
\r\n");
+#line 316 "ErrorPage.cshtml"
+ }
+
+#line default
+#line hidden
+
+ WriteLiteral("
\r\n\r\n");
+#line 319 "ErrorPage.cshtml"
+
+
+#line default
+#line hidden
+
+#line 319 "ErrorPage.cshtml"
+ if (frame.PostContextCode.Any())
+ {
+
+#line default
+#line hidden
+
+ WriteLiteral("
\r\n");
+#line 322 "ErrorPage.cshtml"
+
+
+#line default
+#line hidden
+
+#line 322 "ErrorPage.cshtml"
+ foreach (var line in frame.PostContextCode)
+ {
+
+#line default
+#line hidden
+
+ WriteLiteral(" - ");
+#line 324 "ErrorPage.cshtml"
+ Write(line);
+
+#line default
+#line hidden
+ WriteLiteral("
\r\n");
+#line 325 "ErrorPage.cshtml"
+ }
+
+#line default
+#line hidden
+
+ WriteLiteral("
\r\n");
+#line 327 "ErrorPage.cshtml"
+ }
+
+#line default
+#line hidden
+
+ WriteLiteral("
\r\n");
+#line 329 "ErrorPage.cshtml"
+ }
+
+#line default
+#line hidden
+
+ WriteLiteral(" \r\n");
+#line 331 "ErrorPage.cshtml"
+ }
+
+#line default
+#line hidden
+
+ WriteLiteral(@"
+
+ -
+
+
+
+ \r\n
\r\n
\r\n
");
+#line 341 "ErrorPage.cshtml"
+ Write(errorDetail.Error.ToString());
+
+#line default
+#line hidden
+ WriteLiteral("\r\n
\r\n
\r\n \r\n");
+#line 345 "ErrorPage.cshtml"
+ }
+
+#line default
+#line hidden
+
+ WriteLiteral("
\r\n
\r\n
+
+
+
+");
+ }
+ #pragma warning restore 1998
+ }
+}
diff --git a/src/Hosting/Hosting/src/Startup/ExceptionPage/Views/ErrorPage.cshtml b/src/Hosting/Hosting/src/Startup/ExceptionPage/Views/ErrorPage.cshtml
new file mode 100644
index 0000000000..8f8360c565
--- /dev/null
+++ b/src/Hosting/Hosting/src/Startup/ExceptionPage/Views/ErrorPage.cshtml
@@ -0,0 +1,162 @@
+@using System
+@using System.Globalization
+@using System.Linq
+@using System.Net
+@using System.Reflection
+@using Microsoft.AspNetCore.Hosting.Views
+
+@functions
+{
+ public ErrorPage(ErrorPageModel model)
+ {
+ Model = model;
+ }
+
+ public ErrorPageModel Model { get; set; }
+}
+@{
+ Response.ContentType = "text/html; charset=utf-8";
+ var location = string.Empty;
+}
+
+
+
+
+ @Resources.ErrorPageHtml_Title
+
+
+
+ @Resources.ErrorPageHtml_UnhandledException
+ @foreach (var errorDetail in Model.ErrorDetails)
+ {
+ @errorDetail.Error.GetType().Name: @{ Output.Write(HtmlEncodeAndReplaceLineBreaks(errorDetail.Error.Message)); }
+ @{
+ var firstFrame = errorDetail.StackFrames.FirstOrDefault();
+ if (firstFrame != null)
+ {
+ location = firstFrame.Function;
+ }
+ }
+ if (!string.IsNullOrEmpty(location) && firstFrame != null && !string.IsNullOrEmpty(firstFrame.File))
+ {
+ @location in @System.IO.Path.GetFileName(firstFrame.File), line @firstFrame.Line
+ }
+ else if (!string.IsNullOrEmpty(location))
+ {
+ @location
+ }
+ else
+ {
+ @Resources.ErrorPageHtml_UnknownLocation
+ }
+
+ var reflectionTypeLoadException = errorDetail.Error as ReflectionTypeLoadException;
+ if (reflectionTypeLoadException != null)
+ {
+ if (reflectionTypeLoadException.LoaderExceptions.Length > 0)
+ {
+ Loader Exceptions:
+
+ @foreach (var ex in reflectionTypeLoadException.LoaderExceptions)
+ {
+ - @ex.Message
+ }
+
+ }
+ }
+ }
+
+
+ @{
+ var exceptionCount = 0;
+ var stackFrameCount = 0;
+ var exceptionDetailId = "";
+ var frameId = "";
+ }
+ @foreach (var errorDetail in Model.ErrorDetails)
+ {
+ @{
+ exceptionCount++;
+ exceptionDetailId = "exceptionDetail" + exceptionCount;
+ }
+ -
+
@errorDetail.Error.GetType().Name: @errorDetail.Error.Message
+
+ @foreach (var frame in errorDetail.StackFrames)
+ {
+ @{
+ stackFrameCount++;
+ frameId = "frame" + stackFrameCount;
+ }
+ -
+ @if (string.IsNullOrEmpty(frame.File))
+ {
+
@frame.Function
+ }
+ else
+ {
+ @frame.Function in @System.IO.Path.GetFileName(frame.File)
+ }
+
+ @if (frame.Line != 0 && frame.ContextCode.Any())
+ {
+
+
+ @if (frame.PreContextCode.Any())
+ {
+
+ @foreach (var line in frame.PreContextCode)
+ {
+ - @line
+ }
+
+ }
+
+
+ @foreach (var line in frame.ContextCode)
+ {
+ - @line
+ }
+
+
+ @if (frame.PostContextCode.Any())
+ {
+
+ @foreach (var line in frame.PostContextCode)
+ {
+ - @line
+ }
+
+ }
+
+ }
+
+ }
+
+
+ -
+
+
+
+
+
+
+
@errorDetail.Error.ToString()
+
+
+
+ }
+
+
+
+
+
+
diff --git a/src/Hosting/Hosting/src/Startup/ExceptionPage/Views/ErrorPage.css b/src/Hosting/Hosting/src/Startup/ExceptionPage/Views/ErrorPage.css
new file mode 100644
index 0000000000..4d3287c12d
--- /dev/null
+++ b/src/Hosting/Hosting/src/Startup/ExceptionPage/Views/ErrorPage.css
@@ -0,0 +1,195 @@
+body {
+ font-family: 'Segoe UI', Tahoma, Arial, Helvetica, sans-serif;
+ font-size: .813em;
+ color: #222;
+}
+
+h1, h2, h3, h4, h5 {
+ /*font-family: 'Segoe UI',Tahoma,Arial,Helvetica,sans-serif;*/
+ font-weight: 100;
+}
+
+h1 {
+ color: #44525e;
+ margin: 15px 0 15px 0;
+}
+
+h2 {
+ margin: 10px 5px 0 0;
+}
+
+h3 {
+ color: #363636;
+ margin: 5px 5px 0 0;
+}
+
+code {
+ font-family: Consolas, "Courier New", courier, monospace;
+}
+
+body .titleerror {
+ padding: 3px 3px 6px 3px;
+ display: block;
+ font-size: 1.5em;
+ font-weight: 100;
+}
+
+body .location {
+ margin: 3px 0 10px 30px;
+}
+
+#header {
+ font-size: 18px;
+ padding: 15px 0;
+ border-top: 1px #ddd solid;
+ border-bottom: 1px #ddd solid;
+ margin-bottom: 0;
+}
+
+ #header li {
+ display: inline;
+ margin: 5px;
+ padding: 5px;
+ color: #a0a0a0;
+ cursor: pointer;
+ }
+
+ #header .selected {
+ background: #44c5f2;
+ color: #fff;
+ }
+
+#stackpage ul {
+ list-style: none;
+ padding-left: 0;
+ margin: 0;
+ /*border-bottom: 1px #ddd solid;*/
+}
+
+#stackpage .details {
+ font-size: 1.2em;
+ padding: 3px;
+ color: #000;
+}
+
+#stackpage .stackerror {
+ padding: 5px;
+ border-bottom: 1px #ddd solid;
+}
+
+
+#stackpage .frame {
+ padding: 0;
+ margin: 0 0 0 30px;
+}
+
+ #stackpage .frame h3 {
+ padding: 2px;
+ margin: 0;
+ }
+
+#stackpage .source {
+ padding: 0 0 0 30px;
+}
+
+ #stackpage .source ol li {
+ font-family: Consolas, "Courier New", courier, monospace;
+ white-space: pre;
+ background-color: #fbfbfb;
+ }
+
+#stackpage .frame .source .highlight li span {
+ color: #FF0000;
+}
+
+#stackpage .source ol.collapsible li {
+ color: #888;
+}
+
+ #stackpage .source ol.collapsible li span {
+ color: #606060;
+ }
+
+.page table {
+ border-collapse: separate;
+ border-spacing: 0;
+ margin: 0 0 20px;
+}
+
+.page th {
+ vertical-align: bottom;
+ padding: 10px 5px 5px 5px;
+ font-weight: 400;
+ color: #a0a0a0;
+ text-align: left;
+}
+
+.page td {
+ padding: 3px 10px;
+}
+
+.page th, .page td {
+ border-right: 1px #ddd solid;
+ border-bottom: 1px #ddd solid;
+ border-left: 1px transparent solid;
+ border-top: 1px transparent solid;
+ box-sizing: border-box;
+}
+
+ .page th:last-child, .page td:last-child {
+ border-right: 1px transparent solid;
+ }
+
+.page .length {
+ text-align: right;
+}
+
+a {
+ color: #1ba1e2;
+ text-decoration: none;
+}
+
+ a:hover {
+ color: #13709e;
+ text-decoration: underline;
+ }
+
+.showRawException {
+ cursor: pointer;
+ color: #44c5f2;
+ background-color: transparent;
+ font-size: 1.2em;
+ text-align: left;
+ text-decoration: none;
+ display: inline-block;
+ border: 0;
+ padding: 0;
+}
+
+.rawExceptionStackTrace {
+ font-size: 1.2em;
+}
+
+.rawExceptionBlock {
+ border-top: 1px #ddd solid;
+ border-bottom: 1px #ddd solid;
+}
+
+.showRawExceptionContainer {
+ margin-top: 10px;
+ margin-bottom: 10px;
+}
+
+.expandCollapseButton {
+ cursor: pointer;
+ float: left;
+ height: 16px;
+ width: 16px;
+ font-size: 10px;
+ position: absolute;
+ left: 10px;
+ background-color: #eee;
+ padding: 0;
+ border: 0;
+ margin: 0;
+}
diff --git a/src/Hosting/Hosting/src/Startup/ExceptionPage/Views/ErrorPage.js b/src/Hosting/Hosting/src/Startup/ExceptionPage/Views/ErrorPage.js
new file mode 100644
index 0000000000..3925cfd2f2
--- /dev/null
+++ b/src/Hosting/Hosting/src/Startup/ExceptionPage/Views/ErrorPage.js
@@ -0,0 +1,192 @@
+(function (window, undefined) {
+ "use strict";
+
+ function ns(selector, element) {
+ return new NodeCollection(selector, element);
+ }
+
+ function NodeCollection(selector, element) {
+ this.items = [];
+ element = element || window.document;
+
+ var nodeList;
+
+ if (typeof (selector) === "string") {
+ nodeList = element.querySelectorAll(selector);
+ for (var i = 0, l = nodeList.length; i < l; i++) {
+ this.items.push(nodeList.item(i));
+ }
+ }
+ }
+
+ NodeCollection.prototype = {
+ each: function (callback) {
+ for (var i = 0, l = this.items.length; i < l; i++) {
+ callback(this.items[i], i);
+ }
+ return this;
+ },
+
+ children: function (selector) {
+ var children = [];
+
+ this.each(function (el) {
+ children = children.concat(ns(selector, el).items);
+ });
+
+ return ns(children);
+ },
+
+ hide: function () {
+ this.each(function (el) {
+ el.style.display = "none";
+ });
+
+ return this;
+ },
+
+ toggle: function () {
+ this.each(function (el) {
+ el.style.display = el.style.display === "none" ? "" : "none";
+ });
+
+ return this;
+ },
+
+ show: function () {
+ this.each(function (el) {
+ el.style.display = "";
+ });
+
+ return this;
+ },
+
+ addClass: function (className) {
+ this.each(function (el) {
+ var existingClassName = el.className,
+ classNames;
+ if (!existingClassName) {
+ el.className = className;
+ } else {
+ classNames = existingClassName.split(" ");
+ if (classNames.indexOf(className) < 0) {
+ el.className = existingClassName + " " + className;
+ }
+ }
+ });
+
+ return this;
+ },
+
+ removeClass: function (className) {
+ this.each(function (el) {
+ var existingClassName = el.className,
+ classNames, index;
+ if (existingClassName === className) {
+ el.className = "";
+ } else if (existingClassName) {
+ classNames = existingClassName.split(" ");
+ index = classNames.indexOf(className);
+ if (index > 0) {
+ classNames.splice(index, 1);
+ el.className = classNames.join(" ");
+ }
+ }
+ });
+
+ return this;
+ },
+
+ attr: function (name) {
+ if (this.items.length === 0) {
+ return null;
+ }
+
+ return this.items[0].getAttribute(name);
+ },
+
+ on: function (eventName, handler) {
+ this.each(function (el, idx) {
+ var callback = function (e) {
+ e = e || window.event;
+ if (!e.which && e.keyCode) {
+ e.which = e.keyCode; // Normalize IE8 key events
+ }
+ handler.apply(el, [e]);
+ };
+
+ if (el.addEventListener) { // DOM Events
+ el.addEventListener(eventName, callback, false);
+ } else if (el.attachEvent) { // IE8 events
+ el.attachEvent("on" + eventName, callback);
+ } else {
+ el["on" + type] = callback;
+ }
+ });
+
+ return this;
+ },
+
+ click: function (handler) {
+ return this.on("click", handler);
+ },
+
+ keypress: function (handler) {
+ return this.on("keypress", handler);
+ }
+ };
+
+ function frame(el) {
+ ns(".source .collapsible", el).toggle();
+ }
+
+ function expandCollapseButton(el) {
+ var frameId = el.getAttribute("data-frameId");
+ frame(document.getElementById(frameId));
+ if (el.innerText === "+") {
+ el.innerText = "-";
+ }
+ else {
+ el.innerText = "+";
+ }
+ }
+
+ function tab(el) {
+ var unselected = ns("#header .selected").removeClass("selected").attr("id");
+ var selected = ns("#" + el.id).addClass("selected").attr("id");
+
+ ns("#" + unselected + "page").hide();
+ ns("#" + selected + "page").show();
+ }
+
+ ns(".rawExceptionDetails").hide();
+ ns(".collapsible").hide();
+ ns(".page").hide();
+ ns("#stackpage").show();
+
+ ns(".expandCollapseButton")
+ .click(function () {
+ expandCollapseButton(this);
+ })
+ .keypress(function (e) {
+ if (e.which === 13) {
+ expandCollapseButton(this);
+ }
+ });
+
+ ns("#header li")
+ .click(function () {
+ tab(this);
+ })
+ .keypress(function (e) {
+ if (e.which === 13) {
+ tab(this);
+ }
+ });
+
+ ns(".showRawException")
+ .click(function () {
+ var exceptionDetailId = this.getAttribute("data-exceptionDetailId");
+ ns("#" + exceptionDetailId).toggle();
+ });
+})(window);
\ No newline at end of file
diff --git a/src/Hosting/Hosting/src/Startup/ExceptionPage/Views/ErrorPageModel.cs b/src/Hosting/Hosting/src/Startup/ExceptionPage/Views/ErrorPageModel.cs
new file mode 100644
index 0000000000..b0a9f0354a
--- /dev/null
+++ b/src/Hosting/Hosting/src/Startup/ExceptionPage/Views/ErrorPageModel.cs
@@ -0,0 +1,29 @@
+// Copyright (c) .NET Foundation. All rights reserved.
+// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
+
+using System.Collections.Generic;
+using Microsoft.Extensions.StackTrace.Sources;
+
+namespace Microsoft.AspNetCore.Hosting.Views
+{
+ ///
+ /// Holds data to be displayed on the error page.
+ ///
+ internal class ErrorPageModel
+ {
+ ///
+ /// Detailed information about each exception in the stack.
+ ///
+ public IEnumerable ErrorDetails { get; set; }
+
+ public string RuntimeDisplayName { get; set; }
+
+ public string RuntimeArchitecture { get; set; }
+
+ public string ClrVersion { get; set; }
+
+ public string CurrentAssemblyVesion { get; set; }
+
+ public string OperatingSystemDescription { get; set; }
+ }
+}
diff --git a/src/Hosting/Hosting/src/Startup/StartupBase.cs b/src/Hosting/Hosting/src/Startup/StartupBase.cs
new file mode 100644
index 0000000000..5a180ba9b4
--- /dev/null
+++ b/src/Hosting/Hosting/src/Startup/StartupBase.cs
@@ -0,0 +1,50 @@
+// Copyright (c) .NET Foundation. All rights reserved.
+// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
+
+using System;
+using Microsoft.AspNetCore.Builder;
+using Microsoft.Extensions.DependencyInjection;
+
+namespace Microsoft.AspNetCore.Hosting
+{
+ public abstract class StartupBase : IStartup
+ {
+ public abstract void Configure(IApplicationBuilder app);
+
+ IServiceProvider IStartup.ConfigureServices(IServiceCollection services)
+ {
+ ConfigureServices(services);
+ return CreateServiceProvider(services);
+ }
+
+ public virtual void ConfigureServices(IServiceCollection services)
+ {
+ }
+
+ public virtual IServiceProvider CreateServiceProvider(IServiceCollection services)
+ {
+ return services.BuildServiceProvider();
+ }
+ }
+
+ public abstract class StartupBase : StartupBase
+ {
+ private readonly IServiceProviderFactory _factory;
+
+ public StartupBase(IServiceProviderFactory factory)
+ {
+ _factory = factory;
+ }
+
+ public override IServiceProvider CreateServiceProvider(IServiceCollection services)
+ {
+ var builder = _factory.CreateBuilder(services);
+ ConfigureContainer(builder);
+ return _factory.CreateServiceProvider(builder);
+ }
+
+ public virtual void ConfigureContainer(TBuilder builder)
+ {
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Hosting/Hosting/src/WebHostBuilder.cs b/src/Hosting/Hosting/src/WebHostBuilder.cs
new file mode 100644
index 0000000000..2238bd3b9b
--- /dev/null
+++ b/src/Hosting/Hosting/src/WebHostBuilder.cs
@@ -0,0 +1,365 @@
+// Copyright (c) .NET Foundation. All rights reserved.
+// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
+
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.IO;
+using System.Linq;
+using System.Reflection;
+using System.Runtime.ExceptionServices;
+using Microsoft.AspNetCore.Hosting.Builder;
+using Microsoft.AspNetCore.Hosting.Internal;
+using Microsoft.AspNetCore.Http;
+using Microsoft.Extensions.Configuration;
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.DependencyInjection.Extensions;
+using Microsoft.Extensions.Logging;
+using Microsoft.Extensions.ObjectPool;
+
+namespace Microsoft.AspNetCore.Hosting
+{
+ ///
+ /// A builder for
+ ///
+ public class WebHostBuilder : IWebHostBuilder
+ {
+ private readonly HostingEnvironment _hostingEnvironment;
+ private readonly List> _configureServicesDelegates;
+
+ private IConfiguration _config;
+ private WebHostOptions _options;
+ private WebHostBuilderContext _context;
+ private bool _webHostBuilt;
+ private List> _configureAppConfigurationBuilderDelegates;
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ public WebHostBuilder()
+ {
+ _hostingEnvironment = new HostingEnvironment();
+ _configureServicesDelegates = new List>();
+ _configureAppConfigurationBuilderDelegates = new List>();
+
+ _config = new ConfigurationBuilder()
+ .AddEnvironmentVariables(prefix: "ASPNETCORE_")
+ .Build();
+
+ if (string.IsNullOrEmpty(GetSetting(WebHostDefaults.EnvironmentKey)))
+ {
+ // Try adding legacy environment keys, never remove these.
+ UseSetting(WebHostDefaults.EnvironmentKey, Environment.GetEnvironmentVariable("Hosting:Environment")
+ ?? Environment.GetEnvironmentVariable("ASPNET_ENV"));
+ }
+
+ if (string.IsNullOrEmpty(GetSetting(WebHostDefaults.ServerUrlsKey)))
+ {
+ // Try adding legacy url key, never remove this.
+ UseSetting(WebHostDefaults.ServerUrlsKey, Environment.GetEnvironmentVariable("ASPNETCORE_SERVER.URLS"));
+ }
+
+ _context = new WebHostBuilderContext
+ {
+ Configuration = _config
+ };
+ }
+
+ ///
+ /// Get the setting value from the configuration.
+ ///
+ /// The key of the setting to look up.
+ /// The value the setting currently contains.
+ public string GetSetting(string key)
+ {
+ return _config[key];
+ }
+
+ ///
+ /// Add or replace a setting in the configuration.
+ ///
+ /// The key of the setting to add or replace.
+ /// The value of the setting to add or replace.
+ /// The .
+ public IWebHostBuilder UseSetting(string key, string value)
+ {
+ _config[key] = value;
+ return this;
+ }
+
+ ///
+ /// Adds a delegate for configuring additional services for the host or web application. This may be called
+ /// multiple times.
+ ///
+ /// A delegate for configuring the .
+ /// The .
+ public IWebHostBuilder ConfigureServices(Action configureServices)
+ {
+ if (configureServices == null)
+ {
+ throw new ArgumentNullException(nameof(configureServices));
+ }
+
+ return ConfigureServices((_, services) => configureServices(services));
+ }
+
+ ///
+ /// Adds a delegate for configuring additional services for the host or web application. This may be called
+ /// multiple times.
+ ///
+ /// A delegate for configuring the .
+ /// The .
+ public IWebHostBuilder ConfigureServices(Action configureServices)
+ {
+ if (configureServices == null)
+ {
+ throw new ArgumentNullException(nameof(configureServices));
+ }
+
+ _configureServicesDelegates.Add(configureServices);
+ return this;
+ }
+
+ ///
+ /// Adds a delegate for configuring the that will construct an .
+ ///
+ /// The delegate for configuring the that will be used to construct an .
+ /// The .
+ ///
+ /// The and on the are uninitialized at this stage.
+ /// The is pre-populated with the settings of the .
+ ///
+ public IWebHostBuilder ConfigureAppConfiguration(Action configureDelegate)
+ {
+ if (configureDelegate == null)
+ {
+ throw new ArgumentNullException(nameof(configureDelegate));
+ }
+
+ _configureAppConfigurationBuilderDelegates.Add(configureDelegate);
+ return this;
+ }
+
+ ///
+ /// Builds the required services and an which hosts a web application.
+ ///
+ public IWebHost Build()
+ {
+ if (_webHostBuilt)
+ {
+ throw new InvalidOperationException(Resources.WebHostBuilder_SingleInstance);
+ }
+ _webHostBuilt = true;
+
+ var hostingServices = BuildCommonServices(out var hostingStartupErrors);
+ var applicationServices = hostingServices.Clone();
+ var hostingServiceProvider = GetProviderFromFactory(hostingServices);
+
+ if (!_options.SuppressStatusMessages)
+ {
+ // Warn about deprecated environment variables
+ if (Environment.GetEnvironmentVariable("Hosting:Environment") != null)
+ {
+ Console.WriteLine("The environment variable 'Hosting:Environment' is obsolete and has been replaced with 'ASPNETCORE_ENVIRONMENT'");
+ }
+
+ if (Environment.GetEnvironmentVariable("ASPNET_ENV") != null)
+ {
+ Console.WriteLine("The environment variable 'ASPNET_ENV' is obsolete and has been replaced with 'ASPNETCORE_ENVIRONMENT'");
+ }
+
+ if (Environment.GetEnvironmentVariable("ASPNETCORE_SERVER.URLS") != null)
+ {
+ Console.WriteLine("The environment variable 'ASPNETCORE_SERVER.URLS' is obsolete and has been replaced with 'ASPNETCORE_URLS'");
+ }
+ }
+
+ AddApplicationServices(applicationServices, hostingServiceProvider);
+
+ var host = new WebHost(
+ applicationServices,
+ hostingServiceProvider,
+ _options,
+ _config,
+ hostingStartupErrors);
+ try
+ {
+ host.Initialize();
+
+ var logger = host.Services.GetRequiredService>();
+
+ // Warn about duplicate HostingStartupAssemblies
+ foreach (var assemblyName in _options.GetFinalHostingStartupAssemblies().GroupBy(a => a, StringComparer.OrdinalIgnoreCase).Where(g => g.Count() > 1))
+ {
+ logger.LogWarning($"The assembly {assemblyName} was specified multiple times. Hosting startup assemblies should only be specified once.");
+ }
+
+ return host;
+ }
+ catch
+ {
+ // Dispose the host if there's a failure to initialize, this should clean up
+ // will dispose services that were constructed until the exception was thrown
+ host.Dispose();
+ throw;
+ }
+
+ IServiceProvider GetProviderFromFactory(IServiceCollection collection)
+ {
+ var provider = collection.BuildServiceProvider();
+ var factory = provider.GetService>();
+
+ if (factory != null && !(factory is DefaultServiceProviderFactory))
+ {
+ using (provider)
+ {
+ return factory.CreateServiceProvider(factory.CreateBuilder(collection));
+ }
+ }
+
+ return provider;
+ }
+ }
+
+ private IServiceCollection BuildCommonServices(out AggregateException hostingStartupErrors)
+ {
+ hostingStartupErrors = null;
+
+ _options = new WebHostOptions(_config, Assembly.GetEntryAssembly()?.GetName().Name);
+
+ if (!_options.PreventHostingStartup)
+ {
+ var exceptions = new List();
+
+ // Execute the hosting startup assemblies
+ foreach (var assemblyName in _options.GetFinalHostingStartupAssemblies().Distinct(StringComparer.OrdinalIgnoreCase))
+ {
+ try
+ {
+ var assembly = Assembly.Load(new AssemblyName(assemblyName));
+
+ foreach (var attribute in assembly.GetCustomAttributes())
+ {
+ var hostingStartup = (IHostingStartup)Activator.CreateInstance(attribute.HostingStartupType);
+ hostingStartup.Configure(this);
+ }
+ }
+ catch (Exception ex)
+ {
+ // Capture any errors that happen during startup
+ exceptions.Add(new InvalidOperationException($"Startup assembly {assemblyName} failed to execute. See the inner exception for more details.", ex));
+ }
+ }
+
+ if (exceptions.Count > 0)
+ {
+ hostingStartupErrors = new AggregateException(exceptions);
+ }
+ }
+
+ var contentRootPath = ResolveContentRootPath(_options.ContentRootPath, AppContext.BaseDirectory);
+
+ // Initialize the hosting environment
+ _hostingEnvironment.Initialize(contentRootPath, _options);
+ _context.HostingEnvironment = _hostingEnvironment;
+
+ var services = new ServiceCollection();
+ services.AddSingleton(_options);
+ services.AddSingleton(_hostingEnvironment);
+ services.AddSingleton(_hostingEnvironment);
+ services.AddSingleton(_context);
+
+ var builder = new ConfigurationBuilder()
+ .SetBasePath(_hostingEnvironment.ContentRootPath)
+ .AddConfiguration(_config);
+
+ foreach (var configureAppConfiguration in _configureAppConfigurationBuilderDelegates)
+ {
+ configureAppConfiguration(_context, builder);
+ }
+
+ var configuration = builder.Build();
+ services.AddSingleton(configuration);
+ _context.Configuration = configuration;
+
+ var listener = new DiagnosticListener("Microsoft.AspNetCore");
+ services.AddSingleton(listener);
+ services.AddSingleton(listener);
+
+ services.AddTransient();
+ services.AddTransient();
+ services.AddScoped();
+ services.AddOptions();
+ services.AddLogging();
+
+ // Conjure up a RequestServices
+ services.AddTransient();
+ services.AddTransient, DefaultServiceProviderFactory>();
+
+ // Ensure object pooling is available everywhere.
+ services.AddSingleton();
+
+ if (!string.IsNullOrEmpty(_options.StartupAssembly))
+ {
+ try
+ {
+ var startupType = StartupLoader.FindStartupType(_options.StartupAssembly, _hostingEnvironment.EnvironmentName);
+
+ if (typeof(IStartup).GetTypeInfo().IsAssignableFrom(startupType.GetTypeInfo()))
+ {
+ services.AddSingleton(typeof(IStartup), startupType);
+ }
+ else
+ {
+ services.AddSingleton(typeof(IStartup), sp =>
+ {
+ var hostingEnvironment = sp.GetRequiredService();
+ var methods = StartupLoader.LoadMethods(sp, startupType, hostingEnvironment.EnvironmentName);
+ return new ConventionBasedStartup(methods);
+ });
+ }
+ }
+ catch (Exception ex)
+ {
+ var capture = ExceptionDispatchInfo.Capture(ex);
+ services.AddSingleton(_ =>
+ {
+ capture.Throw();
+ return null;
+ });
+ }
+ }
+
+ foreach (var configureServices in _configureServicesDelegates)
+ {
+ configureServices(_context, services);
+ }
+
+ return services;
+ }
+
+ private void AddApplicationServices(IServiceCollection services, IServiceProvider hostingServiceProvider)
+ {
+ // We are forwarding services from hosting container so hosting container
+ // can still manage their lifetime (disposal) shared instances with application services.
+ // NOTE: This code overrides original services lifetime. Instances would always be singleton in
+ // application container.
+ var listener = hostingServiceProvider.GetService();
+ services.Replace(ServiceDescriptor.Singleton(typeof(DiagnosticListener), listener));
+ services.Replace(ServiceDescriptor.Singleton(typeof(DiagnosticSource), listener));
+ }
+
+ private string ResolveContentRootPath(string contentRootPath, string basePath)
+ {
+ if (string.IsNullOrEmpty(contentRootPath))
+ {
+ return basePath;
+ }
+ if (Path.IsPathRooted(contentRootPath))
+ {
+ return contentRootPath;
+ }
+ return Path.Combine(Path.GetFullPath(basePath), contentRootPath);
+ }
+ }
+}
diff --git a/src/Hosting/Hosting/src/WebHostBuilderExtensions.cs b/src/Hosting/Hosting/src/WebHostBuilderExtensions.cs
new file mode 100644
index 0000000000..09c7e6d96b
--- /dev/null
+++ b/src/Hosting/Hosting/src/WebHostBuilderExtensions.cs
@@ -0,0 +1,148 @@
+// Copyright (c) .NET Foundation. All rights reserved.
+// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
+
+using System;
+using System.Reflection;
+using Microsoft.AspNetCore.Builder;
+using Microsoft.AspNetCore.Hosting.Internal;
+using Microsoft.Extensions.Configuration;
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.DependencyInjection.Extensions;
+using Microsoft.Extensions.Logging;
+
+namespace Microsoft.AspNetCore.Hosting
+{
+ public static class WebHostBuilderExtensions
+ {
+ ///
+ /// Specify the startup method to be used to configure the web application.
+ ///
+ /// The to configure.
+ /// The delegate that configures the .
+ /// The .
+ public static IWebHostBuilder Configure(this IWebHostBuilder hostBuilder, Action configureApp)
+ {
+ if (configureApp == null)
+ {
+ throw new ArgumentNullException(nameof(configureApp));
+ }
+
+ var startupAssemblyName = configureApp.GetMethodInfo().DeclaringType.GetTypeInfo().Assembly.GetName().Name;
+
+ return hostBuilder
+ .UseSetting(WebHostDefaults.ApplicationKey, startupAssemblyName)
+ .ConfigureServices(services =>
+ {
+ services.AddSingleton(sp =>
+ {
+ return new DelegateStartup(sp.GetRequiredService>(), configureApp);
+ });
+ });
+ }
+
+
+ ///
+ /// Specify the startup type to be used by the web host.
+ ///
+ /// The to configure.
+ /// The to be used.
+ /// The .
+ public static IWebHostBuilder UseStartup(this IWebHostBuilder hostBuilder, Type startupType)
+ {
+ var startupAssemblyName = startupType.GetTypeInfo().Assembly.GetName().Name;
+
+ return hostBuilder
+ .UseSetting(WebHostDefaults.ApplicationKey, startupAssemblyName)
+ .ConfigureServices(services =>
+ {
+ if (typeof(IStartup).GetTypeInfo().IsAssignableFrom(startupType.GetTypeInfo()))
+ {
+ services.AddSingleton(typeof(IStartup), startupType);
+ }
+ else
+ {
+ services.AddSingleton(typeof(IStartup), sp =>
+ {
+ var hostingEnvironment = sp.GetRequiredService();
+ return new ConventionBasedStartup(StartupLoader.LoadMethods(sp, startupType, hostingEnvironment.EnvironmentName));
+ });
+ }
+ });
+ }
+
+ ///
+ /// Specify the startup type to be used by the web host.
+ ///
+ /// The to configure.
+ /// The type containing the startup methods for the application.
+ /// The .
+ public static IWebHostBuilder UseStartup(this IWebHostBuilder hostBuilder) where TStartup : class
+ {
+ return hostBuilder.UseStartup(typeof(TStartup));
+ }
+
+ ///
+ /// Configures the default service provider
+ ///
+ /// The to configure.
+ /// A callback used to configure the for the default .
+ /// The .
+ public static IWebHostBuilder UseDefaultServiceProvider(this IWebHostBuilder hostBuilder, Action configure)
+ {
+ return hostBuilder.UseDefaultServiceProvider((context, options) => configure(options));
+ }
+
+ ///
+ /// Configures the default service provider
+ ///
+ /// The to configure.
+ /// A callback used to configure the for the default .
+ /// The .
+ public static IWebHostBuilder UseDefaultServiceProvider(this IWebHostBuilder hostBuilder, Action configure)
+ {
+ return hostBuilder.ConfigureServices((context, services) =>
+ {
+ var options = new ServiceProviderOptions();
+ configure(context, options);
+ services.Replace(ServiceDescriptor.Singleton>(new DefaultServiceProviderFactory(options)));
+ });
+ }
+
+ ///
+ /// Adds a delegate for configuring the that will construct an .
+ ///
+ /// The to configure.
+ /// The delegate for configuring the that will be used to construct an .
+ /// The .
+ ///
+ /// The and on the are uninitialized at this stage.
+ /// The is pre-populated with the settings of the .
+ ///
+ public static IWebHostBuilder ConfigureAppConfiguration(this IWebHostBuilder hostBuilder, Action configureDelegate)
+ {
+ return hostBuilder.ConfigureAppConfiguration((context, builder) => configureDelegate(builder));
+ }
+
+ ///
+ /// Adds a delegate for configuring the provided . This may be called multiple times.
+ ///
+ /// The to configure.
+ /// The delegate that configures the .
+ /// The .
+ public static IWebHostBuilder ConfigureLogging(this IWebHostBuilder hostBuilder, Action configureLogging)
+ {
+ return hostBuilder.ConfigureServices(collection => collection.AddLogging(configureLogging));
+ }
+
+ ///
+ /// Adds a delegate for configuring the provided . This may be called multiple times.
+ ///
+ /// The to configure.
+ /// The delegate that configures the .
+ /// The .
+ public static IWebHostBuilder ConfigureLogging(this IWebHostBuilder hostBuilder, Action configureLogging)
+ {
+ return hostBuilder.ConfigureServices((context, collection) => collection.AddLogging(builder => configureLogging(context, builder)));
+ }
+ }
+}
diff --git a/src/Hosting/Hosting/src/WebHostExtensions.cs b/src/Hosting/Hosting/src/WebHostExtensions.cs
new file mode 100644
index 0000000000..e73399c419
--- /dev/null
+++ b/src/Hosting/Hosting/src/WebHostExtensions.cs
@@ -0,0 +1,187 @@
+// Copyright (c) .NET Foundation. All rights reserved.
+// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
+
+using System;
+using System.Threading;
+using System.Threading.Tasks;
+using Microsoft.AspNetCore.Hosting.Server.Features;
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.AspNetCore.Hosting.Internal;
+
+namespace Microsoft.AspNetCore.Hosting
+{
+ public static class WebHostExtensions
+ {
+ ///
+ /// Attempts to gracefully stop the host with the given timeout.
+ ///
+ ///
+ /// The timeout for stopping gracefully. Once expired the
+ /// server may terminate any remaining active connections.
+ ///
+ public static Task StopAsync(this IWebHost host, TimeSpan timeout)
+ {
+ return host.StopAsync(new CancellationTokenSource(timeout).Token);
+ }
+
+ ///
+ /// Block the calling thread until shutdown is triggered via Ctrl+C or SIGTERM.
+ ///
+ /// The running .
+ public static void WaitForShutdown(this IWebHost host)
+ {
+ host.WaitForShutdownAsync().GetAwaiter().GetResult();
+ }
+
+ ///
+ /// Returns a Task that completes when shutdown is triggered via the given token, Ctrl+C or SIGTERM.
+ ///
+ /// The running .
+ /// The token to trigger shutdown.
+ public static async Task WaitForShutdownAsync(this IWebHost host, CancellationToken token = default)
+ {
+ var done = new ManualResetEventSlim(false);
+ using (var cts = CancellationTokenSource.CreateLinkedTokenSource(token))
+ {
+ AttachCtrlcSigtermShutdown(cts, done, shutdownMessage: string.Empty);
+
+ try
+ {
+ await host.WaitForTokenShutdownAsync(cts.Token);
+ }
+ finally
+ {
+ done.Set();
+ }
+ }
+ }
+
+ ///
+ /// Runs a web application and block the calling thread until host shutdown.
+ ///
+ /// The to run.
+ public static void Run(this IWebHost host)
+ {
+ host.RunAsync().GetAwaiter().GetResult();
+ }
+
+ ///
+ /// Runs a web application and returns a Task that only completes when the token is triggered or shutdown is triggered.
+ ///
+ /// The to run.
+ /// The token to trigger shutdown.
+ public static async Task RunAsync(this IWebHost host, CancellationToken token = default)
+ {
+ // Wait for token shutdown if it can be canceled
+ if (token.CanBeCanceled)
+ {
+ await host.RunAsync(token, shutdownMessage: null);
+ return;
+ }
+
+ // If token cannot be canceled, attach Ctrl+C and SIGTERM shutdown
+ var done = new ManualResetEventSlim(false);
+ using (var cts = new CancellationTokenSource())
+ {
+ var shutdownMessage = host.Services.GetRequiredService().SuppressStatusMessages ? string.Empty : "Application is shutting down...";
+ AttachCtrlcSigtermShutdown(cts, done, shutdownMessage: shutdownMessage);
+
+ try
+ {
+ await host.RunAsync(cts.Token, "Application started. Press Ctrl+C to shut down.");
+ }
+ finally
+ {
+ done.Set();
+ }
+ }
+ }
+
+ private static async Task RunAsync(this IWebHost host, CancellationToken token, string shutdownMessage)
+ {
+ using (host)
+ {
+ await host.StartAsync(token);
+
+ var hostingEnvironment = host.Services.GetService();
+ var options = host.Services.GetRequiredService();
+
+ if (!options.SuppressStatusMessages)
+ {
+ Console.WriteLine($"Hosting environment: {hostingEnvironment.EnvironmentName}");
+ Console.WriteLine($"Content root path: {hostingEnvironment.ContentRootPath}");
+
+
+ var serverAddresses = host.ServerFeatures.Get()?.Addresses;
+ if (serverAddresses != null)
+ {
+ foreach (var address in serverAddresses)
+ {
+ Console.WriteLine($"Now listening on: {address}");
+ }
+ }
+
+ if (!string.IsNullOrEmpty(shutdownMessage))
+ {
+ Console.WriteLine(shutdownMessage);
+ }
+ }
+
+ await host.WaitForTokenShutdownAsync(token);
+ }
+ }
+
+ private static void AttachCtrlcSigtermShutdown(CancellationTokenSource cts, ManualResetEventSlim resetEvent, string shutdownMessage)
+ {
+ void Shutdown()
+ {
+ if (!cts.IsCancellationRequested)
+ {
+ if (!string.IsNullOrEmpty(shutdownMessage))
+ {
+ Console.WriteLine(shutdownMessage);
+ }
+ try
+ {
+ cts.Cancel();
+ }
+ catch (ObjectDisposedException) { }
+ }
+
+ // Wait on the given reset event
+ resetEvent.Wait();
+ };
+
+ AppDomain.CurrentDomain.ProcessExit += (sender, eventArgs) => Shutdown();
+ Console.CancelKeyPress += (sender, eventArgs) =>
+ {
+ Shutdown();
+ // Don't terminate the process immediately, wait for the Main thread to exit gracefully.
+ eventArgs.Cancel = true;
+ };
+ }
+
+ private static async Task WaitForTokenShutdownAsync(this IWebHost host, CancellationToken token)
+ {
+ var applicationLifetime = host.Services.GetService();
+
+ token.Register(state =>
+ {
+ ((IApplicationLifetime)state).StopApplication();
+ },
+ applicationLifetime);
+
+ var waitForStop = new TaskCompletionSource