How does Katana relate to ASP.NET 5 applications on IIS? - asp.net-mvc

I understand what OWIN is, and it is good, and generally that Katana is a Microsoft implementation the standard in terms of the ASP.NET ecosystem.
I've also read that Katana has only so far been designed to work with WebApi and SignalR, since these take no dependency System.Web. Cool.
However, a new ASP.NET MVC 5 project template does include some Katana stuff and references Microsoft.Owin.Host.SystemWeb and that's where I get confused.
"[SystemWeb] provides an OWIN server that runs in the ASP.NET request pipeline"
http://www.asp.net/aspnet/overview/owin-and-katana/an-overview-of-project-katana
So, on IIS, does a request off the wire flow through the Owin pipeline before being routed to a WebApi action? And MVC actions, too? At what point in the pipeline does Owin sit?
Look at the following code from ChallengeResult.cs the template:
public Task<HttpResponseMessage> ExecuteAsync(CancellationToken cancellationToken)
{
Request.GetOwinContext().Authentication.Challenge(LoginProvider);
HttpResponseMessage response = new HttpResponseMessage(HttpStatusCode.Unauthorized);
response.RequestMessage = Request;
return Task.FromResult(response);
}
This appears to be talking to two pipelines; it tells the authentication middleware on the Owin pipeline to send a 401 challenge and then also returns a 401 via the normal response messaging system.
I'm sure its simple, but I'm confused.

When you use Owin.Host.SystemWeb, you are injecting in the usual HttpModules pipeline an HttpModule meant to host the OWIN pipeline.
From the IIS/ASP.NET perspective, the OWIN pipeline will be executed in that context.
If you want to exercise finer control on what runs when, you can add specific stage markers that map to the traditional event sequence.
I recommend Prabu's article at:
http://www.asp.net/aspnet/overview/owin-and-katana/owin-middleware-in-the-iis-integrated-pipeline
It gives a very nice overview of the process.

Related

How does IIS server identify that request is mvc request?

In asp.net life cycle, on basis of the extension (.aspx), the request would be identified and handled by aspnet_isapi.dll and then httpapplication object is created followed by request and response objects and then request is processed by ProcessRequest() method.
I was going through mvc page life cycle
I have doubt about how the IIS server is able to identify the incoming request is MVC request?
Both the answers with some research I did, collectively resolves my question.
Step 1:
From the below mentioned article #1 (which I found during my research):
From a very high view, IIS is just a process which is listening on a
particular port (usually 80). Listening means it is ready to accept a
connections from clients on port 80. A very important thing to
remember is: IIS is not ASP.NET. This means that IIS doesn't know
anything about ASP.NET; it can work by itself.
Step 2:
Note: When we deploy and start the application in IIS, it would call Application_Start which would register the routes.
So, when MVC request comes to IIS, we are ready with our Route Table to handle this request.
Step 3:
As mentioned by #Babin, IIS doesn't know how to handle the request but because of ASP.NET framework, the request automatically goes to managed handlers.
Step 4:
As mentioned by #Rune, the request is intercepted by the UrlRoutingModule which in turn gets object of MvcRouteHandler class that will ultimately map to controller and action to handle the request.
Step 5:
As mentioned in one of SO question's comments:
If no routes match, the UrlRoutingModule object does nothing
and lets the request fall back to the regular ASP.NET or IIS request processing.
References:
I found good articles to read through and clear out the doubts in IIS request processing.
1) The following link has in-depth explanation for how IIS handles ASP.NET WebForms request:
http://www.codeproject.com/Articles/121096/Web-Server-and-ASP-NET-Application-Life-Cycle-in-D
2) The following links explains how IIS handles MVC requests using managed handlers:
http://blogs.msdn.com/b/tmarq/archive/2010/04/01/asp-net-4-0-enables-routing-of-extensionless-urls-without-impacting-static-requests.aspx
3) MVC Lifecycle:
http://pratiktips.blogspot.de/2012/08/the-magic-of-aspnet-mvc-model-binding.html
IIS 7+ can run in two pipeline modes: "Classic mode" and "Integrated mode". The latter mode means that ASP.NET sees all incoming requests and can handle / manipulate them.
If you are asking how ASP.NET knows to invoke MVC, that is described in step 4 of the diagram you linked to: The UrlRoutingModule matches the request against all registered routes. When using MVC, you will have registered a route with a MvcRouteHandler. From MSDN:
A MvcRouteHandler instance is registered with routing when you use the MapRoute method. When the MvcRouteHandler class is invoked, the class generates an MvcHandler instance using the current RequestContext instance. It then delegates control to the new MvcHandler instance
IIS doesn't know; ASP.NET knows via HTTP Handlers
Both WebForms and MVC are built on top of ASP.NET, and both use HTTP Handlers to deal with per-request execution:
WebForms has .aspx files mapped to the PageHandlerFactory: PageHandlerFactory implements IHttpHandlerFactory::GetHandler() returns HttpHandler
MVC integrates into the Routing infrastructure as an IRouteHandler implementation. Routes is notified of requests via the UrlRoutingHandler URLRoutingHanlder implements IHttpHandler. ASP.NET MVC is just a custom handler added to the ASP.NET pipeline.
Below is MVC 4.0 & ASP.NET 4.0 onwards These rules can be defined at any level in IIS. Most MVC applications define the handlers at the application level in the web.config file
<handler>
<add name="ExtensionlessUrlHandler-ISAPI-4.0_32bit"/>
<add name="ExtensionlessUrlHandler-ISAPI-4.0_64bit"/>
<add name="ExtensionlessUrlHandler-Integrated-4.0"/>
</handlers>

asp.net mvc5 forms authentication, how does OWIN come in to place?

I started a new MVC5 project and am implementing forms authentication (which I used to do using custom code to check the user credentials and the FormsAuthentication object to login and logoff).
Now I've read that the identity model has changed, but I saw this line of code in the generated code:
private IAuthenticationManager AuthenticationManager
{
get
{
return HttpContext.GetOwinContext().Authentication;
}
}
Because later on the login is done on that object
( AuthenticationManager.SignIn)
I want to make sure I've got the right object.
I've read that OWIN is about decoupling ASP.NET from IIS, so I'm not sure why I need this GetOwinContext, because I am not using OWIN (at least I think)?
ASP.NET MVC 5 is using regular IIS Integrated Pipeline to operate which involves a lot of steps such as AuthenticateRequest, PostAuthenticateRequests and so on. FormsAuthenticationModule is responsible for management of Forms Authentication process which involves decryption / extracting user information from cookie and it is integrated in several of those steps.
Now, when it comes to part with OWIN, it is operating on the completely different approach, which will be the only approach in the nearby future, so you might consider dropping Forms authentication completely because at this point, there are several better ways to implement your security.
If you go with IIS Integrated Pipeline and want to skip all the OWIN thing (which I strongly recommend against), you might check classes ClaimsAuthenticationManager, ClaimsAuthorizationManager and SessionAuthenticationModule. These effectively replace RoleManagerModule and FormsAuthenticationModule in order to allow Claims-Based Access Control, which is based on concept of Claims, which again in turn are used for all modern authentication protocols such as WS-Federation, OAuth2, etc.
Back to OWIN part - OWIN has it's own pipeline, which with usage of some "bridge" assemblies can hook up on IIS events as well, meaning that you have OWIN web server running in the background (Microsoft.Owin.SystemWeb) and also System.Web that is leveraging IIS for MVC purposes.
So when you use OWIN authentication in MVC 5, you're basically still using IIS Integrating Pipeline for MVC, but you're using OWIN middleware for security, which is part of OWIN pipeline.
Now in order to access that OWIN pipeline, you need to do GetOwinContext. OwinContext is OWIN version of previously used HttpContext, except on the base level it is quite different. OWIN middleware operates exclusively on OwinContext (IOwinContext), so to use middleware you need to access the context, since context has information that is required by the middleware.
This is unfortunately quite complex, but I would strongly suggest to you to start reading about OWIN and Katana, and pay attention on vNext as well, as Forms Authentication is right now pretty much obsolete, and will definitely stop being supported with vNext so you might start building an application now that will require a lot of refactoring later.

adopting action filters for both MVC and web Api controllers

as you know MVC and web api action filters uses different namespaces for their filters:
in web api:
public override void OnActionExecuted(HttpActionExecutedContext actionExecutedContext)
HttpActionExecutedContext is in system.web.http.filters
in MVC:
public override void OnActionExecuted(ActionExecutedContext actionExecutedContext)
ActionExecutedContext is in system.web.mvc
I want to have one filters for all of my controllers whenever web api or MVC.
so how can I solve this issue?
MVC and Web API are different frameworks and where they converge is the hosting part. At this point in time, MVC and Web API can be web-hosted (IIS + ASP.NET pipeline) and hence you can write an IIS module to do what you want.
OWIN middleware could be a better option but unfortunately MVC cannot be OWIN-hosted at this point. However, you can use a stage marker to run an OWIN middleware in ASP.NET pipeline at the stage you want but as far as I can see, PipelineStage enum has PreHandlerExecute as the last stage. This means you can do something like OnActionExecuting but not OnActionExecuted.

MVC5 Where is Principal Read From Cookie?

Where and when is the HttpContext.Current.User read from the HttpContext.Current.Request.Cookies ?
I have started looking at the ASP.NET MVC 5 source code http://aspnetwebstack.codeplex.com/ and couldn't figure out where principal was first set.
If you are using federated authentication, it is the SessionAuthenticationModule that uses its configured CookieHandler to deserialize a cookie into a SessionSecurityToken. It then uses the token to create a ClaimsPrincipal for the user. This ClaimsPrincipal is then used to set to the Thread.CurrentPrincipal and HttpContext.User properties. This process takes place in the AuthenticateRequest and PostAuthenticateRequest steps of the ASP.NET pipeline. Since it is done in the ASP.NET pipeline, I doubt you will find it in the MVC source code.
You can find more info on the SessionAuthenticationModule here on MSDN.
This is a great post on FormsAuth and FedAuth. It explains how all the bits fit together in the ASP.NET pipeline.
I am looking in the wrong spot. Authentication is now using the OWIN middleware. This blog is useful. The source code is in a project called katana. The source code is here. And here is the official asp.net blog post
In short. Owins is new way of processing the http request. The owins request is passed down a pipeline of 'middle ware' which handles the request. The CookieAuthenticationMiddleware from project katana (above) is responsible for decoding the authentication cookie.

Design of a web application with ServiceStack

After getting an advice about using ServiceStack for my asp.net MVC website
(Maintaining state in Asp.Net MVC website), I started implementing it in my project - but some stuff is still unclear for me.
Currently I have two projects: one is the asp.net MVC project and the other is the BL project (a class library that holds all the business logic).
All controllers in the MVC project make calls to classes/functions in the BL project.
For now, the mvc project loads the BL's DLL, but in the future when the website will grow, the BL's project will run on separate machines.
I would like to use ServiceStack for session management/caching and authentication (which both of them usually depended on each other).
My questions:
1) Is it possible to use only these two features without the functionality of message based web service? ServiceStack need to be initialized, and it throws me an error when initialized twice (in both projects).
2) Is it possible to split the implementation of ServiceStack between the two projects? I would like to maintain the process of authentication in the BL project using the ServiceStack's authentication providers, but handle all the UI/cookies by myself (or with the help of ServiceStack) in the mvc project.
3) I would like to use ServiceStack's caching in the BL project, but I guess that I still need to maintain some session cookies to receive the session id. What is the right way to do it? Are there any built-in helper functions for this purpose?
Thanks in advance!
1) Is it possible to use only these two features without the functionality of message based web service? ServiceStack need to be initialized, and it throws me an error when initialized twice (in both projects).
If you install the latest ServiceStack.Mvc NuGet package you will get the base ServiceStackController which is an MVC Controller providing convenient access to ServiceStack's built-in providers. Although you still need to auto-wire your controllers with the dependencies it needs, e.g. an injected ICacheClient.
Although even if you're not using ServiceStack's WebFramework, having an AppHost is a convenient place to register your dependencies. ServiceStack is triggered by ASP.NET's IHttpHandler mappings specified in the Web.config, so if you don't have any mappings specified ServiceStack is never able to be called externally, but the registered dependencies are still able to be accessed internally with:
var cache = AppHost.Resolve<ICacheClient>(); //Get ICacheClient for SS IOC
2) Is it possible to split the implementation of ServiceStack between the two projects?
If you do have an AppHost, you cannot have more than one instance in a host project (by design) since an AppHost should be analogous to a host project where all your service dependencies should be registered and settings configured that apply to your entire web application or service.
You can however split the implementation of your services across multiple assemblies and have ServiceStack scan them all by specifying them in your AppHostBase constructor, e.g:
public class AppHost : AppHostBase
{
public AppHost() : base("My Service",
typeof(AServiceInDll1).Assembly, typeof(AServiceInDll2).Assembly/*, etc.*/){}
}
2) cont. I would like to maintain the process of authentication in the BL project using the ServiceStack's authentication providers, but handle all the UI/cookies by myself (or with the help of ServiceStack) in the mvc project.
Look at the ServiceStack.UseCases CustomAuthenticationMvc example project for an example of using MVC but authenticating with ServiceStack.
3) I would like to use ServiceStack's caching in the BL project, but I guess that I still need to maintain some session cookies to receive the session id. What is the right way to do it? Are there any built-in helper functions for this purpose?
You can use any of ServiceStack's Caching providers just like any other C# class, i.e. have your Business Logic binded to ICacheClient and inject the concrete implementation in your IOC.
For sessions you can use the base.SessionAs<T> method in the ServiceStack.Mvc ServiceStackController to access the session. To Save back the session you can use the IHttpRequest.SaveSession() extension methods. Although both these methods require the ASP.NET context (it uses ASP.NET's HttpContext singleton if not provided) to work since it relies on ServiceStack's ss-id/ss-pid cookies that are automatically instructed to be added on the client (by the server) whenever you access the Session.
If you don't want your business logic services to have a dependency on ASP.NET's System.Web I recommend accessing and saving the session to be done in your controllers and passed to your business logic.
I recommend reading the Sessions Wiki Page for more background info on how ServiceStack's sessions work.
Integration of ASP.NET Context between ServiceStack and ASP.NET or MVC
I'll add this info since it's useful for anyone doing advanced integration between ServiceStack and ASP.NET or MVC as some of ServiceStack's extension methods rely on these built-in types.
You can create a ServiceStack IHttpRequest or IHttpResponse (within any HTTP/Controller request) with:
var ssHttpRequest = System.Web.HttpContext.Current.Request.ToRequest();
var ssHttpResponse = System.Web.HttpContext.Current.Response.ToResponse();
Finally you can create a complete request context (that encapsulates both a IHttpRequest and IHttpResponse) with:
var ssRequestContext = System.Web.HttpContext.Current.ToRequestContext();
Not sure I fully grasp your questions and how you would like to split the projects across multiple servers. I'll try my best to answer your questions...
Is it possible to use only these two features without the functionality of message based web service? ServiceStack need to be initialized, and it throws me an error when initialized twice
It seems like you're trying to run 2 instances of ServiceStack (maybe even 2 websites) within one solution (one in your web project and once in your BL layer). I don't think that's possible. Your BL layer can share ServiceStack libraries and you can configure (within AppHost.Configure method) those in your web project that references your BL project.
Is it possible to split the implementation of ServiceStack between the two projects?
I think the answer is yes, but you would have have one instance of ServiceStack used by both the projects. This would share the Session state across the projects. There might be a way to have two projects with there own instances of ServiceStack...see https://github.com/ServiceStack/ServiceStack/wiki/Self-hosting.
I would like to use ServiceStack's caching in the BL project, but I guess that I still need to maintain some session cookies to receive the session id.
If ServiceStack is being used across both projects you can access all session data in UserSession (https://github.com/ServiceStack/ServiceStack/wiki/Sessions). If you MVC Controllers inherit from ServiceStackController you can use SessionFeature.GetSessionId() to get the session Id. In your ServiceStack Service (classes that implement Service) you can get the session data from using base.Session.
Hope this helps.

Resources