{"id":744,"date":"2014-02-18T10:00:00","date_gmt":"2014-02-18T10:00:00","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/webdev\/2014\/02\/18\/introducing-asp-net-project-helios\/"},"modified":"2014-02-18T10:00:00","modified_gmt":"2014-02-18T10:00:00","slug":"introducing-asp-net-project-helios","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/dotnet\/introducing-asp-net-project-helios\/","title":{"rendered":"Introducing ASP.NET Project \u201cHelios\u201d"},"content":{"rendered":"<p>In late 2013 we made available a prerelease NuGet package which allows running a managed web application directly on top of IIS without going through the normal ASP.NET (System.Web) request processing pipeline. This was a relatively quiet event without too much fanfare. At last month\u2019s <a href=\"https:\/\/channel9.msdn.com\/Series\/Building-Modern-Web-Apps\">MVA Windows Azure Deep Dive<\/a>, we spoke about this for the first time publicly to a global audience.<\/p>\n<p>Today, I\u2019d like to give a formal introduction to ASP.NET Project \u201cHelios\u201d. This post will talk about why we\u2019re introducing this project, what we hope to accomplish with it, and how this might fit in to our ecosystem moving forward.<\/p>\n<blockquote>\n<p><em>I assume that the reader has a basic understanding of OWIN and ASP.NET Project Katana. If you are not familiar with these, a brief overview can be found at <\/em><a href=\"http:\/\/www.asp.net\/aspnet\/overview\/owin-and-katana\/an-overview-of-project-katana\"><em>http:\/\/www.asp.net\/aspnet\/overview\/owin-and-katana\/an-overview-of-project-katana<\/em><\/a><em>.<\/em><\/p>\n<\/blockquote>\n<h2>The world today<\/h2>\n<h2>Prescriptive behaviors<\/h2>\n<p>ASP.NET is an \u201ceverything and the kitchen sink\u201d programming model. It\u2019s very prescriptive, and developers are pushed to follow its recommended coding patterns. This makes it great for quickly designing and deploying LOB web applications, which was ASP.NET\u2019s original intended audience. However, over the years frameworks like MVC, WebAPI, and SignalR have come online, and developers have begun writing more complex applications following newer standards. These applications don\u2019t fit nicely into the LOB model which made ASP.NET famous. And while ASP.NET certainly allows writing this style of modern application, the simple truth is that the framework\u2019s prescriptive patterns don\u2019t always lend themselves to this style of application. Sometimes these behaviors are downright intrusive. Developers can end up spending a significant amount of time cajoling the framework into meeting their needs.<\/p>\n<p>Below are some sample behaviors which made sense when they were first implemented, but nowadays they are a large source of complaints from our developer base:<\/p>\n<ul>\n<li style=\"margin-bottom: 1em\">You cannot mix Windows Authentication (NTLM, Kerberos) and Forms Authentication in the same application.<\/li>\n<li style=\"margin-bottom: 1em\">The built-in Forms Authentication module silently converts HTTP 401 Unauthorized responses into HTTP 302 Found (redirect) responses.<\/li>\n<li style=\"margin-bottom: 1em\">Request validation shuts down requests which contain \u2018&lt;\u2019, \u2018&amp;\u2019, or other \u201cdangerous\u201d characters, even if your application handles these requests correctly.<\/li>\n<li style=\"margin-bottom: 1em\">Using Task.Wait() can lead to deadlocks in ASP.NET due to the special SynchronizationContext we use. Channel 9 has a video where Brad, Damian, and I <a href=\"https:\/\/channel9.msdn.com\/Events\/aspConf\/aspConf\/Async-in-ASP-NET\">speak about this<\/a> in more detail.<\/li>\n<\/ul>\n<h2>Why Helios?<\/h2>\n<p>When we look at our ecosystem, we\u2019re pleased by the success of MVC, WebAPI, SignalR, and our other recent high-level frameworks. These are valuable tools, they have a low barrier to entry for most developers, and they\u2019re deployed completely out-of-band. This allows us to innovate quickly. MVC and WebAPI have published new major releases annually; SignalR has approximately quarterly releases. It allows our customers to deploy immediately, even to shared hosters.<\/p>\n<p>Yet because System.Web is part of the .NET Framework proper, the ASP.NET runtime itself cannot iterate as quickly as we would like it to. We are bound by the release schedules of the .NET Framework as a whole. If a developer asks us to add a feature to ASP.NET, he must wait for the entire framework to rev. And then he must wait for his hoster or IT administrator to update the .NET Framework version on the web server. And if there\u2019s a bug he must again wait for us to provide a fix.<\/p>\n<p>Our core runtime iterates on the scale of years. The state of web technologies is much more agile \u2013 much more nimble. <i>A web technology can live its entire lifetime \u2013 conception to sunset \u2013 in the time that elapses between major releases of the .NET Framework.<\/i> Our developer audience deserves a base on which they can build a new breed of modern web applications.<\/p>\n<p>And it\u2019s not just wanting more agile development. Recall the list of ASP.NET pain points from earlier: unwanted redirects, too-helpful security handholding resulting in requests being denied, and so on. We\u2019ll never be able to make more than minor tweaks to these behaviors, as we can\u2019t risk breaking customers who have deployed sites and are depending on the existing behaviors.<\/p>\n<p>Finally, we\u2019ll never be able to make the ASP.NET core runtime a \u201cpay-for-play\u201d model. We have experimented several times with moving Web Forms out of System.Web.dll and into its own out-of-band package. This would finally allow us finally fix bugs that have been plaguing us for years. But Web Forms <i>defined<\/i> ASP.NET for years. The ASP.NET core pipeline and Web Forms processing are inextricably linked.<\/p>\n<h2>On IIS and self-host<\/h2>\n<p>A developer who cares deeply about these matters may opt to self-host his application. This is perfectly valid, and the Katana stack makes it easy to write host-agnostic applications. But consider all the features that IIS brings to the table.<\/p>\n<p>IIS handles application lifetime management, inspecting request patterns and frequencies to determine how long applications should run. It can suspend (rather than terminate) processes that are idle to help balance available system resources. For improved responsiveness, IIS offers a built-in user-mode cache and can automatically compress response content if appropriate. Application health monitoring is available via built-in logging and failed request tracing modules. IIS supports request filtering and transient worker process identities (least privilege) as part of its 10+ years of security hardening. And the inetmgr utility makes all of this (and more!) available to server administrators.<\/p>\n<p>In a self-hosted scenario, you\u2019re ultimately responsible for the process or Windows service, so you could absolutely achieve feature parity. But this is quite the undertaking to reimplement, and such an endeavor would be error-prone. Besides, if IIS already exists, why not just leverage it for our new host so that we get all of these automatically?<\/p>\n<p>And there\u2019s the crux of Project \u201cHelios\u201d. We want to combine the best of both worlds: pair the granular control offered by self-hosted scenarios with the benefits offered by being hosted inside IIS. And we want to do this while jettisoning the behaviors that developers have told us they dislike about ASP.NET.<\/p>\n<h2>Goals and non-goals<\/h2>\n<p>As with all things, we need to define our goals before we can determine whether we have been successful in this endeavor. It is not our intent to make a new framework that is everything to all developers. In particular:<\/p>\n<ul>\n<li style=\"margin-bottom: 1em\">It is <b>not<\/b> our goal to have screaming high throughput for \u201cHello World\u201d scenarios. While Helios does in fact perform significantly better than the full ASP.NET pipeline for such scenarios, these metrics aren\u2019t terribly useful for real-world applications.<\/li>\n<li style=\"margin-bottom: 1em\">It is <b>not<\/b> our goal to provide 100% compatibility with existing applications. In particular, Helios projects do not support .aspx or .ashx endpoints or other ASP.NET-isms.<\/li>\n<li style=\"margin-bottom: 1em\">It is <b>not<\/b> our goal to compete with self-host for developer mindshare. Each OWIN host has its own benefits and drawbacks, and developers should choose the host that meets their needs. We\u2019ll discuss choosing a host later in this post.<\/li>\n<\/ul>\n<p>On the flip side:<\/p>\n<ul>\n<li style=\"margin-bottom: 1em\">It <b>is<\/b> our goal to enable higher density on web servers. For a machine running a single application, this might be measured by allowing a greater number of concurrent requests on the machine. For a shared hoster, this might be measured by allowing more active sites on a single machine.<\/li>\n<li style=\"margin-bottom: 1em\">It <b>is<\/b> our goal to provide behavior that mimics self-host more than it mimics web-host. We\u2019re trying to eliminate as much magic as possible from the new host.<\/li>\n<li style=\"margin-bottom: 1em\">It <b>is<\/b> our goal to make the Helios framework fully out-of-band. The framework should be able to run without requiring installation as long as the target machine meets the minimum system requirements called out below. Developers should be able to acquire bug fixes \/ feature additions by acquiring updated packages through NuGet and bin-deploying to their servers \/ hosters.<\/li>\n<li style=\"margin-bottom: 1em\">It <b>is<\/b> our goal to reduce the friction of deploying a web application built on the Helios host. It should be just as easy to deploy a Helios-hosted application as it is any typical ASP.NET application.<\/li>\n<\/ul>\n<h2>Getting started<\/h2>\n<h2>Minimum system requirements<\/h2>\n<p>You\u2019ll need the following on your development box in order to write a Helios-based application:<\/p>\n<ul>\n<li><b>Windows 8<\/b> or <b>Windows Server 2012<\/b><\/li>\n<li><b>.NET Framework 4.5.1<\/b> (<a href=\"https:\/\/www.microsoft.com\/en-us\/download\/details.aspx?id=40773\">download<\/a>)<\/li>\n<li><b>Visual Studio 2012<\/b> (Visual Studio 2013 preferred but not required)<\/li>\n<\/ul>\n<p>And your web server \/ web hoster needs the following in order to run a Helios-based application:<\/p>\n<ul>\n<li><b>Windows Server 2012<\/b><\/li>\n<li><b>.NET Framework 4.5.1<\/b><\/li>\n<li><b>Full trust<\/b><\/li>\n<\/ul>\n<p>Some hosters (such as <a href=\"http:\/\/go.microsoft.com\/fwlink\/?linkid=306051\">Windows Azure Web Sites<\/a>) already meet these minimum requirements, and developers can begin creating and deploying Helios-based applications to these hosters immediately. Contact your hoster if you\u2019re unsure about their capabilities or system configuration.<b><\/b><\/p>\n<blockquote>\n<p><em>We\u2019re working on adding support for Windows 7 \/ Windows Server 2008 R2 in a future prerelease.<\/em><\/p>\n<\/blockquote>\n<p>Finally, since this application will be hosted in IIS, you\u2019ll need to make sure the application pool is configured as below:<\/p>\n<ul>\n<li>Managed runtime version: v4.0<\/li>\n<li>Pipeline mode: Integrated<\/li>\n<\/ul>\n<h2>Creating a new OWIN application on the Helios host<\/h2>\n<p>I\u2019m using Visual Studio 2013 for this walkthrough, but the same general steps should work on Visual Studio 2012.<\/p>\n<blockquote>\n<p><em>Important: Make sure NuGet Package Manager is fully up-to-date before you begin! The latest NuGet Package Manager for Visual Studio 2013 can be found at <\/em><a href=\"http:\/\/visualstudiogallery.msdn.microsoft.com\/4ec1526c-4a8c-4a84-b702-b21a8f5293ca\"><em>http:\/\/visualstudiogallery.msdn.microsoft.com\/4ec1526c-4a8c-4a84-b702-b21a8f5293ca<\/em><\/a><em>.<\/em><\/p>\n<\/blockquote>\n<ol>\n<li style=\"margin-bottom: 1em\">In Visual Studio, select File -&gt; New -&gt; Project.<\/li>\n<li style=\"margin-bottom: 1em\">Select Templates -&gt; Visual C# -&gt; Web, then <i>ASP.NET Web Application<\/i>. Ensure the target framework is set to .NET Framework 4.5 or later. Then hit OK.       \n<p><img decoding=\"async\" title=\"image\" border=\"0\" alt=\"image\" src=\"https:\/\/devblogs.microsoft.com\/aspnet\/wp-content\/uploads\/sites\/16\/2014\/02\/7041.image_310ED0E7.png\" width=\"532\" height=\"369\" \/><\/li>\n<li style=\"margin-bottom: 1em\">Select the Empty template, then hit OK.      \n<p><img decoding=\"async\" title=\"image\" border=\"0\" alt=\"image\" src=\"https:\/\/devblogs.microsoft.com\/aspnet\/wp-content\/uploads\/sites\/16\/2014\/02\/4807.image_3EE116E2.png\" width=\"455\" height=\"320\" \/><\/li>\n<li style=\"margin-bottom: 1em\">Install the <b>Microsoft.Owin.Host.IIS<\/b> NuGet package. If you use the NuGet Package Manager UI (in the Solution Explorer pane, right-click the project name, then select Manage NuGet Packages), remember to change the release type dropdown to <i>Include Prerelease<\/i>.       \n<p>You can also find installation instructions at <a href=\"https:\/\/www.nuget.org\/packages\/Microsoft.Owin.Host.IIS\/\">https:\/\/www.nuget.org\/packages\/Microsoft.Owin.Host.IIS\/<\/a>. At the time of this writing, the latest prerelease version is <i>0.1.5-pre<\/i>.       <\/p>\n<p><img decoding=\"async\" title=\"image\" border=\"0\" alt=\"image\" src=\"https:\/\/devblogs.microsoft.com\/aspnet\/wp-content\/uploads\/sites\/16\/2014\/02\/8130.image_70D8B76C.png\" width=\"483\" height=\"323\" \/><\/li>\n<li style=\"margin-bottom: 1em\">Add an OWIN startup class. Add a C# file named <i>Startup.cs<\/i> to your project with these contents:             \n<div id=\"scid:9ce6104f-a9aa-4a17-a79f-3a39532ebf7c:04a283bb-b2db-4004-85d9-935958a9085f\" class=\"wlWriterEditableSmartContent\" style=\"margin: 0px;padding: 0px;float: none\">\n<div style=\"border: #000080 1px solid;color: #000;font-family: 'Courier New', Courier, Monospace;font-size: 10pt\">\n<div style=\"background-color: #ffffff;overflow: auto;padding: 2px 5px\"><span style=\"background:#ffffff;color:#0000ff\">using<\/span><span style=\"background:#ffffff;color:#000000\"> System;<\/span><br> <span style=\"background:#ffffff;color:#0000ff\">using<\/span><span style=\"background:#ffffff;color:#000000\"> Owin;<\/span><\/p>\n<p> <span style=\"background:#ffffff;color:#0000ff\">public<\/span><span style=\"background:#ffffff;color:#000000\"> <\/span><span style=\"background:#ffffff;color:#0000ff\">class<\/span><span style=\"background:#ffffff;color:#000000\"> <\/span><span style=\"background:#ffffff;color:#2b91af\">Startup<\/span><span style=\"background:#ffffff;color:#000000\"> {<\/span><br> \u00a0\u00a0\u00a0\u00a0<span style=\"background:#ffffff;color:#000000\"><\/span><span style=\"background:#ffffff;color:#0000ff\">public<\/span><span style=\"background:#ffffff;color:#000000\"> <\/span><span style=\"background:#ffffff;color:#0000ff\">void<\/span><span style=\"background:#ffffff;color:#000000\"> Configuration(<\/span><span style=\"background:#ffffff;color:#2b91af\">IAppBuilder<\/span><span style=\"background:#ffffff;color:#000000\"> app) {<\/span><br> \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<span style=\"background:#ffffff;color:#000000\"><\/span><span style=\"background:#ffffff;color:#008000\">\/\/ New code:<\/span><br> \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<span style=\"background:#ffffff;color:#000000\">app.Run(<\/span><span style=\"background:#ffffff;color:#0000ff\">async<\/span><span style=\"background:#ffffff;color:#000000\"> context =&gt; {<\/span><br> \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<span style=\"background:#ffffff;color:#000000\">context.Response.ContentType = <\/span><span style=\"background:#ffffff;color:#a31515\">&quot;text\/plain&quot;<\/span><span style=\"background:#ffffff;color:#000000\">;<\/span><br> \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<span style=\"background:#ffffff;color:#000000\"><\/span><span style=\"background:#ffffff;color:#0000ff\">await<\/span><span style=\"background:#ffffff;color:#000000\"> context.Response.WriteAsync(<\/span><span style=\"background:#ffffff;color:#a31515\">&quot;Hello, world.&quot;<\/span><span style=\"background:#ffffff;color:#000000\">);<\/span><br> \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<span style=\"background:#ffffff;color:#000000\">});<\/span><br> \u00a0\u00a0\u00a0\u00a0<span style=\"background:#ffffff;color:#000000\">}<\/span><br> <span style=\"background:#ffffff;color:#000000\">}<\/span><\/div>\n<\/p><\/div>\n<\/p><\/div>\n<\/li>\n<li style=\"margin-bottom: 1em\">Run the project via CTRL-F5. You should see <i>Hello, world.<\/i> written to the response.       \n<p>Note: If you instead see an HTTP 403 Forbidden error page, verify that you have .NET 4.5.1 installed on your machine. The download is located <a href=\"https:\/\/www.microsoft.com\/en-us\/download\/details.aspx?id=40773\">here<\/a>.<\/li>\n<\/ol>\n<p>That\u2019s it! You\u2019ve now created an OWIN application running atop the Helios host for IIS. You can easily verify that System.Web.dll isn\u2019t involved anywhere in request processing by changing the code to print out all assemblies loaded into the current AppDomain along with a full stack trace.<\/p>\n<div id=\"scid:9ce6104f-a9aa-4a17-a79f-3a39532ebf7c:9f5935e4-49cc-4e3f-a5ef-496beb04270c\" class=\"wlWriterEditableSmartContent\" style=\"margin: 0px;padding: 0px;float: none\">\n<div style=\"border: #000080 1px solid;color: #000;font-family: 'Courier New', Courier, Monospace;font-size: 10pt\">\n<div style=\"background-color: #ffffff;overflow: auto;padding: 2px 5px\"><span style=\"background:#ffffff;color:#0000ff\">public<\/span><span style=\"background:#ffffff;color:#000000\"> <\/span><span style=\"background:#ffffff;color:#0000ff\">class<\/span><span style=\"background:#ffffff;color:#000000\"> <\/span><span style=\"background:#ffffff;color:#2b91af\">Startup<\/span><span style=\"background:#ffffff;color:#000000\"> {<\/span><br> \u00a0\u00a0\u00a0\u00a0<span style=\"background:#ffffff;color:#000000\"><\/span><span style=\"background:#ffffff;color:#0000ff\">public<\/span><span style=\"background:#ffffff;color:#000000\"> <\/span><span style=\"background:#ffffff;color:#0000ff\">void<\/span><span style=\"background:#ffffff;color:#000000\"> Configuration(<\/span><span style=\"background:#ffffff;color:#2b91af\">IAppBuilder<\/span><span style=\"background:#ffffff;color:#000000\"> app) {<\/span><br> \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<span style=\"background:#ffffff;color:#000000\"><\/span><span style=\"background:#ffffff;color:#008000\">\/\/ New code:<\/span><br> \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<span style=\"background:#ffffff;color:#000000\">app.Run(<\/span><span style=\"background:#ffffff;color:#0000ff\">async<\/span><span style=\"background:#ffffff;color:#000000\"> context =&gt; {<\/span><br> \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<span style=\"background:#ffffff;color:#000000\">context.Response.ContentType = <\/span><span style=\"background:#ffffff;color:#a31515\">&quot;text\/plain&quot;<\/span><span style=\"background:#ffffff;color:#000000\">;<\/span><\/p>\n<p> \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<span style=\"background:#ffffff;color:#000000\"><\/span><span style=\"background:#ffffff;color:#0000ff\">await<\/span><span style=\"background:#ffffff;color:#000000\"> context.Response.WriteAsync(<\/span><span style=\"background:#ffffff;color:#a31515\">&quot;Assemblies in AppDomain:&quot;<\/span><span style=\"background:#ffffff;color:#000000\"> + <\/span><span style=\"background:#ffffff;color:#2b91af\">Environment<\/span><span style=\"background:#ffffff;color:#000000\">.NewLine);<\/span><br> \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<span style=\"background:#ffffff;color:#000000\"><\/span><span style=\"background:#ffffff;color:#0000ff\">foreach<\/span><span style=\"background:#ffffff;color:#000000\"> (<\/span><span style=\"background:#ffffff;color:#0000ff\">var<\/span><span style=\"background:#ffffff;color:#000000\"> asm <\/span><span style=\"background:#ffffff;color:#0000ff\">in<\/span><span style=\"background:#ffffff;color:#000000\"> <\/span><span style=\"background:#ffffff;color:#2b91af\">AppDomain<\/span><span style=\"background:#ffffff;color:#000000\">.CurrentDomain.GetAssemblies()) {<\/span><br> \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<span style=\"background:#ffffff;color:#000000\"><\/span><span style=\"background:#ffffff;color:#0000ff\">await<\/span><span style=\"background:#ffffff;color:#000000\"> context.Response.WriteAsync(asm.FullName + <\/span><span style=\"background:#ffffff;color:#2b91af\">Environment<\/span><span style=\"background:#ffffff;color:#000000\">.NewLine);<\/span><br> \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<span style=\"background:#ffffff;color:#000000\">}<\/span><br> \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<span style=\"background:#ffffff;color:#000000\"><\/span><span style=\"background:#ffffff;color:#0000ff\">await<\/span><span style=\"background:#ffffff;color:#000000\"> context.Response.WriteAsync(<\/span><span style=\"background:#ffffff;color:#2b91af\">Environment<\/span><span style=\"background:#ffffff;color:#000000\">.NewLine);<\/span><\/p>\n<p> \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<span style=\"background:#ffffff;color:#000000\"><\/span><span style=\"background:#ffffff;color:#0000ff\">await<\/span><span style=\"background:#ffffff;color:#000000\"> context.Response.WriteAsync(<\/span><span style=\"background:#ffffff;color:#a31515\">&quot;Stack trace:&quot;<\/span><span style=\"background:#ffffff;color:#000000\"> + <\/span><span style=\"background:#ffffff;color:#2b91af\">Environment<\/span><span style=\"background:#ffffff;color:#000000\">.NewLine);<\/span><br> \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<span style=\"background:#ffffff;color:#000000\"><\/span><span style=\"background:#ffffff;color:#0000ff\">await<\/span><span style=\"background:#ffffff;color:#000000\"> context.Response.WriteAsync(<\/span><span style=\"background:#ffffff;color:#2b91af\">Environment<\/span><span style=\"background:#ffffff;color:#000000\">.StackTrace);<\/span><br> \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<span style=\"background:#ffffff;color:#000000\">});<\/span><br> \u00a0\u00a0\u00a0\u00a0<span style=\"background:#ffffff;color:#000000\">}<\/span><br> <span style=\"background:#ffffff;color:#000000\">}<\/span><\/div>\n<\/p><\/div>\n<\/p><\/div>\n<p>The output for <i>0.1.5-pre<\/i> will read:<\/p>\n<div id=\"scid:9ce6104f-a9aa-4a17-a79f-3a39532ebf7c:9495f6ef-5af2-4b86-8a6d-77364042d3d0\" class=\"wlWriterEditableSmartContent\" style=\"margin: 0px;padding: 0px;float: none\">\n<div style=\"border: #000080 1px solid;color: #000;font-family: 'Courier New', Courier, Monospace;font-size: 10pt\">\n<div style=\"background-color: #ffffff;overflow: auto;padding: 2px 5px\"><span style=\"background:#ffffff;color:#000000\">Assemblies in AppDomain:<\/span><br> <span style=\"background:#ffffff;color:#000000\">mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089<\/span><br> <span style=\"background:#ffffff;color:#000000\">Microsoft.AspNet.Loader.IIS, Version=0.1.5.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35<\/span><br> <span style=\"background:#ffffff;color:#000000\">System.Core, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089<\/span><br> <span style=\"background:#ffffff;color:#000000\">System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089<\/span><br> <span style=\"background:#ffffff;color:#000000\">System.Configuration, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a<\/span><br> <span style=\"background:#ffffff;color:#000000\">System.Xml, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089<\/span><br> <span style=\"background:#ffffff;color:#000000\">Microsoft.Owin, Version=2.1.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35<\/span><br> <span style=\"background:#ffffff;color:#000000\">Microsoft.Owin.Host.IIS, Version=0.1.5.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35<\/span><br> <span style=\"background:#ffffff;color:#000000\">Microsoft.Owin.Host.IIS.Security, Version=0.1.5.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35<\/span><br> <span style=\"background:#ffffff;color:#000000\">Microsoft.Owin.Hosting, Version=2.1.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35<\/span><br> <span style=\"background:#ffffff;color:#000000\">Owin, Version=1.0.0.0, Culture=neutral, PublicKeyToken=f0ebd12fd5e55cc5<\/span><br> <span style=\"background:#ffffff;color:#000000\">WebApplication32, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null<\/span><br> <span style=\"background:#ffffff;color:#000000\">Microsoft.CSharp, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a<\/span><br> <span style=\"background:#ffffff;color:#000000\">System.Dynamic, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a<\/span><br> <span style=\"background:#ffffff;color:#000000\">Anonymously Hosted DynamicMethods Assembly, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null<\/span><br> <span style=\"background:#ffffff;color:#000000\">System.Security, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a<\/span><\/p>\n<p> <span style=\"background:#ffffff;color:#000000\">Stack trace:<\/span><br> <span style=\"background:#ffffff;color:#000000\">at System.Environment.GetStackTrace(Exception e, Boolean needFileInfo)<\/span><br> <span style=\"background:#ffffff;color:#000000\">at System.Environment.get_StackTrace()<\/span><br> <span style=\"background:#ffffff;color:#000000\">at Startup.&lt;&lt;Configuration&gt;b__0&gt;d__2.MoveNext() in c:&#092;Users&#092;levib&#092;Documents&#092;Visual Studio 2013&#092;Projects&#092;WebApplication32&#092;WebApplication32&#092;Startup.cs:line 17<\/span><br> <span style=\"background:#ffffff;color:#000000\">at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine&amp; stateMachine)<\/span><br> <span style=\"background:#ffffff;color:#000000\">at System.Runtime.CompilerServices.AsyncTaskMethodBuilder.Start[TStateMachine](TStateMachine&amp; stateMachine)<\/span><br> <span style=\"background:#ffffff;color:#000000\">at Startup.&lt;Configuration&gt;b__0(IOwinContext context)<\/span><br> <span style=\"background:#ffffff;color:#000000\">at Microsoft.Owin.Extensions.UseHandlerMiddleware.Invoke(IOwinContext context)<\/span><br> <span style=\"background:#ffffff;color:#000000\">at Microsoft.Owin.Infrastructure.OwinMiddlewareTransition.Invoke(IDictionary`2 environment)<\/span><br> <span style=\"background:#ffffff;color:#000000\">at Microsoft.Owin.Host.IIS.HeliosCallContext.Invoke(Func`2 app)<\/span><br> <span style=\"background:#ffffff;color:#000000\">&#8230; boring intrinsic stuff removed &#8230;<\/span><br> <span style=\"background:#ffffff;color:#000000\">at Microsoft.AspNet.Loader.IIS.Infrastructure.PipelineExecutor.MapRequestHandler(MapRequestHandlerData* pMapRequestHandlerData)<\/span><\/div>\n<\/p><\/div>\n<\/p><\/div>\n<p>You can see that System.Web.dll and related assemblies (like System.Web.Extensions.dll) aren\u2019t in the stack trace at all. In fact, they\u2019re not even in the current AppDomain! They exert no influence over request processing, so you\u2019re not paying their per-request memory overhead and aren\u2019t battling their unwanted behaviors.<\/p>\n<p>Note: If you attach a debugger and look at the loaded modules list (Debug -&gt; Windows -&gt; Modules), you\u2019ll see that System.Web.dll is still loaded in the process. The reason for this is that it\u2019s still ultimately involved with process management: application startup and shutdown, <a href=\"http:\/\/blogs.technet.com\/b\/erezs_iis_blog\/archive\/2013\/06\/26\/new-feature-in-iis-8-5-idle-worker-process-page-out.aspx\">IIS idle process page-out<\/a>, and a handful of other features. But even though System.Web.dll is present in the process, this only incurs a small fixed per-process overhead. There is no per-request overhead. (In fact, no System.Web.dll code paths are involved <i>whatsoever<\/i> in request processing.)<\/p>\n<h2>Adding Helios to an existing OWIN-based application<\/h2>\n<p>Have an existing OWIN-based application? No problem! Consider the <a href=\"https:\/\/github.com\/SignalR\/SignalR-StockTicker\">SignalR-StockTicker sample<\/a> on GitHub. This sample uses the System.Web host for OWIN.<\/p>\n<ol>\n<li style=\"margin-bottom: 1em\">Open the SignalR-StockTicker project in Visual Studio 2013.<\/li>\n<li style=\"margin-bottom: 1em\">Install the <b>Microsoft.Owin.Host.IIS<\/b> NuGet package to the project.<\/li>\n<li style=\"margin-bottom: 1em\">[optional] Remove the <b>Microsoft.Owin.Host.SystemWeb<\/b> NuGet package from the project. This step is not strictly required, as the Helios framework will suppress loading this particular package at runtime anyway.<\/li>\n<li style=\"margin-bottom: 1em\">In the Solution Explorer pane, open the SignalR.StockTicker folder, right-click StockTicker.html, and hit <i>View in Browser<\/i>.<\/li>\n<li style=\"margin-bottom: 1em\">Hit the <i>Open Market<\/i> button on the page.       \n<p><img decoding=\"async\" title=\"image\" border=\"0\" alt=\"image\" src=\"https:\/\/devblogs.microsoft.com\/aspnet\/wp-content\/uploads\/sites\/16\/2014\/02\/6076.image_65AF2D22.png\" width=\"531\" height=\"362\" \/><\/li>\n<\/ol>\n<p>That\u2019s it! The only thing that\u2019s needed to convert a web-hosted OWIN application into a Helios-hosted OWIN application is to pull the necessary NuGet package. As long as the application truly is OWIN-based (doesn\u2019t rely on HttpRuntime, HttpContext, etc.), no other changes should be necessary.<\/p>\n<p>There\u2019s one more nifty thing I want to point out: notice that SignalR is continuing to utilize WebSockets under the covers, even after migrating to the Helios host.<\/p>\n<h2>Using the Helios runtime without OWIN<\/h2>\n<p>Finally, the option exists to run an application directly on top of Helios rather than go through the Helios host for OWIN. This provides the most granular control over application startup, shutdown, and request processing. More on this can be found in <a href=\"http:\/\/blogs.msdn.com\/b\/webdev\/archive\/2014\/02\/18\/supplemental-to-asp-net-project-helios.aspx#_Using_the_Helios\">the supplemental post<\/a>.<\/p>\n<h2>Caveats<\/h2>\n<p>Remember our stated non-goals: we <i>do not<\/i> intend 100% compatibility with existing applications. In particular, since Helios completely bypasses the typical ASP.NET pipeline, anything that has a hard dependency on the ASP.NET pipeline will not work correctly in a Helios application. Requests to Web Forms (.aspx) or Razor \/ Web Pages (.cshtml) endpoints will not be recognized. ASP.NET MVC endpoints will be ignored. Accessing HttpRuntime, HostingEnvironment, or other ASP.NET-hosting-intrinsic types could result in undefined behavior.<\/p>\n<p>ASP.NET Web API endpoints will be reachable as long as Web API has been configured via the OWIN extensibility layer rather than as a typical ASP.NET IHttpModule. To use Web API atop OWIN:<\/p>\n<ol>\n<li style=\"margin-bottom: 1em\">In your project, reference the <a href=\"https:\/\/www.nuget.org\/packages\/Microsoft.AspNet.WebApi.Owin\/\"><b>Microsoft.AspNet.WebApi.Owin<\/b><\/a> NuGet package.<\/li>\n<li style=\"margin-bottom: 1em\">Use the <b>IAppBuilder.UseWebApi<\/b> extension method to register Web API as an OWIN middleware. A sample Startup.cs that defines a default Web API route is provided below:             \n<div id=\"scid:9ce6104f-a9aa-4a17-a79f-3a39532ebf7c:d5c8bbf7-f5d0-4674-910b-135f483feb3a\" class=\"wlWriterEditableSmartContent\" style=\"margin: 0px;padding: 0px;float: none\">\n<div style=\"border: #000080 1px solid;color: #000;font-family: 'Courier New', Courier, Monospace;font-size: 10pt\">\n<div style=\"background-color: #ffffff;overflow: auto;padding: 2px 5px\"><span style=\"background:#ffffff;color:#0000ff\">using<\/span><span style=\"background:#ffffff;color:#000000\"> System;<\/span><br> <span style=\"background:#ffffff;color:#0000ff\">using<\/span><span style=\"background:#ffffff;color:#000000\"> System.Web.Http;<\/span><br> <span style=\"background:#ffffff;color:#0000ff\">using<\/span><span style=\"background:#ffffff;color:#000000\"> Owin;<\/span><\/p>\n<p> <span style=\"background:#ffffff;color:#0000ff\">public<\/span><span style=\"background:#ffffff;color:#000000\"> <\/span><span style=\"background:#ffffff;color:#0000ff\">class<\/span><span style=\"background:#ffffff;color:#000000\"> <\/span><span style=\"background:#ffffff;color:#2b91af\">Startup<\/span><span style=\"background:#ffffff;color:#000000\"> {<\/span><br> \u00a0\u00a0\u00a0\u00a0<span style=\"background:#ffffff;color:#000000\"><\/span><span style=\"background:#ffffff;color:#008000\">\/\/ This code configures Web API. The Startup class is specified as a type<\/span><br> \u00a0\u00a0\u00a0\u00a0<span style=\"background:#ffffff;color:#000000\"><\/span><span style=\"background:#ffffff;color:#008000\">\/\/ parameter in the WebApp.Start method.<\/span><br> \u00a0\u00a0\u00a0\u00a0<span style=\"background:#ffffff;color:#000000\"><\/span><span style=\"background:#ffffff;color:#0000ff\">public<\/span><span style=\"background:#ffffff;color:#000000\"> <\/span><span style=\"background:#ffffff;color:#0000ff\">void<\/span><span style=\"background:#ffffff;color:#000000\"> Configuration(<\/span><span style=\"background:#ffffff;color:#2b91af\">IAppBuilder<\/span><span style=\"background:#ffffff;color:#000000\"> appBuilder) {<\/span><br> \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<span style=\"background:#ffffff;color:#000000\"><\/span><span style=\"background:#ffffff;color:#008000\">\/\/ Configure Web API for self-host. <\/span><br> \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<span style=\"background:#ffffff;color:#000000\"><\/span><span style=\"background:#ffffff;color:#2b91af\">HttpConfiguration<\/span><span style=\"background:#ffffff;color:#000000\"> config = <\/span><span style=\"background:#ffffff;color:#0000ff\">new<\/span><span style=\"background:#ffffff;color:#000000\"> <\/span><span style=\"background:#ffffff;color:#2b91af\">HttpConfiguration<\/span><span style=\"background:#ffffff;color:#000000\">();<\/span><br> \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<span style=\"background:#ffffff;color:#000000\">config.Routes.MapHttpRoute(<\/span><br> \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<span style=\"background:#ffffff;color:#000000\">name: <\/span><span style=\"background:#ffffff;color:#a31515\">&quot;DefaultApi&quot;<\/span><span style=\"background:#ffffff;color:#000000\">,<\/span><br> \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<span style=\"background:#ffffff;color:#000000\">routeTemplate: <\/span><span style=\"background:#ffffff;color:#a31515\">&quot;api\/{controller}\/{id}&quot;<\/span><span style=\"background:#ffffff;color:#000000\">,<\/span><br> \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<span style=\"background:#ffffff;color:#000000\">defaults: <\/span><span style=\"background:#ffffff;color:#0000ff\">new<\/span><span style=\"background:#ffffff;color:#000000\"> { id = <\/span><span style=\"background:#ffffff;color:#2b91af\">RouteParameter<\/span><span style=\"background:#ffffff;color:#000000\">.Optional }<\/span><br> \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<span style=\"background:#ffffff;color:#000000\">);<\/span><\/p>\n<p> \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<span style=\"background:#ffffff;color:#000000\">appBuilder.UseWebApi(config);<\/span><br> \u00a0\u00a0\u00a0\u00a0<span style=\"background:#ffffff;color:#000000\">}<\/span><br> <span style=\"background:#ffffff;color:#000000\">}<\/span><\/div>\n<\/p><\/div>\n<\/p><\/div>\n<\/li>\n<\/ol>\n<h2>Further thoughts<\/h2>\n<h2>Performance and resource consumption<\/h2>\n<p>The Helios architecture follows the modern trend of \u201cpay-for-play\u201d design. As much as possible, the framework tries to avoid magic behavior, opting instead to give the developer nearly complete control over the application. This is the same model followed by the Katana project. If your application doesn\u2019t use a particular capability or feature, the unused functionality shouldn\u2019t affect the application\u2019s behavior or its performance characteristics.<\/p>\n<p>The Helios runtime achieves around 2x \u2013 3x the throughput for \u201cHello world\u201d scenarios when compared to System.Web, but this honestly isn\u2019t a terribly interesting measurement. These requests are best handled by caches rather than by the web server itself. Developer code tends to dominate in real-world applications, so throughput remains steady regardless of the underlying framework. What <i>is<\/i> interesting is considering other resources like available memory, where the framework does in fact tend to show up in profiles. In our tests the Helios runtime consumes around <b>96% less<\/b> amortized per-request memory than does the System.Web runtime. See <a href=\"http:\/\/blogs.msdn.com\/b\/webdev\/archive\/2014\/02\/18\/supplemental-to-asp-net-project-helios.aspx#_On_performance_and\">the supplemental post<\/a> for more information on these measurements and their real-world impact.<\/p>\n<h2>Support<\/h2>\n<p>This is a very early prerelease. One might even call it pre-alpha. There is no official support provided for this. We do not guarantee that we\u2019ll ever ship a release version. The full EULA can be found <a href=\"http:\/\/www.microsoft.com\/web\/webpi\/eula\/aspnetcomponent_enu.htm\">here<\/a>.<\/p>\n<p>The EULA <i>does<\/i> allow for deployment to a hosting provider. However, deploying such an early prerelease to a service that you care about is ill-advised.<\/p>\n<h2>Conclusion<\/h2>\n<p>We\u2019re excited about what this could mean for the future of our platform, especially as more frameworks and components break their strict dependency on System.Web.dll. This new design promises to allow us to ship new functionality fully out-of-band and to avoid surprising developers with unwanted behaviors.<\/p>\n<p>I also want to stress that this is strictly <i>an option<\/i>. The target audience for this package is a minority of our overall developer audience. The team has no plans to force our general developer audience on to this system.<\/p>\n<p>Finally, there is a <a href=\"http:\/\/blogs.msdn.com\/b\/webdev\/archive\/2014\/02\/18\/supplemental-to-asp-net-project-helios.aspx\">supplemental post<\/a> available with further information available for more advanced developers.&#160; That post discusses performance and resource utilization in more detail. It also discusses using the Helios APIs directly without going through OWIN.<\/p>\n<p>As always, feedback is greatly appreciated! Feel free to sound off in the comments below. And thanks for reading!<\/p>\n<p><em>Thanks to Eilon, Glenn, Damian, and Scott, who all graciously offered their time to help review this post.<\/em><\/p>\n","protected":false},"excerpt":{"rendered":"<p>In late 2013 we made available a prerelease NuGet package which allows running a managed web application directly on top of IIS without going through the normal ASP.NET (System.Web) request processing pipeline. This was a relatively quiet event without too much fanfare. At last month\u2019s MVA Windows Azure Deep Dive, we spoke about this for [&hellip;]<\/p>\n","protected":false},"author":413,"featured_media":58792,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[197],"tags":[7463],"class_list":["post-744","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-aspnet","tag-helios"],"acf":[],"blog_post_summary":"<p>In late 2013 we made available a prerelease NuGet package which allows running a managed web application directly on top of IIS without going through the normal ASP.NET (System.Web) request processing pipeline. This was a relatively quiet event without too much fanfare. At last month\u2019s MVA Windows Azure Deep Dive, we spoke about this for [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/posts\/744","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/users\/413"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/comments?post=744"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/posts\/744\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/media\/58792"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/media?parent=744"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/categories?post=744"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/tags?post=744"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}