📜 ⬆️ ⬇️

Implementing a client-server web-based application using OWIN

Introduction


On Habré, the topic of OWIN has been touched many times, but so far, questions about the implementation of applications and components using OWIN still surface. In this publication, I will start with the standard Visual Studio 2013 template and demonstrate the implementation of the application architecture. I will also show how to use a single DI container - both for MVC and for WebApi in a single project.

Configuring WebApi


In the standard VS2013 template, the WebApi configuration is performed in global.asax. Let's transfer it to the Startup class.

Now, register the OWIN module of WebApi. To do this, we need to install the appropriate NuGet package. Open the Package Manager Console and enter:

PM> Install-Package Microsoft.AspNet.WebApi.Owin 

')
After installing the package, we can register OWIN Middleware for WebApi.

 var apiConfig = ConfigureWebApi(); ConfigureDependencyInjection(app, apiConfig); app.UseWebApi(apiConfig); 


We will talk further about the “ConfigureDependencyInjection” method.

Configuring a DI Container


In this example, I use the Autofac DI container, since it already has the necessary implementations of the DependencyResolver classes for WebApi and MVC, as well as extension methods for integration with OWIN.

Install the necessary modules:

 PM> Install-Package Autofac.Mvc5 PM> Install-Package Autofac.WebApi2.Owin 


To integrate MVC and Owin, you need to install another package:

 PM> Install-Package Autofac.Mvc5.Owin 


As I want to demonstrate using a single container for WebApi and MVC, container initialization will be located in the OWIN configuration class.

 private void ConfigureDependencyInjection(IAppBuilder app, HttpConfiguration apiConfig) { var builder = new ContainerBuilder(); Assembly executingAssembly = Assembly.GetExecutingAssembly(); builder.RegisterApiControllers(executingAssembly); builder.RegisterControllers(executingAssembly); RegisterComponents(builder); var container = builder.Build(); app.UseAutofacMiddleware(container); var apiResolver = new AutofacWebApiDependencyResolver(container); apiConfig.DependencyResolver = apiResolver; app.UseAutofacWebApi(apiConfig); var mvcResolver = new AutofacDependencyResolver(container); DependencyResolver.SetResolver(mvcResolver); app.UseAutofacMvc(); } 


With this code, everything is very simple. First we create a ContainerBuilder and register our controllers in it, then register the services. After that we create a container and set it as a DependencyResolver for WebApi and Mvc.

Here it is necessary to pay attention to the app.UseAutofacMvc (); line. Calling this method allows you to extend LifetimeScope objects so that they are involved in MVC.

Implementation of the application security component on the example of AspNet Identity


Registering components

AspNet Identity packages are already installed in the standard application template, but if you started with an empty template, you need to install the following packages:

 PM> Install-Package Microsoft.AspNet.Identity.Owin PM> Install-Package Microsoft.AspNet.Identity.EntityFramework 


To implement AspNet Identity security, we need to register four classes:



There are no problems with registering the SignInManager <ApplicationUser, string> and IUserStore components, the code for their registration is shown below.

 private void RegisterComponents(ContainerBuilder builder) { builder.RegisterType<ApplicationDbContext>().As<DbContext>().InstancePerRequest(); builder.RegisterType<ApplicationSignInManager>().As<SignInManager<ApplicationUser, string>>().InstancePerRequest(); builder.RegisterType<UserStore<ApplicationUser>>().As<IUserStore<ApplicationUser>>().InstancePerRequest(); } 


It is worth noting that as IUserStore I used the AspNet.Identity.EntityFramework class library, so the ApplicationDbContext class is present in the registration.

Next you need to register the IAuthenticationManager. It should be noted here that the implementation of the IAuthenticationManager interface does not have an open constructor, so we set the factory method.

 builder.Register<IAuthenticationManager>((c, p) => c.Resolve<IOwinContext>().Authentication).InstancePerRequest(); 


The IOwinContext.Authentication property is actually a factory method and provides us with a new AuthenticationManager on every call.

Now you need to register the class UserManager. The constructor of this class is of no particular interest, but the factory method “Create”, which is responsible for the creation and configuration of this class, is defined later in this class.

Transfer the creation and configuration of the class to the factory method autofac to keep the entire configuration together. In this case, we will face a small problem. The “Create” method takes IdentityFactoryOptions as one of the arguments. We cannot create IdentityFactoryOptions ourselves. Fortunately, there is an IAppBuilder.GetDataProtectionProvider () method, located in the Microsoft.Owin.Security.DataProtection namespace.

 var dataProtectionProvider = app.GetDataProtectionProvider(); builder.Register<UserManager<ApplicationUser>>((c, p) => BuildUserManager(c, p, dataProtectionProvider)); 


Business logic

Now you can use our DI container to implement the application logic. If we look in AccountController, we will see the following lines there:

 HttpContext.GetOwinContext().Get<ApplicationSignInManager>(); HttpContext.GetOwinContext().GetUserManager<ApplicationUserManager>(); HttpContext.GetOwinContext().Authentication; 


Using these lines, objects of the UserManager, SignInManager, and IAuthenticationManager classes are permitted, respectively. This approach is offered by the AspNet Identity library. It does not suit us for several reasons, the most obvious of them are:

  1. Using ServiceLocator does not allow us to control dependencies within a class.
  2. The appearance of the second DI container, which directly depends on the AspNet Identity.


Remove the UserManager, SignInManager, AuthenticationManager properties and add the _userManager and _authenticationManager fields initialization through the constructor. Also remove the constructor without parameters. Similarly, fix ManageController. In the Identity configuration method, we remove the rows that register our classes in OwinContext.

  app.CreatePerOwinContext(ApplicationDbContext.Create); app.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.Create); app.CreatePerOwinContext<ApplicationSignInManager>(ApplicationSignInManager.Create); 


Now you can remove the extra packages responsible for integrating WebApi with IIS.

 Uninstall-Package Microsoft.AspNet.WebApi Uninstall-Package Microsoft.AspNet.WebApi.WebHost 


Conclusion


In this publication, we learned how to implement the modular structure of an ASP.Net application with registering components as an OWIN Middleware, register a single Dependency Injection container for ASP.Net MVC and WebApi and implement an application security module with it.

The full application code is available via the link on GitHub .

Source: https://habr.com/ru/post/237773/


All Articles