So I was quite confused about hosting Nancyfx on OWIN under IIS. Parts of the Nancy wiki led me slightly astray.

Here is the simple guide.

Make sure you Install the following nuget packages (if you havn’t already).

1
2
Nancy.Owin
Microsoft.Owin.Host.SystemWeb

Owin uses a class called Startup.cs to do basic configuration. We need to add nancy to the app, and then add additional StageMarkers used by the ASP pipeline.

Startup.cs

1
2
3
4
5
6
7
8
9
10
11
12
using Microsoft.Owin.Extensions;
using Owin;
public class Startup
{
public void Configuration(IAppBuilder app)
{
app.UseNancy();
app.UseStageMarker(PipelineStage.MapHandler);
}
}

Static Files

Here you need to make a choice, do you want to have IIS manage the static files, or use the OWIN module. Personally I go for IIS. I don’t have any data on this, but I have a feeling IIS might be faster to serve static content.

IIS Static Hosting

runAllManagedModulesForAllRequests when set to true does not allow Native IIS modules to run like the static files module. So we will want to turn that off if we want IIS to handle static files.

web.config

1
2
3
4
<system.webServer>
<modules runAllManagedModulesForAllRequests="false" />
</system.webServer>

OWIN Static Hosting

Nuget Package

Install-Package Microsoft.Owin.StaticFiles

Web.config

1
2
3
4
<system.webServer>
<modules runAllManagedModulesForAllRequests="true" />
</system.webServer>

Startup.cs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class Startup
{
public void Configuration(IAppBuilder app)
{
app.UseFileServer(new FileServerOptions()
{
RequestPath = new PathString("/foo"),
FileSystem = new PhysicalFileSystem(@".\web"),
});
app.UseNancy();
app.UseStageMarker(PipelineStage.MapHandler);
}
}

Put, Head, Delete

if you need Put, Head or Delete requests add the following to your webconfig

1
2
3
4
5
6
7
8
9
<system.webServer>
<handlers>
<remove name="ExtensionlessUrlHandler-Integrated-4.0" />
<remove name="OPTIONSVerbHandler" />
<remove name="TRACEVerbHandler" />
<add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="*" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />
</handlers>
</system.webServer>

Windows Authentication

To use Windows authentication you need to have the authentication type in your web.config

1
2
3
<system.web>
<authentication mode="Windows"/>
</system.web>

To actually be able to get the username of the user in code, you can use the following (assume .net 45).

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
public class User : IUserIdentity
{
private readonly ClaimsPrincipal claimsPrincipal;
public User(ClaimsPrincipal claimsPrincipal)
{
this.claimsPrincipal = claimsPrincipal;
}
public string UserName { get { return claimsPrincipal.Identity.Name; } }
public IEnumerable<string> Claims { get { return claimsPrincipal.Claims.Select(c => c.ToString()); } }
}
public class Bootstrapper : DefaultNancyBootstrapper
{
protected override void RequestStartup(TinyIoCContainer container, IPipelines pipelines, NancyContext context)
{
pipelines.BeforeRequest += ctx =>
{
ctx.CurrentUser = new User(Thread.CurrentPrincipal as ClaimsPrincipal);
return null;
};
}
}