{"action":"created","comment":{"url":"https://api.github.com/repos/dotnet/training-tutorials/pulls/comments/86170449","pull_request_review_id":6836400,"id":86170449,"diff_hunk":"@@ -1,20 +1,145 @@\n # Injecting Dependencies into Controllers\n-by [Steve Smith](http://deviq.com/me/steve-smith)\n+by [James Chambers](http://jameschambers.com)\n \n #### Sample Files\n Download a ZIP containing this tutorial's sample files:\n-- [Initial Version] - Use this as a starting point when following along with the tutorial yourself\n-- [Completed Version] - Includes the completed versions of all samples\n+- [Completed Version (Pending)] - Includes the completed versions of all MVC tutorials\n \n-See the [Issue](https://github.com/dotnet/training-tutorials/issues/63) to claim this lesson and/or view what should be included in it.\n+## Using Dependencies in Your Controllers\n+Through the various lessons in this tutorial series we have talked about the responsibilities of the different types of components of - and the role that the MVC framework has in - your app. While taking a pragmatic approach will pay dividends and help you deliver software, it's also important to consider the things that will make you successful down the road in managing, maintaining and adding features to your software.\n \n-## First Header\n+A good example of a place for this is in your controllers. When a controller is created, you may be tempted to add in the code that initializes the dependencies in the controller's constructor, which would look something like the following:\n \n-Start the lesson here.\n+```c#\n \n-...\n+public class PersonController : Controller\n+{\n+    private PersonService _personService;\n \n+    public PersonController()\n+    {\n+        _personService = new PersonService();\n+    }\n+}\n+``` \n+\n+This seems harmless enough; the `PersonController` needs access to the facilities of `PersonService` and so it creates an instance when it is being initialized. However there are a couple of caveats to this approach.  What if `PersonService` now needs access to the database, and you'll need to provide it an instace of a `DbContext`?  One approach might now be to do the following:\n+\n+```c#\n+public class PersonController : Controller\n+{\n+    private PersonService _personService;\n+\n+    public PersonController()\n+    {\n+        var dbContext = new ApplicationDbContext();\n+        _personService = new PersonService(dbContext);\n+    }\n+}\n+```  \n+\n+Okay so far, right? Except, now how will you test this? The controller is now essentially responsible for providing a way to connect to the database, so any unit test is now going to be difficult to implement without talking to a database. What if we need to know an environment-specific connection string?  Furthermore, if the `PersonService` is  refined to also require an `AddressVerificationService` you'll now need to update your `PersonController` constructor to properly configure an instance of it when you adjust your `PersonService`. It doesn't take long before we end up with a constructor that looks like this:\n+\n+```c#\n+public class PersonController : Controller\n+{\n+    private PersonService _personService;\n+\n+    public PersonController()\n+    {\n+        var connString = Settings.ConnectionStrings[\"application\"];\n+        var endpoint = Settings.AddressVerificationServiceEndpoint;\n+        var dbContext = new ApplicationDbContext(connString);\n+        var addressService = new AddressVerificationService(endpoint);\n+        \n+        // ... and on ...\n+        \n+        _personService = new PersonService(dbContext, addressService);\n+    }\n+}\n+```  \n+\n+This spiralling effect is why we tend to practice the [Single Responsibility Principle](https://en.wikipedia.org/wiki/Single_responsibility_principle) and avoid leaking dependencies across and between  classes: we want as few reasons as possible to have to change our code. \n+\n+Do we care if the database connection is to a real database or not for the purpose of, say, a unit test? Do we want to know in this (and every) class how to setup the database connection? Do we want the responsibility of creating the service? \"Probably not,\" is the likely answer to all of these.\n+\n+If our controller _needs_ to access the `PersonService` our only other option is to force whichever code is creating an instace of the `PersonController` to provide it to us. This is a pattern known as [Inversion of Control](https://en.wikipedia.org/wiki/Inversion_of_control), and it allows us to push the creation of dependencies outside of our controller proper.  It also gives us the beneficial side effect of _explicitly_ stating our dependencies, for no code can instantiate our class without providing them to us through our public constructor.  \n+\n+## The Explicit Dependencies Principle \n+Let's flip that code on its head now to see what that will look like, requiring our dependencies to be passed in:\n+\n+```c#\n+public class PersonController : Controller\n+{\n+    private IPersonService _personService;","path":"content/asp.net/getting-started/controller-dependencies.md","position":81,"original_position":81,"commit_id":"65b21d1b011be0c168f5288da80fd2f184c864d0","original_commit_id":"65b21d1b011be0c168f5288da80fd2f184c864d0","user":{"login":"ardalis","id":782127,"avatar_url":"https://avatars.githubusercontent.com/u/782127?v=3","gravatar_id":"","url":"https://api.github.com/users/ardalis","html_url":"https://github.com/ardalis","followers_url":"https://api.github.com/users/ardalis/followers","following_url":"https://api.github.com/users/ardalis/following{/other_user}","gists_url":"https://api.github.com/users/ardalis/gists{/gist_id}","starred_url":"https://api.github.com/users/ardalis/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ardalis/subscriptions","organizations_url":"https://api.github.com/users/ardalis/orgs","repos_url":"https://api.github.com/users/ardalis/repos","events_url":"https://api.github.com/users/ardalis/events{/privacy}","received_events_url":"https://api.github.com/users/ardalis/received_events","type":"User","site_admin":false},"body":"make this readonly?","created_at":"2016-11-02T15:34:50Z","updated_at":"2016-11-02T15:34:50Z","html_url":"https://github.com/dotnet/training-tutorials/pull/164#discussion_r86170449","pull_request_url":"https://api.github.com/repos/dotnet/training-tutorials/pulls/164","_links":{"self":{"href":"https://api.github.com/repos/dotnet/training-tutorials/pulls/comments/86170449"},"html":{"href":"https://github.com/dotnet/training-tutorials/pull/164#discussion_r86170449"},"pull_request":{"href":"https://api.github.com/repos/dotnet/training-tutorials/pulls/164"}}},"pull_request":{"url":"https://api.github.com/repos/dotnet/training-tutorials/pulls/164","id":83943681,"html_url":"https://github.com/dotnet/training-tutorials/pull/164","diff_url":"https://github.com/dotnet/training-tutorials/pull/164.diff","patch_url":"https://github.com/dotnet/training-tutorials/pull/164.patch","issue_url":"https://api.github.com/repos/dotnet/training-tutorials/issues/164","number":164,"state":"open","locked":false,"title":"Controller dependencies","user":{"login":"MisterJames","id":1197383,"avatar_url":"https://avatars.githubusercontent.com/u/1197383?v=3","gravatar_id":"","url":"https://api.github.com/users/MisterJames","html_url":"https://github.com/MisterJames","followers_url":"https://api.github.com/users/MisterJames/followers","following_url":"https://api.github.com/users/MisterJames/following{/other_user}","gists_url":"https://api.github.com/users/MisterJames/gists{/gist_id}","starred_url":"https://api.github.com/users/MisterJames/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/MisterJames/subscriptions","organizations_url":"https://api.github.com/users/MisterJames/orgs","repos_url":"https://api.github.com/users/MisterJames/repos","events_url":"https://api.github.com/users/MisterJames/events{/privacy}","received_events_url":"https://api.github.com/users/MisterJames/received_events","type":"User","site_admin":false},"body":null,"created_at":"2016-09-05T02:38:20Z","updated_at":"2016-11-02T15:37:35Z","closed_at":null,"merged_at":null,"merge_commit_sha":"bb520db8aa51f1983a60a78bc7b0250424e332df","assignee":null,"assignees":[],"milestone":null,"commits_url":"https://api.github.com/repos/dotnet/training-tutorials/pulls/164/commits","review_comments_url":"https://api.github.com/repos/dotnet/training-tutorials/pulls/164/comments","review_comment_url":"https://api.github.com/repos/dotnet/training-tutorials/pulls/comments{/number}","comments_url":"https://api.github.com/repos/dotnet/training-tutorials/issues/164/comments","statuses_url":"https://api.github.com/repos/dotnet/training-tutorials/statuses/65b21d1b011be0c168f5288da80fd2f184c864d0","head":{"label":"MisterJames:ftr/controller-dependencies","ref":"ftr/controller-dependencies","sha":"65b21d1b011be0c168f5288da80fd2f184c864d0","user":{"login":"MisterJames","id":1197383,"avatar_url":"https://avatars.githubusercontent.com/u/1197383?v=3","gravatar_id":"","url":"https://api.github.com/users/MisterJames","html_url":"https://github.com/MisterJames","followers_url":"https://api.github.com/users/MisterJames/followers","following_url":"https://api.github.com/users/MisterJames/following{/other_user}","gists_url":"https://api.github.com/users/MisterJames/gists{/gist_id}","starred_url":"https://api.github.com/users/MisterJames/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/MisterJames/subscriptions","organizations_url":"https://api.github.com/users/MisterJames/orgs","repos_url":"https://api.github.com/users/MisterJames/repos","events_url":"https://api.github.com/users/MisterJames/events{/privacy}","received_events_url":"https://api.github.com/users/MisterJames/received_events","type":"User","site_admin":false},"repo":{"id":63390865,"name":"training-tutorials","full_name":"MisterJames/training-tutorials","owner":{"login":"MisterJames","id":1197383,"avatar_url":"https://avatars.githubusercontent.com/u/1197383?v=3","gravatar_id":"","url":"https://api.github.com/users/MisterJames","html_url":"https://github.com/MisterJames","followers_url":"https://api.github.com/users/MisterJames/followers","following_url":"https://api.github.com/users/MisterJames/following{/other_user}","gists_url":"https://api.github.com/users/MisterJames/gists{/gist_id}","starred_url":"https://api.github.com/users/MisterJames/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/MisterJames/subscriptions","organizations_url":"https://api.github.com/users/MisterJames/orgs","repos_url":"https://api.github.com/users/MisterJames/repos","events_url":"https://api.github.com/users/MisterJames/events{/privacy}","received_events_url":"https://api.github.com/users/MisterJames/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/MisterJames/training-tutorials","description":"Getting started tutorials for C# and ASP.NET","fork":true,"url":"https://api.github.com/repos/MisterJames/training-tutorials","forks_url":"https://api.github.com/repos/MisterJames/training-tutorials/forks","keys_url":"https://api.github.com/repos/MisterJames/training-tutorials/keys{/key_id}","collaborators_url":"https://api.github.com/repos/MisterJames/training-tutorials/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/MisterJames/training-tutorials/teams","hooks_url":"https://api.github.com/repos/MisterJames/training-tutorials/hooks","issue_events_url":"https://api.github.com/repos/MisterJames/training-tutorials/issues/events{/number}","events_url":"https://api.github.com/repos/MisterJames/training-tutorials/events","assignees_url":"https://api.github.com/repos/MisterJames/training-tutorials/assignees{/user}","branches_url":"https://api.github.com/repos/MisterJames/training-tutorials/branches{/branch}","tags_url":"https://api.github.com/repos/MisterJames/training-tutorials/tags","blobs_url":"https://api.github.com/repos/MisterJames/training-tutorials/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/MisterJames/training-tutorials/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/MisterJames/training-tutorials/git/refs{/sha}","trees_url":"https://api.github.com/repos/MisterJames/training-tutorials/git/trees{/sha}","statuses_url":"https://api.github.com/repos/MisterJames/training-tutorials/statuses/{sha}","languages_url":"https://api.github.com/repos/MisterJames/training-tutorials/languages","stargazers_url":"https://api.github.com/repos/MisterJames/training-tutorials/stargazers","contributors_url":"https://api.github.com/repos/MisterJames/training-tutorials/contributors","subscribers_url":"https://api.github.com/repos/MisterJames/training-tutorials/subscribers","subscription_url":"https://api.github.com/repos/MisterJames/training-tutorials/subscription","commits_url":"https://api.github.com/repos/MisterJames/training-tutorials/commits{/sha}","git_commits_url":"https://api.github.com/repos/MisterJames/training-tutorials/git/commits{/sha}","comments_url":"https://api.github.com/repos/MisterJames/training-tutorials/comments{/number}","issue_comment_url":"https://api.github.com/repos/MisterJames/training-tutorials/issues/comments{/number}","contents_url":"https://api.github.com/repos/MisterJames/training-tutorials/contents/{+path}","compare_url":"https://api.github.com/repos/MisterJames/training-tutorials/compare/{base}...{head}","merges_url":"https://api.github.com/repos/MisterJames/training-tutorials/merges","archive_url":"https://api.github.com/repos/MisterJames/training-tutorials/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/MisterJames/training-tutorials/downloads","issues_url":"https://api.github.com/repos/MisterJames/training-tutorials/issues{/number}","pulls_url":"https://api.github.com/repos/MisterJames/training-tutorials/pulls{/number}","milestones_url":"https://api.github.com/repos/MisterJames/training-tutorials/milestones{/number}","notifications_url":"https://api.github.com/repos/MisterJames/training-tutorials/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/MisterJames/training-tutorials/labels{/name}","releases_url":"https://api.github.com/repos/MisterJames/training-tutorials/releases{/id}","deployments_url":"https://api.github.com/repos/MisterJames/training-tutorials/deployments","created_at":"2016-07-15T04:10:08Z","updated_at":"2016-07-13T15:22:49Z","pushed_at":"2016-09-05T02:38:20Z","git_url":"git://github.com/MisterJames/training-tutorials.git","ssh_url":"git@github.com:MisterJames/training-tutorials.git","clone_url":"https://github.com/MisterJames/training-tutorials.git","svn_url":"https://github.com/MisterJames/training-tutorials","homepage":"http://dot.net/","size":852,"stargazers_count":0,"watchers_count":0,"language":null,"has_issues":false,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":0,"mirror_url":null,"open_issues_count":0,"forks":0,"open_issues":0,"watchers":0,"default_branch":"master"}},"base":{"label":"dotnet:master","ref":"master","sha":"db02e749b17a278e47641d73dfa74fef8c33267d","user":{"login":"dotnet","id":9141961,"avatar_url":"https://avatars.githubusercontent.com/u/9141961?v=3","gravatar_id":"","url":"https://api.github.com/users/dotnet","html_url":"https://github.com/dotnet","followers_url":"https://api.github.com/users/dotnet/followers","following_url":"https://api.github.com/users/dotnet/following{/other_user}","gists_url":"https://api.github.com/users/dotnet/gists{/gist_id}","starred_url":"https://api.github.com/users/dotnet/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/dotnet/subscriptions","organizations_url":"https://api.github.com/users/dotnet/orgs","repos_url":"https://api.github.com/users/dotnet/repos","events_url":"https://api.github.com/users/dotnet/events{/privacy}","received_events_url":"https://api.github.com/users/dotnet/received_events","type":"Organization","site_admin":false},"repo":{"id":59598094,"name":"training-tutorials","full_name":"dotnet/training-tutorials","owner":{"login":"dotnet","id":9141961,"avatar_url":"https://avatars.githubusercontent.com/u/9141961?v=3","gravatar_id":"","url":"https://api.github.com/users/dotnet","html_url":"https://github.com/dotnet","followers_url":"https://api.github.com/users/dotnet/followers","following_url":"https://api.github.com/users/dotnet/following{/other_user}","gists_url":"https://api.github.com/users/dotnet/gists{/gist_id}","starred_url":"https://api.github.com/users/dotnet/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/dotnet/subscriptions","organizations_url":"https://api.github.com/users/dotnet/orgs","repos_url":"https://api.github.com/users/dotnet/repos","events_url":"https://api.github.com/users/dotnet/events{/privacy}","received_events_url":"https://api.github.com/users/dotnet/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/dotnet/training-tutorials","description":"Getting started tutorials for C# and ASP.NET","fork":false,"url":"https://api.github.com/repos/dotnet/training-tutorials","forks_url":"https://api.github.com/repos/dotnet/training-tutorials/forks","keys_url":"https://api.github.com/repos/dotnet/training-tutorials/keys{/key_id}","collaborators_url":"https://api.github.com/repos/dotnet/training-tutorials/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/dotnet/training-tutorials/teams","hooks_url":"https://api.github.com/repos/dotnet/training-tutorials/hooks","issue_events_url":"https://api.github.com/repos/dotnet/training-tutorials/issues/events{/number}","events_url":"https://api.github.com/repos/dotnet/training-tutorials/events","assignees_url":"https://api.github.com/repos/dotnet/training-tutorials/assignees{/user}","branches_url":"https://api.github.com/repos/dotnet/training-tutorials/branches{/branch}","tags_url":"https://api.github.com/repos/dotnet/training-tutorials/tags","blobs_url":"https://api.github.com/repos/dotnet/training-tutorials/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/dotnet/training-tutorials/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/dotnet/training-tutorials/git/refs{/sha}","trees_url":"https://api.github.com/repos/dotnet/training-tutorials/git/trees{/sha}","statuses_url":"https://api.github.com/repos/dotnet/training-tutorials/statuses/{sha}","languages_url":"https://api.github.com/repos/dotnet/training-tutorials/languages","stargazers_url":"https://api.github.com/repos/dotnet/training-tutorials/stargazers","contributors_url":"https://api.github.com/repos/dotnet/training-tutorials/contributors","subscribers_url":"https://api.github.com/repos/dotnet/training-tutorials/subscribers","subscription_url":"https://api.github.com/repos/dotnet/training-tutorials/subscription","commits_url":"https://api.github.com/repos/dotnet/training-tutorials/commits{/sha}","git_commits_url":"https://api.github.com/repos/dotnet/training-tutorials/git/commits{/sha}","comments_url":"https://api.github.com/repos/dotnet/training-tutorials/comments{/number}","issue_comment_url":"https://api.github.com/repos/dotnet/training-tutorials/issues/comments{/number}","contents_url":"https://api.github.com/repos/dotnet/training-tutorials/contents/{+path}","compare_url":"https://api.github.com/repos/dotnet/training-tutorials/compare/{base}...{head}","merges_url":"https://api.github.com/repos/dotnet/training-tutorials/merges","archive_url":"https://api.github.com/repos/dotnet/training-tutorials/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/dotnet/training-tutorials/downloads","issues_url":"https://api.github.com/repos/dotnet/training-tutorials/issues{/number}","pulls_url":"https://api.github.com/repos/dotnet/training-tutorials/pulls{/number}","milestones_url":"https://api.github.com/repos/dotnet/training-tutorials/milestones{/number}","notifications_url":"https://api.github.com/repos/dotnet/training-tutorials/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/dotnet/training-tutorials/labels{/name}","releases_url":"https://api.github.com/repos/dotnet/training-tutorials/releases{/id}","deployments_url":"https://api.github.com/repos/dotnet/training-tutorials/deployments","created_at":"2016-05-24T18:25:52Z","updated_at":"2016-11-01T15:51:47Z","pushed_at":"2016-11-02T15:13:11Z","git_url":"git://github.com/dotnet/training-tutorials.git","ssh_url":"git@github.com:dotnet/training-tutorials.git","clone_url":"https://github.com/dotnet/training-tutorials.git","svn_url":"https://github.com/dotnet/training-tutorials","homepage":"http://dot.net/","size":1026,"stargazers_count":40,"watchers_count":40,"language":null,"has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":19,"mirror_url":null,"open_issues_count":30,"forks":19,"open_issues":30,"watchers":40,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/dotnet/training-tutorials/pulls/164"},"html":{"href":"https://github.com/dotnet/training-tutorials/pull/164"},"issue":{"href":"https://api.github.com/repos/dotnet/training-tutorials/issues/164"},"comments":{"href":"https://api.github.com/repos/dotnet/training-tutorials/issues/164/comments"},"review_comments":{"href":"https://api.github.com/repos/dotnet/training-tutorials/pulls/164/comments"},"review_comment":{"href":"https://api.github.com/repos/dotnet/training-tutorials/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/dotnet/training-tutorials/pulls/164/commits"},"statuses":{"href":"https://api.github.com/repos/dotnet/training-tutorials/statuses/65b21d1b011be0c168f5288da80fd2f184c864d0"}}}}
{"actor":{"display_login":"ardalis"}}