{"id":36860,"date":"2016-10-19T09:57:34","date_gmt":"2016-10-19T16:57:34","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/webdev\/?p=7755"},"modified":"2016-10-19T09:57:34","modified_gmt":"2016-10-19T16:57:34","slug":"modern-asp-net-web-forms-development-dependency-injection","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/dotnet\/modern-asp-net-web-forms-development-dependency-injection\/","title":{"rendered":"Modern ASP.NET Web Forms Development \u2013 Dependency Injection"},"content":{"rendered":"<p><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/aspnet\/wp-content\/uploads\/sites\/16\/2016\/10\/15012-illustration-of-a-blue-puzzle-piece-pv-300x300-1.png\" alt=\"Puzzle Piece\" class=\"alignright wp-image-7765 size-medium\" title=\"Courtesy of Free Stock Photos.biz\" width=\"300\" height=\"300\" \/>We\u2019ve all read various \u2018best practices\u2019 posts about this framework and that framework from expert developers in the community.\u00a0 They\u2019ll cover topics regarding how to make your application more maintainable and how to drive down the risk of maintenance in your applications.\u00a0 A common design recommendation is to structure your applications so that you compose the objects you are working on.\u00a0 The MVC framework is a good example that demonstrates this technique.\u00a0 You compose controller objects in MVC using constructor dependency injection so that the other facilities that our controllers need like loggers and database access are managed in other classes.\u00a0 What do we do if we\u2019re working on an ASP.NET Web Forms application?\u00a0 The Page object doesn\u2019t allow you to use constructor injection, so how do we work around this limitation?<\/p>\n<p>In this series of posts, we\u2019re going to look at how to modernize the development of your ASP.NET Web Forms application using existing features in innovative ways.\u00a0 Along the way, we will also learn how to reduce risk while maintaining our long standing applications. <!--more--><\/p>\n<h2>Dependency Injection Primer<\/h2>\n<p>For those unfamiliar with the concept, dependency injection is a class design strategy that relocates logic from one class to another. The second class is then injected into the first through either a property or a constructor argument.\u00a0 As an example, we can move all database management logic to a repository class or all log management tasks to a logger class.\u00a0 Our application code can be structured so that it focuses more on the application logic and only pulling in these concerns when needed.<\/p>\n<p>The following code demonstrates how you can inject a repository object that is defined by an interface, ICustomerRepository, into a Controller class for use in an MVC action method:<\/p>\n<pre><code>public interface ICustomerRepository {\n\n  IEnumerable&lt;Customer&gt; GetAll();\n\n  void Save(Customer c);\n\n  void Delete(int customerId);\n\n}\n\npublic class CustomerController : Controller {\n\n  public ICustomerRepository Repository { get; }\n\n  public CustomerController(ICustomerRepository repo) {\n\n    Repository = repo;\n\n  }\n\n  public IActionResult Index() {\n\n    return View(Repository.GetAll());\n\n  }\n\n}\n<\/code><\/pre>\n<p>An inversion of control container can be configured to automatically create the CustomerController and pass in an appropriate class that implements the ICustomerRepository interface.<\/p>\n<h2>Inversion of Control Containers<\/h2>\n<p>An Inversion of Control (IOC) container is an object in your code that manages the construction and object lifetime of objects that can be automatically injected into your classes for use.\u00a0 The code you are writing in the client classes, like the CustomerController above, calls into the classes that do most of the work for you.\u00a0 This inversion of control is facilitated by a container object.\u00a0 There are many containers available on NuGet.org for you to choose and add to your projects including:<\/p>\n<ul>\n<li><a href=\"http:\/\/www.nuget.org\/packages\/Castle.Windsor\/\">Castle Windsor<\/a><\/li>\n<li><a href=\"http:\/\/www.nuget.org\/packages\/Ninject\">Ninject<\/a><\/li>\n<li><a href=\"http:\/\/www.nuget.org\/packages\/structuremap\/\">StructureMap<\/a><\/li>\n<li><a href=\"http:\/\/www.nuget.org\/packages\/Autofac\/\">Autofac<\/a><\/li>\n<li><a href=\"http:\/\/www.nuget.org\/packages\/Unity\/\">Unity<\/a> <\/li>\n<\/ul>\n<p>For this article, we\u2019re going to work with Autofac and add its capabilities to a Web Forms application.<\/p>\n<h2>Web Forms and Dependencies<\/h2>\n<p>ASP.NET Web Forms has a long history of managing code in a collection of code-behind files named something like \u201cEditCustomer.aspx.cs\u201d that contain a partial class.\u00a0 This is the editable part of the class, as there is also a \u201cEditCustomer.designer.aspx.cs\u201d class that contains some generated code for the framework to use in managing the user-interface.\u00a0 If we would like to add dependencies to a page, say a reference to a CustomerRepository, we would typically create the CustomerRepository in the constructor of the EditCustomer class and then use it appropriately later in the class.<\/p>\n<p>This leads to some code management problems as we are then creating all of the dependent objects that we need to build and service our pages in the constructor of every page.<\/p>\n<p> If those objects change or if we wanted to use a different implementation of our interface, we\u2019re going to have a lot of code to update and test to ensure that it still functions the same way.\u00a0 We can start to simplify this problem by introducing an abstract BasePage concept to move some of these common concerns out into a reusable class that other pages can inherit from as well:<\/p>\n<p> We still have a page level concern for the CustomerRepository, but perhaps that\u2019s just a one-off problem for this page.\u00a0 Or maybe it isn\u2019t\u2026<\/p>\n<h2>Using a Container with Web Forms<\/h2>\n<p>Out of the box, you can\u2019t add parameters to any of your code-behind file\u2019s constructors.\u00a0 Not only that, but you have no way to plug in a container to set property values either.\u00a0 There is a way around this, and it involves using an <a href=\"https:\/\/support.microsoft.com\/en-us\/kb\/307996\">HttpModule<\/a>.\u00a0 An HttpModule is a class that can intercept events in the ASP.NET pipeline and interact with the input, output, and other processes managing the pipeline.\u00a0 In this case, we\u2019re going to write a simple HttpModule to inspect a Page object and inject required properties or constructor arguments as needed.<\/p>\n<p>In this sample, we\u2019re going to use Autofac to power our module.\u00a0 After installing the Autofac NuGet package, you can create a new class that implements the IHttpModule interface.\u00a0 The IHttpModule defines two methods that you must implement: Init and Dispose.\u00a0 We can use the Init method to listen for the PreRequestHandlerExecute event, the event that is triggered after a Page is constructed and before it begins any Page-level events processing.\u00a0 Let\u2019s also add a static constructor to configure the Autofac container:<\/p>\n<p> \nWith some additional reflection work inside of our event handler method, we can inject arguments for the constructor method and execute that constructor.\u00a0 This is a little strange, as we\u2019re used to executing constructor methods when calling \u201cnew FooClass()\u201d.\u00a0 In this case, the class is already instantiated and we are triggering the constructor method after the fact.<\/p>\n<h2>Structuring a Page<\/h2>\n<p>To set up a page to be injected, we can add public properties of types that Autofac knows how to handle or we can create a public constructor method that accepts arguments.\u00a0 If we use the constructor injection technique, we need to ensure that a protected argument-less constructor method is available for the framework to use when it creates the Page object.<\/p>\n<h2>Final Configuration<\/h2>\n<p>The last piece of configuration needed to ensure that our AutofacModule executes in the ASP.NET event pipeline is to add an entry appropriately to web.config:<\/p>\n<h2>Summary<\/h2>\n<p>We\u2019ve taught an old dog a new trick.\u00a0 This is sample code only, and may not be optimized for the best performance for your application in production.\u00a0 Some of the containers, <a href=\"http:\/\/docs.autofac.org\/en\/latest\/integration\/webforms.html\">like Autofac<\/a>, have their own modules available for you to use if you want to employ this technique with your application.\u00a0 Is this something that you find valuable?\u00a0 Should we make investments in this type of \u201cmodernization\u201d of the web forms templates and architecture?\u00a0 Let us know in the comments below. <span style=\"font-size: smaller\"><em>Thanks to MVP and Regional Director <a href=\"http:\/\/melvicorp.com\">Miguel Castro<\/a> for helping with the content of this article.<\/em><\/span><\/p>\n","protected":false},"excerpt":{"rendered":"<p>We\u2019ve all read various \u2018best practices\u2019 posts about this framework and that framework from expert developers in the community.\u00a0 They\u2019ll cover topics regarding how to make your application more maintainable and how to drive down the risk of maintenance in your applications.\u00a0 A common design recommendation is to structure your applications so that you compose [&hellip;]<\/p>\n","protected":false},"author":405,"featured_media":58792,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[197],"tags":[7422,7469],"class_list":["post-36860","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-aspnet","tag-asp-net-web-forms","tag-dependency-injection"],"acf":[],"blog_post_summary":"<p>We\u2019ve all read various \u2018best practices\u2019 posts about this framework and that framework from expert developers in the community.\u00a0 They\u2019ll cover topics regarding how to make your application more maintainable and how to drive down the risk of maintenance in your applications.\u00a0 A common design recommendation is to structure your applications so that you compose [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/posts\/36860","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\/405"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/comments?post=36860"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/posts\/36860\/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=36860"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/categories?post=36860"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/tags?post=36860"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}