This presentation is an introduction to OWIN and Katana project. The title states it all, NOT ONLY IIS, meaning that, we can now host Web Apps outside IIS.
Apidays New York 2024 - The value of a flexible API Management solution for O...
OWIN and Katana Project - Not Only IIS - NoIIS
1. NoIIS
OWIN, KATANA BY MICROSOFT
Bilal Haidar, http://blog.bilalhaidar.com
NOT ONLY IIS
2. AGENDA
• Microsoft Web Platform, Brief History
• OWIN is a Specification
• Katana by Microsoft
3. ASP.NET: BRIEF HISTORY
ASP.NET first released in early 2002 with the .NET
Framework 1.0
Optimized for 2 primary customers:
Classic ASP developers
Desktop LOB developers
4. THIS CREATED SOME
CHALLENGES…
ASP.NET shipped as a part of .NET Framework – slow ship
cycle (time between releases was on the order of years)
As the ASP.NET requirements grew, so did the size &
complexity of System.Web
All of the features were turned on by default – you have to
opt out
Only one hosting option – IIS
5. REVOLUTIONARY STEPS…
2007-2008: ASP.NET MVC ships out of band from the .NET
Framework
Enables more rapid ship cycle
Open Source!
Still tied to System.Web
6. TOWARDS MODERN WEB
APPS…
“Shift from dynamic, server-generated Web pages to static initial markup
with dynamic sections of the page generated from client-side script
communicating with backend Web APIs through AJAX requests”
2012: ASP.NET Web API released, NUGET package
Designed with no dependencies on System.Web
No dependency on System.Web
Includes self-hosting capability (NoIIS)
7. THE SELF-HOST
REALIZATION…
“The power and flexibility of Web API’s self-hosting capability proved
very attractive to developers who wanted a small, lightweight host of their
services”
ASP.NET Web API enabled self-hosting
Other frameworks had or were writing their own self-host
servers (e.g. SignalR)
“A modern Web application generally supports static file serving,
dynamic page generation, Web API, and SignalR.”
8. WHAT’S NEEDED?
“What was needed was a single hosting abstraction that would enable a
developer to compose an application from a variety of different
components and frameworks, and then run that application on a
supporting host.”
Welcome to OWIN
Open Web Interface for .NET
9. OWIN
“A specification aiming at creating abstraction between Web servers
and framework components” (http://www.owin.org)
• Inspired by the benefits achieved by Rack & Nodejs
• 2 Microsoft employee behind it (Benjamin Vanderveen & Louis
Dejardin)
• 2 main goals:
• New components could be more easily developed &
consumed
• Apps could be more easily ported between hosts &
potentially entire platforms/OS.
11. OWIN ENVIRONMENT
DICTIONARY
• A data structure: IDictionary<string, object>
• Stores all of the state necessary for processing an HTTP
request & response
“An OWIN-compatible Web server is responsible for populating the
environment dictionary with data such as the body streams and header
collections for an HTTP request and response. It is then the responsibility
of the application or framework components to populate or update the
dictionary values and write to the response body stream”
12. OWIN ENVIRONMENT
DICTIONARY
Required Key Name Value Description
Yes "owin.RequestBody" A Stream with the request body, if any.
Yes "owin.RequestHeaders" An IDictionary<string, string[]> of request headers.
Yes "owin.RequestMethod"
A string containing the HTTP request method of the request
(e.g., "GET", "POST").
Yes "owin.RequestPath"
A string containing the request path. The path MUST be relative to the "root" of
the application delegate.
Yes "owin.RequestPathBase"
A string containing the portion of the request path corresponding to the "root" of
the application delegate.
Yes "owin.RequestProtocol"
A string containing the protocol name and version
(e.g. "HTTP/1.0" or "HTTP/1.1").
Yes "owin.RequestQueryString"
A string containing the query string component of the HTTP request URI, without
the leading “?” (e.g., "foo=bar&baz=quux"). The value may be an empty string.
Yes "owin.RequestScheme" A string containing the URI scheme used for the request (e.g., "http", "https").
13. OWIN ENVIRONMENT
DICTIONARY
Required Key Name Value Description
Yes "owin.ResponseBody" A Stream used to write out the response body, if any
Yes "owin.ResponseHeaders" An IDictionary<string, string[]> of response headers.
No "owin.ResponseStatusCode"
An optional int containing the HTTP response status code as defined in RFC
2616 section 6.1.1. The default is 200.
No "owin.ResponseReasonPhrase"
An optional string containing the reason phrase associated the given status
code. If none is provided then the server SHOULD provide a default as described
in RFC 2616section 6.1.1
No "owin.ResponseProtocol"
An optional string containing the protocol name and version
(e.g. "HTTP/1.0" or "HTTP/1.1"). If none is provided then
the “owin.RequestProtocol” key’s value is the default.
Yes "owin.ResponseBody" A Stream used to write out the response body, if any.
Yes "owin.ResponseHeaders" An IDictionary<string, string[]> of response headers.
No "owin.ResponseStatusCode"
An optional int containing the HTTP response status code as defined in RFC
2616 section 6.1.1. The default is 200.
14. OWIN APPLICATION
DELEGATE
“The primary interface in OWIN is called the application delegate or
AppFunc.
An application delegate takes the IDictionary<string, object> environment
variable and returns a Task when it has finished processing.”
using AppFunc =
Func<IDictionary<string, object>, Task>;
15. OWIN APPLICATION
DELEGATE
“The application delegate is an implementation of the Func delegate type
where the function accepts the environment dictionary as input and
returns a task.”
“The asynchronous design enables the abstraction to be efficient with its
handling of computing resources, particularly in more I/O intensive
operations.”
“Because the application delegate is an atomic unit of execution and
because the environment dictionary is carried as a parameter on the
delegate, OWIN components could be easily chained together to create
complex HTTP processing pipelines.”
16. KATANA
Microsoft’s OWIN implementation
https://katanaproject.codeplex.com/
Set of hosts and servers
IIS or self-host
Set of convenience classes
OwinContext, OwinRequest, OwinResponse, etc.
AppBuilderUseExtensions
AuthenticationManager
Set of middleware for common features
Authentication
Hosting content (e.g. static files)
CORS
17. KATANA WEB STACK
Host manages process lifetime (start & stop), it could be IIS or any other custom/standalone
executable.
Server listens for HTTP requests, constructs the environment dictionary, Startups the application &
processes requests through an OWIN pipeline.
Middleware are specific components that runs in the OWIN pipeline (e.g. WebAPI, SignalR, etc.). A
middleware is simply a component that exposes the application delegate.
Application is the code you write!
client
Host
OWIN Server
Middleware Middleware Application
18. KATANA COMPONENTS
Host
Server
Middleware
Application
• IIS
• OwinHost.exe (OwinHost)
• Custom Process (e.g. Console app, Windows
Service)
• SystemWeb (Microsoft.Owin.Host.SystemWeb)
• HttpListener (Microsoft.Owin.Host.HttpListener)
• SignalR)
• Web API
• Nancy (MVC Framework)
• etc.
19. KATANA NUGET PACKAGES
Self Hosting / No IIS
IIS Hosting
PM> Install-Package Microsoft.Owin.SelfHost
Attempting to resolve dependency 'Owin (≥ 1.0)'.
Attempting to resolve dependency 'Microsoft.Owin (≥ 2.1.0)'.
Attempting to resolve dependency 'Microsoft.Owin.Diagnostics (≥
2.1.0)'.
PM> Install-Package Microsoft.Owin.Host.SystemWeb
Attempting to resolve dependency 'Owin (≥ 1.0)'.
Attempting to resolve dependency 'Microsoft.Owin (≥ 2.1.0)'.
21. KATANA STARTUP
Startup class
using Microsoft.Owin;
using Owin;
[assembly: OwinStartup(typeof(IISHosting.Startup))]
namespace IISHosting
{
public class Startup
{
public void Configuration(IAppBuilder app)
{
app.UseHandlerAsync((req, res) => {
res.ContentType = "text/plain";
return res.WriteAsync("Hello Katana!");
});
}
}
}
22. KATANA STARTUP
DETECTION
Naming Convention: Katana looks for a class named Startup in
namespace matching the assembly name
OwinStartup Attribute: Katana looks for the OwinStartup attribute to
locate the Startup class. The OwinStartup attribute overrides the naming
convention
appSetting element in the Configuration file:
The appSetting element overrides the OwinStartup attribute
and naming convention
[assembly: OwinStartup(typeof(StartupDemo.TestStartup))]
<appSettings>
<add key="owin:appStartup" value="StartupDemo.TestStartup" />
</appSettings>
23. KATANA HOST
(CUSTOM PROCESS)
using System;
using Microsoft.Owin.Hosting;
namespace NoIISHosting
{
public class Program
{
static void Main(string[] args)
{
var baseUrl = "http://localhost:5000";
if (args[0] == "--url") { baseUrl = args[1]; }
using (WebApp.Start<Startup>(new StartOptions(baseUrl) { ServerFactory =
"Microsoft.Owin.Host.HttpListener"}))
{
Console.WriteLine(string.Format("Katana Server running @ {0}", baseUrl));
Console.WriteLine();
// Keep the server going until we're done
Console.WriteLine("Press [Enter] To Exit ...");
Console.ReadKey();
}
}
}
}
Starting SERVER
(HttpListener) & using
Startup
24. KATANA MIDDLEWARE
Code to process requests
A class with a constructor accepting:
Func<IDictionary<string, object>, Task> (aka “AppFunc”)
representing the NEXT middleware in the pipeline
Method named Invoke (by convention) accepting as input
IDictionary<string, object>
One or more Middlewares can be chained in a pipeline
26. KATANA MIDDLEWARE
using AppFunc = Func<IDictionary<string, object>, Task>;
public class SimpleLogger
{
private readonly AppFunc _next;
private readonly SimpleLoggerOptions _options;
public SimpleLogger(AppFunc next, SimpleLoggerOptions options)
{
_next = next;
_options = options;
}
public async Task Invoke(IDictionary<string, object> environment)
{
foreach (var key in _options.RequestKeys)
{
_options.Log(key, environment[key]);
}
await _next(environment);
foreach (var key in _options.ResponseKeys)
{
_options.Log(key, environment[key]);
}
}
}
public class SimpleLoggerOptions
{
public IList<string> RequestKeys { get; set; }
public IList<string> ResponseKeys { get; set; }
public Action<string, object> Log { get; set; }
}
Request Processing
Response Processing
NEXT Middleware in
Pipeline
AppFunc
27. KATANA OWINCONTEXT
An API providing a strongly typed wrapper for
environment dictionary
public async Task Invoke(IDictionary<string, object> env)
{
var ctx = new OwinContext(env);
var url = ctx.Request.Uri;
var accept = ctx.Request.Headers["Accept"];
var username = ctx.Request.User.Identity.Name;
ctx.Response.StatusCode = 200;
ctx.Response.Headers.Add("Myheader", new [] {"cusotm value"});
using (var sw = new StreamWriter(ctx.Response.Body))
{
await sw.WriteLineAsync("<h1>Hello Katana!</h1>");
}
}
29. SIGNALR 2.0 SELF HOSTING
Add Program class to host the HttpListener server
using System;
using Microsoft.AspNet.SignalR;
using Microsoft.Owin.Hosting;
using Owin;
using Microsoft.Owin.Cors;
namespace SignalRSelfHost
{
public class Program
{
static void Main(string[] args)
{
var url = "http://localhost:8080";
using (WebApp.Start(url))
{
Console.WriteLine("Server running on {0}", url);
Console.ReadLine();
}
}
}
}
30. SIGNALR 2.0 SELF HOSTING
Add Startup class to configure & add SignalR to OWIN
pipeline
using System;
using Microsoft.AspNet.SignalR;
using Microsoft.Owin.Hosting;
using Owin;
using Microsoft.Owin.Cors;
namespace SignalRSelfHost
{
class Startup
{
public void Configuration(IAppBuilder app)
{
app.UseCors(CorsOptions.AllowAll);
app.MapSignalR();
}
}
}
31. SIGNALR 2.0 SELF HOSTING
Add MyHub class to communicate with clients connecting
to SignalR server
using System;
using Microsoft.AspNet.SignalR;
using Microsoft.Owin.Hosting;
using Owin;
using Microsoft.Owin.Cors;
namespace SignalRSelfHost
{
public class MyHub : Hub
{
public void Send(string name, string message)
{
Clients.All.addMessage(name, message);
}
}
}
Defined by Server,
Called by Client
Defined by Client,
Called by Server
32. SIGNALR 2.0 SELF HOSTING
Add Empty Website to host SignalR JS files & HTML
page
Install the following Nuget Packages:
Finally, add an HTML page
PM> Install-Package Microsoft.AspNet.SignalR.JS
33. SIGNALR 2.0 SELF HOSTING
<script type="text/javascript">
$(function () {
//Set the hubs URL for the connection
$.connection.hub.url = "http://localhost:8080/signalr";
// Declare a proxy to reference the hub.
var chat = $.connection.myHub;
// Create a function that the hub can call to broadcast messages.
chat.client.addMessage = function (name, message) {
// Html encode display name and message.
var encodedName = $('<div />').text(name).html();
var encodedMsg = $('<div />').text(message).html();
// Add the message to the page.
$('#discussion').append('<li><strong>' + encodedName
+ '</strong>: ' + encodedMsg + '</li>');
};
// Get the user name and store it to prepend to messages.
$('#displayname').val(prompt('Enter your name:', ''));
// Set initial focus to message input box.
$('#message').focus();
// Start the connection.
$.connection.hub.start().done(function () {
$('#sendmessage').click(function () {
// Call the Send method on the hub.
chat.server.send($('#displayname').val(), $('#message').val());
// Clear text box and reset focus for next comment.
$('#message').val('').focus();
});
});
});
</script>
36. KATANA PORTABILITY
IIS
SystemWeb
Web API + SignalR + static files
Application
Windows (local or remote)
Console App / Owin Host
HttpListener
Web API + SignalR + static files
Application
Windows (local or remote)
OwinHost
HttpSys
Web API + SignalR + static files
Application
Windows Azure Worker Role
37. KATANA PERF / SCALE
Composition model gives you control over performance
characteristics
Async throughout
Separate server and host components
38. REFERENCES
Open Web Interface for .NET
OWIN & Katana
Mini-Training OWIN & Katana
The Katana Project
Getting Started with the Katana Project
OWIN and Katana (The new HTTP Host for Web Apps)