{"action":"created","comment":{"url":"https://api.github.com/repos/aspnet/Docs/pulls/comments/43325847","id":43325847,"diff_hunk":"@@ -1,10 +1,277 @@\n-.. _dependency-injection:\n+Dependency Injection\n+====================\n+By `Steve Smith`_\n \n-.. include:: /../common/stub-topic.txt\n+ASP.NET 5 is designed from the ground up to support and leverage dependency injection. ASP.NET 5 applications can leverage built-in framework services by having them injected into methods in the Startup class, and application services can be configured for injection as well. If desired, developers can replace the built-in services container with a custom or third party implementation.\n \n-|stub-icon| Dependency Injection\n-================================\n+In this article:\n+\t- `What is Dependency Injection?`_\n+\t- `Using Framework-Provided Services`_\n+\t- `Registering Your Own Services`_\n+\t- `Service Lifetimes and Registration Options`_\n+\t- `Request Services and Application Services`_\n+\t- `Designing Your Services For Dependency Injection`_\n+\t- `Replacing the default services container`_\n+\t- `Recommendations`_\n \n-.. include:: /../common/stub-notice.txt\n+`Download sample from GitHub <https://github.com/aspnet/docs/aspnet/fundamentals/dependency-injection/sample>`_. \n \n-.. _issue: https://github.com/aspnet/Docs/issues/24\n\\ No newline at end of file\n+What is Dependency Injection?\n+-----------------------------\n+\n+Dependency injection (DI) is a technique for achieving loose coupling between objects and their collaborators, or dependencies. Rather than directly instantiating collaborators, or using static references, the objects a class needs in order to perform its actions are provided to the class in some fashion. Most often, classes will declare their dependencies via their constructor, allowing them to follow the `Explicit Dependencies Principle <http://deviq.com/explicit-dependencies-principle/>`_. This approach is known as \"constructor injection\". Alternately, dependencies can be provided via properties (\"property injection\") or even as parameters on methods (\"parameter injection\"), though this is much less common.\n+\n+When classes are designed with DI in mind, they are more loosely coupled because they do not have direct, hard-coded dependencies on their collaborators. This follows the `Dependency Inversion Principle <http://deviq.com/dependency-inversion-principle/>`_, which states that *\"high level modules should not depend on low level modules; both should depend on abstractions.\"* Instead of referencing specific implementations, classes request abstractions (typically ``interfaces``) which are provided to them when they are constructed. Extracting dependencies into interfaces and providing implementations of these interfaces as parameters is also an example of the `Strategy design pattern <http://deviq.com/strategy-design-pattern/>`_.\n+\n+When a system is designed to use DI, with many classes requesting their dependencies via their constructor (or properties), it's helpful to have a class dedicated to creating these classes with their associated dependencies. These classes are referred to as *containers*, or more specifically, `Inversion of Control (IoC) <http://deviq.com/inversion-of-control/>`_ containers or Dependency Injection (DI) containers. A container is essentially a factory that is responsible for providing instances of types that are requested from it. If a given type has declared that it has dependencies, and the container has been configured to provide the dependency types, it will create the dependencies as part of creating the requested instance. In this way, complex dependency graphs can be provided to classes without the need for any hard-coded object construction. In addition to creating objects with their dependencies, containers typically manage object lifetimes within the application.\n+\n+ASP.NET 5 includes a simple built-in container (represented by the IServiceProvider interface) that supports constructor and property injection by default, and ASP.NET makes certain services available through DI. ASP.NET's container refers to the types it manages as *services*. Throughout the rest of this article, *services* will refer to types that are managed by ASP.NET 5's IoC container. You configure the built-in container's services in the ``ConfigureServices`` method in your application's ``Startup`` class.\n+\n+.. note:: Martin Fowler has written an extensive article on `Inversion of Control Containers and the Dependency Injection Pattern <http://www.martinfowler.com/articles/injection.html>`_. Microsoft Patterns and Practices also has a great description of `Dependency Injection <https://msdn.microsoft.com/en-us/library/dn178469(v=pandp.30).aspx>`_.\n+\n+Using Framework-Provided Services\n+---------------------------------\n+\n+ASP.NET 5 provides certain application services during your application's startup. You can request any of these services by simply including the appropriate interface as a parameter on your ``Startup`` class's constructor or one of its ``Configure`` or ``ConfigureServices`` methods. These services include:\n+\n+IApplicationBuilder (`source <https://github.com/aspnet/HttpAbstractions/blob/1.0.0-beta7/src/Microsoft.AspNet.Http.Abstractions/IApplicationBuilder.cs>`_)\n+\tUsed to build the application request pipeline. Available only to the ``Configure`` method in ``Startup``. Learn more about :doc:`request-features`.\n+\t\n+IApplicationEnvironment (`source <https://github.com/aspnet/dnx/blob/1.0.0-beta7/src/Microsoft.Dnx.Runtime.Abstractions/IApplicationEnvironment.cs>`_)\n+\tProvides access to the application properties, such as ``ApplicationName``, ``ApplicationVersion``, and ``ApplicationBasePath``. Available to the ``Startup`` constructor and ``Configure`` method.\n+\t\n+IHostingEnvironment (`source <https://github.com/aspnet/Hosting/blob/1.0.0-beta7/src/Microsoft.AspNet.Hosting.Abstractions/IHostingEnvironment.cs>`_)\n+\tProvides the current ``EnvironmentName``, ``WebRootPath``, and web root file provider. Available to the ``Startup`` constructor and ``Configure`` method. Learn more about :doc:`hosting`.\n+\t\n+ILoggerFactory (`source <https://github.com/aspnet/Logging/blob/1.0.0-beta7/src/Microsoft.Framework.Logging.Abstractions/ILoggerFactory.cs>`_)\n+\tProvides a mechanism for creating loggers. Available to the ``Startup`` constructor and ``Configure`` method. Learn more about :doc:`logging`.\n+\t\n+IServiceCollection (`source <https://github.com/aspnet/DependencyInjection/blob/1.0.0-beta7/src/Microsoft.Framework.DependencyInjection.Abstractions/IServiceCollection.cs>`_)\n+\tThe current set of services configured in the container. Available only to the ``ConfigureServices`` method, and used by that method to configure the services available to an application.\n+\n+Looking at each method in the ``Startup`` class in the order in which they are called, the following services may be requested as parameters:\n+\n+Startup Constructor\n+\t- ``IApplicationEnvironment``\n+\t- ``IHostingEnvironment``\n+\t- ``ILoggerFactory``\n+\t\n+ConfigureServices\n+\t- ``IServiceCollection``\n+\n+Configure\n+\t- ``IApplicationBuilder``\n+\t- ``IApplicationEnvironment``\n+\t- ``IHostingEnvironment``\n+\t- ``ILoggerFactory``\n+\t\n+\n+.. note:: Although ``ILoggerFactory`` is available in the constructor, it is typically configured in the ``Configure`` method. Learn more about the ``Startup`` class constructor and ``Configure`` method in :doc:`startup`.\n+\n+The ``ConfigureServices`` method is responsible for defining the services the application will use, including platform features like Entity Framework and ASP.NET MVC. Initially, the ``IServiceCollection`` provided to ``ConfigureServices`` has just a handful of services defined. The default web template shows an example of how to add additional services to the container using a number of extensions methods like ``AddEntityFramework``, ``Configure<Options>``, and ``AddMvc``.\n+\n+.. literalinclude:: ../../common/samples/WebApplication1/src/WebApplication1/Startup.cs\n+\t:language: c#\n+\t:linenos:\n+\t:lines: 45-84\n+\t:dedent: 8\n+\t:emphasize-lines: 5,11,18,24\n+\n+In order to keep the ``ConfigureServices`` method manageable, it is recommended that :doc:`middleware` and :doc:`request-features` authors provide extension methods and fluent configuration APIs that work with ``IServiceCollection``. The built-in features for Entity Framework, Identity, and ASP.NET MVC all follow this approach and can be used as models for providing a very succinct way to add a great deal of functionality to an ASP.NET application.\n+\n+Of course, in addition to configuring the application to take advantage of various framework features, you can also use ``ConfigureServices`` to configure your own application services.\n+\n+Registering Your Own Services\n+-----------------------------\n+\n+In the default web template example above, two application services are added to the ``IServiceCollection`` (``IEmailSender`` and ``ISmsSender``). The ``AddTransient`` method is used to map abstract types to concrete services that are instantiated separately for every object that requires it. This is known as the service's *lifetime*, and additional lifetime options are described below. It is important to choose an appropriate lifetime for each of the services you register. Should a new instance of the service be provided to each class that requests it? Should once instance be used throughout a given web request? Or should a single instance be used for the lifetime of the application?\n+\n+In the sample for this article, there is a simple controller that displays character names, called ``CharacterController``. Its ``Index`` method displays the current list of characters that have been stored in the application, and initializes the collection with a handful of characters if none exist. Note that although this application uses Entity Framework and the ``ApplicationDbContext`` class for its persistence, none of that is apparent in the controller. Instead, the specific data access mechanism has been abstracted behind an interface, ``ICharacterRepository``, which follows the `repository pattern <http://deviq.com/repository-pattern/>`_. An instance of ``ICharacterRepository`` is requested via the constructor and assigned to a private field, which is then used to access characters as necessary.\n+\n+.. literalinclude:: dependency-injection/sample/src/DependencyInjectionSample/Controllers/CharactersController.cs\n+\t:language: c#\n+\t:linenos:\n+\t:lines: 1-32\n+\t:emphasize-lines: 10,12,14,20,23-27\n+\n+The `ICharacterRepository` simply defines the two methods the controller needs to work with `Character` instances.\n+\n+.. literalinclude:: dependency-injection/sample/src/DependencyInjectionSample/Interfaces/ICharacterRepository.cs\n+\t:language: c#\n+\t:linenos:\n+\n+This interface is in turn implemented by a concrete type, ``CharacterRepository``, that is used at runtime.\n+\n+.. literalinclude:: dependency-injection/sample/src/DependencyInjectionSample/Models/CharacterRepository.cs\n+\t:language: c#\n+\t:linenos:\n+\n+Note that ``CharacterRepository`` requests an ``ApplicationDbContext`` in its constructor. It is not unusual for dependency injection to be used in a chained fashion like this, with each requested dependency in turn requesting its own dependencies. The container is responsible for resolving all of the dependencies in the tree and returning the fully resolved object graph.\n+\n+In this case, both ``ICharacterRepository`` and in turn ``ApplicationDbContext`` must be registered with the services container in ``ConfigureServices`` in ``Startup``. ``ApplicationDbContext`` is configured via the call to the extension method ``AddEntityFramework`` which includes an extension for adding a ``DbContext`` (``AddDbContext<T>``). Registration of the repository is done at the bottom end of ``ConfigureServices``:\n+\n+.. literalinclude:: dependency-injection/sample/src/DependencyInjectionSample/Startup.cs\n+\t:language: c#\n+\t:lines: 48-54, 82-86\n+\t:linenos:\n+\t:dedent: 8\n+\t:emphasize-lines: 6, 11\n+\n+Entity Framework contexts should be added to the services container using the ``Scoped`` lifetime. This is taken care of automatically if you use the helper methods as shown above. Repositories that will make use of Entity Framework should use the same lifetime.\n+\n+Service Lifetimes and Registration Options\n+------------------------------------------\n+\n+ASP.NET services can be configured with the following lifetimes:\n+\n+Transient\n+\tTransient lifetime services are created each time they are requested. This lifetime works best for lightweight, stateless service.\n+\n+Scoped\n+\tScoped lifetime services are created once per request.\n+\n+Singleton\n+\tSingleton lifetime services are created the first time they are requested, and then every subsequent request will use the same instance. If your application requires singleton behavior, this is recommended in place of implementing the singleton design pattern in your class yourself.\n+\n+Instance\n+\tYou can choose to add an instance directly to the services container. If you do so, this instance will be used for all subsequent requests (this technique will create a Singleton-scoped instance).\n+\n+Services can be registered with the container in several ways. We have already seen how to register a service implementation with a given type by specifying the concrete type to use. In addition, a factory can be specified, which will then be used to create the instance on demand. The third approach is to directly specify the instance of the type to use, in which case the container will never attempt to create an instance.\n+\n+To demonstrate the difference between these four lifetime and registration options, consider a simple interface that represents one or more tasks as an *operation* with a unique identifier, ``OperationId``. Depending on how we configure the lifetime for this service, the container will provide either the same or different instances of the service to the requesting class. To make it clear which lifetime is being requested, we will create one type per lifetime option:\n+\n+.. literalinclude:: dependency-injection/sample/src/DependencyInjectionSample/Interfaces/IOperation.cs\n+\t:language: c#\n+\t:linenos:\n+\t:emphasize-lines: 7\n+\n+Next, in ``ConfigureServices``, each type is added to the container according to its named lifetime:\n+\n+.. literalinclude:: dependency-injection/sample/src/DependencyInjectionSample/Startup.cs\n+\t:language: c#\n+\t:lines: 83-88\n+\t:linenos:\n+\t:dedent: 8\n+\n+Note that the *instance* lifetime type has been added with a known ID of ``Guid.Empty`` so it will be clear when this type is in use. We have also registered an ``OperationService`` that depends on each of the other ``Operation`` types, so that it will be clear within a request whether this service is getting the same instance as the controller, or a new one, for each operation type.\n+\n+.. literalinclude:: dependency-injection/sample/src/DependencyInjectionSample/Services/OperationService.cs\n+\t:language: c#\n+\t:linenos:\n+\n+To demonstrate the object lifetimes within and between separate individual requests to the application, the sample includes an ``OperationsController`` that requests each kind of ``IOperation`` type as well as an ``OperationService``. The ``Index`` action then displays all of the controller's and service's ``OperationId`` values.\n+\n+.. literalinclude:: dependency-injection/sample/src/DependencyInjectionSample/Controllers/OperationsController.cs\n+\t:language: c#\n+\t:linenos:\n+\n+Now two separate requests are made to this controller action:\n+\n+.. image:: dependency-injection/_static/lifetimes_request1.png\n+.. image:: dependency-injection/_static/lifetimes_request2.png\n+\n+Observe which of the ``OperationId`` values varies within a request, and between requests.\n+\n+- *Transient* objects are always different; a new instance is provided to every controller and every service.\n+- *Scoped* objects are the same within a request, but different across different requests\n+- *Singleton* objects are the same for every object and every request\n+- *Instance* objects are the same for every object and every request, and are the exact instance that was specified in ``ConfigureServices``\n+\n+Request Services and Application Services\n+-----------------------------------------\n+\n+The services available within an ASP.NET request from ``HttpContext`` fall into two collections: *ApplicationServices* and *RequestServices*.\n+\n+.. image:: dependency-injection/_static/application_request_services.png\n+\n+Request Services represent the services you configure and request as part of your application. These are the services that are available on a per-request basis. Application Services are limited to those things that are available on application startup. These are services that are outside the scope of one request, such as ``IHostingEnvironment``. Anything that is scoped is only available as part of Request Services, not Application Services. When your objects specify dependencies, these are satisfied by the types found in ``RequestServices``, not ``ApplicationServices``.\n+\n+Generally, you shouldn't use these properties directly, preferring instead to request the types your classes you require via your class's constructor, and letting the framework inject these dependencies. This yields classes that are easier to :doc:`test <testing>` and are more loosely coupled. However, there may be instances in which you need to use a service locator pattern to gain access to a particular service. This should be the exception, rather than the rule, since there are substantial drawbacks to this pattern (hence it is commonly considered to be an `antipattern <http://blog.ploeh.dk/2010/02/03/ServiceLocatorisanAnti-Pattern/>`_). If you do find yourself with no other choice but to use service location, a static service locator is available in the framework:\n+\n+.. code-block:: c#\n+\n+\t// using Microsoft.Dnx.Runtime.Infrastructure\n+\tvar hostingEnv = CallContextServiceLocator.Locator.ServiceProvider\n+\t\t.GetService(typeof(IHostingEnvironment)) as IHostingEnvironment;\n+\tstring environmentName = hostingEnv.EnvironmentName;\n+\n+.. warning:: Prefer the use of dependency injection over service location in your application code, since it provides looser coupling and better testability. Service location may be the best (or only) choice in some framework or test code scenarios, however.\n+\n+Designing Your Services For Dependency Injection\n+------------------------------------------------\n+\n+You should design your services to use dependency injection to get their collaborators. This means avoiding the use of stateful static method calls (which result in a code smell known as `static cling <http://deviq.com/static-cling/>`_) and the direct instantiation of dependent classes within your services. It may help to remember the phrase, `New is Glue <http://ardalis.com/new-is-glue>`_, when choosing whether to instantiate a type or to request it via dependency injection. By following the `SOLID Principles of Object Oriented Design <http://deviq.com/solid/>`_, your classes will naturally tend to be small, well-named and well-factored, and easily tested.\n+\n+What if you find that your classes tend to have way too many dependencies being injected? This is generally a sign that your class is trying to do too much, and is probably violating SRP - the `Single Responsibility Principle <http://deviq.com/single-responsibility-principle/>`_. See if you can refactor the class by moving some of its responsibilities into a new class. Keep in mind that your ``Controller`` classes should be focused on UI concerns, so business rules and data access implementation details should be kept in classes appropriate to these separate concerns.\n+\n+With regard to data access specifically, you can easily inject Entity Framework ``DbContext`` types into your controllers, assuming you've configured EF in your ``Startup`` class. However, I recommend avoiding direct dependency on ``DbContext`` in your application. Instead, depend on an abstraction (like a Repository interface), and restrict knowledge of EF (or any other specific data access technology) to the implementation of this interface. This will reduce the coupling between your application and a particular data access strategy, and will make :doc:`testing` your application code much easier.\n+\n+Replacing the default services container\n+----------------------------------------\n+\n+The built-in services container is mean to serve the basic needs of the framework and most consumer applications built on it. However, developers who wish to replace the built-in container with their preferred container can easily do so. The ``ConfigureServices`` method typically returns ``void``, but if its signature is changed to return ``IServiceProvider``, a different container can be configured and returned. There are `many IOC containers available for .NET <https://github.com/danielpalme/IocPerformance/blob/master/README.md>`_. This article will attempt to add links to DNX implementations of containers as they become available. In this example, the `StructureMap.Dnx <https://github.com/structuremap/structuremap.dnx>`_ package is used.\n+\n+First, add the appropriate container to the dependencies property in project.json:\n+\n+.. code-block:: javascript\n+\n+\t\"dependencies\" : {\n+\t\t\"StructureMap.Dnx\": \"0.4.0-alpha\"\n+\t},\n+\n+.. note:: Currently StructureMap does not support .NET Core.\n+\n+Next, configure the container in ``ConfigureServices`` and return an ``IServiceProvider``:\n+\n+.. code-block:: c#\n+\n+\tpublic IServiceProvider ConfigureServices(IServiceCollection services)\n+\t{\n+\t\tservices.AddMvc();\n+\t\t// add other services\n+\t\t\n+\t\t// Add StructureMap\n+\t\tvar container = new StructureMap.Container();\n+\t\tcontainer.Populate(services);\n+\t\treturn container.GetInstance<IServiceProvider>();\n+\t}\n+\n+.. note:: If you add StructureMap to the sample project, you will need to add a ``[DefaultConstructor]`` attribute to the default constructor for ``Operation``.\n+\n+.. list-table:: ASP.NET 5 / DNX Containers (in alphabetical order)\n+   :header-rows: 1\n+\n+   * - Package (Nuget)\n+     - Setup Instructions\n+   * - `Autofac.Dnx <http://www.nuget.org/packages/Autofac.Dnx/>`_\n+     - http://autofac.org/\n+   * - `StructureMap.Dnx <http://www.nuget.org/packages/StructureMap.Dnx>`_\n+     - `Getting Started <https://github.com/structuremap/structuremap.dnx/blob/master/README.md>`_\n+\n+Recommendations\n+---------------\n+\n+When working with dependency injection, keep the following recommendations in mind:\n+\n+- DI is for objects that have complex dependencies. Controllers, services, adapters, and repositories are all examples of objects that might be added to DI.\n+- Avoid storing data and configuration directly in DI. For example, a user's shopping cart shouldn't typically be added to the services container. Configuration should use the :doc:`options`.\n+- Avoid creating \"data holder\" objects. These are objects that only exist to allow access to some other object. It's better to request the actual item needed via DI, is possible.","path":"aspnet/fundamentals/dependency-injection.rst","position":265,"original_position":265,"commit_id":"7edbdfc7029b717345502ebe4b45b8aea00ca06e","original_commit_id":"7edbdfc7029b717345502ebe4b45b8aea00ca06e","user":{"login":"dougbu","id":6431421,"avatar_url":"https://avatars.githubusercontent.com/u/6431421?v=3","gravatar_id":"","url":"https://api.github.com/users/dougbu","html_url":"https://github.com/dougbu","followers_url":"https://api.github.com/users/dougbu/followers","following_url":"https://api.github.com/users/dougbu/following{/other_user}","gists_url":"https://api.github.com/users/dougbu/gists{/gist_id}","starred_url":"https://api.github.com/users/dougbu/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/dougbu/subscriptions","organizations_url":"https://api.github.com/users/dougbu/orgs","repos_url":"https://api.github.com/users/dougbu/repos","events_url":"https://api.github.com/users/dougbu/events{/privacy}","received_events_url":"https://api.github.com/users/dougbu/received_events","type":"User","site_admin":false},"body":"Two points about data services seem redundant. Suggest generalizing this one a bit to make it clear any service that exists only to provide a reference to something else is a poor idea.\r\n\r\nIt's important to mention exceptions to the \"storing data\" point exist. E.g. MVC internally uses an `IActionContextAccessor` service to reach very short-lived `ActionContext` instances. Some shared objects don't even live as long as a request.","created_at":"2015-10-28T22:14:45Z","updated_at":"2015-10-28T22:14:45Z","html_url":"https://github.com/aspnet/Docs/pull/517#discussion_r43325847","pull_request_url":"https://api.github.com/repos/aspnet/Docs/pulls/517","_links":{"self":{"href":"https://api.github.com/repos/aspnet/Docs/pulls/comments/43325847"},"html":{"href":"https://github.com/aspnet/Docs/pull/517#discussion_r43325847"},"pull_request":{"href":"https://api.github.com/repos/aspnet/Docs/pulls/517"}}},"pull_request":{"url":"https://api.github.com/repos/aspnet/Docs/pulls/517","id":47708384,"html_url":"https://github.com/aspnet/Docs/pull/517","diff_url":"https://github.com/aspnet/Docs/pull/517.diff","patch_url":"https://github.com/aspnet/Docs/pull/517.patch","issue_url":"https://api.github.com/repos/aspnet/Docs/issues/517","number":517,"state":"open","locked":false,"title":"Dependency Injection","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":"Ready for review","created_at":"2015-10-14T20:09:55Z","updated_at":"2015-10-28T22:14:46Z","closed_at":null,"merged_at":null,"merge_commit_sha":"d5258ccf9ddb7e50305a94570aaf25d85816283f","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/aspnet/Docs/pulls/517/commits","review_comments_url":"https://api.github.com/repos/aspnet/Docs/pulls/517/comments","review_comment_url":"https://api.github.com/repos/aspnet/Docs/pulls/comments{/number}","comments_url":"https://api.github.com/repos/aspnet/Docs/issues/517/comments","statuses_url":"https://api.github.com/repos/aspnet/Docs/statuses/7edbdfc7029b717345502ebe4b45b8aea00ca06e","head":{"label":"aspnet:ardalis/dependency-injection","ref":"ardalis/dependency-injection","sha":"7edbdfc7029b717345502ebe4b45b8aea00ca06e","user":{"login":"aspnet","id":6476660,"avatar_url":"https://avatars.githubusercontent.com/u/6476660?v=3","gravatar_id":"","url":"https://api.github.com/users/aspnet","html_url":"https://github.com/aspnet","followers_url":"https://api.github.com/users/aspnet/followers","following_url":"https://api.github.com/users/aspnet/following{/other_user}","gists_url":"https://api.github.com/users/aspnet/gists{/gist_id}","starred_url":"https://api.github.com/users/aspnet/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/aspnet/subscriptions","organizations_url":"https://api.github.com/users/aspnet/orgs","repos_url":"https://api.github.com/users/aspnet/repos","events_url":"https://api.github.com/users/aspnet/events{/privacy}","received_events_url":"https://api.github.com/users/aspnet/received_events","type":"Organization","site_admin":false},"repo":{"id":28239455,"name":"Docs","full_name":"aspnet/Docs","owner":{"login":"aspnet","id":6476660,"avatar_url":"https://avatars.githubusercontent.com/u/6476660?v=3","gravatar_id":"","url":"https://api.github.com/users/aspnet","html_url":"https://github.com/aspnet","followers_url":"https://api.github.com/users/aspnet/followers","following_url":"https://api.github.com/users/aspnet/following{/other_user}","gists_url":"https://api.github.com/users/aspnet/gists{/gist_id}","starred_url":"https://api.github.com/users/aspnet/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/aspnet/subscriptions","organizations_url":"https://api.github.com/users/aspnet/orgs","repos_url":"https://api.github.com/users/aspnet/repos","events_url":"https://api.github.com/users/aspnet/events{/privacy}","received_events_url":"https://api.github.com/users/aspnet/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/aspnet/Docs","description":"Documentation for ASP.NET 5","fork":false,"url":"https://api.github.com/repos/aspnet/Docs","forks_url":"https://api.github.com/repos/aspnet/Docs/forks","keys_url":"https://api.github.com/repos/aspnet/Docs/keys{/key_id}","collaborators_url":"https://api.github.com/repos/aspnet/Docs/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/aspnet/Docs/teams","hooks_url":"https://api.github.com/repos/aspnet/Docs/hooks","issue_events_url":"https://api.github.com/repos/aspnet/Docs/issues/events{/number}","events_url":"https://api.github.com/repos/aspnet/Docs/events","assignees_url":"https://api.github.com/repos/aspnet/Docs/assignees{/user}","branches_url":"https://api.github.com/repos/aspnet/Docs/branches{/branch}","tags_url":"https://api.github.com/repos/aspnet/Docs/tags","blobs_url":"https://api.github.com/repos/aspnet/Docs/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/aspnet/Docs/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/aspnet/Docs/git/refs{/sha}","trees_url":"https://api.github.com/repos/aspnet/Docs/git/trees{/sha}","statuses_url":"https://api.github.com/repos/aspnet/Docs/statuses/{sha}","languages_url":"https://api.github.com/repos/aspnet/Docs/languages","stargazers_url":"https://api.github.com/repos/aspnet/Docs/stargazers","contributors_url":"https://api.github.com/repos/aspnet/Docs/contributors","subscribers_url":"https://api.github.com/repos/aspnet/Docs/subscribers","subscription_url":"https://api.github.com/repos/aspnet/Docs/subscription","commits_url":"https://api.github.com/repos/aspnet/Docs/commits{/sha}","git_commits_url":"https://api.github.com/repos/aspnet/Docs/git/commits{/sha}","comments_url":"https://api.github.com/repos/aspnet/Docs/comments{/number}","issue_comment_url":"https://api.github.com/repos/aspnet/Docs/issues/comments{/number}","contents_url":"https://api.github.com/repos/aspnet/Docs/contents/{+path}","compare_url":"https://api.github.com/repos/aspnet/Docs/compare/{base}...{head}","merges_url":"https://api.github.com/repos/aspnet/Docs/merges","archive_url":"https://api.github.com/repos/aspnet/Docs/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/aspnet/Docs/downloads","issues_url":"https://api.github.com/repos/aspnet/Docs/issues{/number}","pulls_url":"https://api.github.com/repos/aspnet/Docs/pulls{/number}","milestones_url":"https://api.github.com/repos/aspnet/Docs/milestones{/number}","notifications_url":"https://api.github.com/repos/aspnet/Docs/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/aspnet/Docs/labels{/name}","releases_url":"https://api.github.com/repos/aspnet/Docs/releases{/id}","created_at":"2014-12-19T17:38:02Z","updated_at":"2015-10-27T00:18:25Z","pushed_at":"2015-10-28T20:45:52Z","git_url":"git://github.com/aspnet/Docs.git","ssh_url":"git@github.com:aspnet/Docs.git","clone_url":"https://github.com/aspnet/Docs.git","svn_url":"https://github.com/aspnet/Docs","homepage":null,"size":42706,"stargazers_count":228,"watchers_count":228,"language":"C#","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":290,"mirror_url":null,"open_issues_count":196,"forks":290,"open_issues":196,"watchers":228,"default_branch":"master"}},"base":{"label":"aspnet:1.0.0-beta7","ref":"1.0.0-beta7","sha":"ec5b3c2eb6030900c3ba10609dd35f63d98034e6","user":{"login":"aspnet","id":6476660,"avatar_url":"https://avatars.githubusercontent.com/u/6476660?v=3","gravatar_id":"","url":"https://api.github.com/users/aspnet","html_url":"https://github.com/aspnet","followers_url":"https://api.github.com/users/aspnet/followers","following_url":"https://api.github.com/users/aspnet/following{/other_user}","gists_url":"https://api.github.com/users/aspnet/gists{/gist_id}","starred_url":"https://api.github.com/users/aspnet/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/aspnet/subscriptions","organizations_url":"https://api.github.com/users/aspnet/orgs","repos_url":"https://api.github.com/users/aspnet/repos","events_url":"https://api.github.com/users/aspnet/events{/privacy}","received_events_url":"https://api.github.com/users/aspnet/received_events","type":"Organization","site_admin":false},"repo":{"id":28239455,"name":"Docs","full_name":"aspnet/Docs","owner":{"login":"aspnet","id":6476660,"avatar_url":"https://avatars.githubusercontent.com/u/6476660?v=3","gravatar_id":"","url":"https://api.github.com/users/aspnet","html_url":"https://github.com/aspnet","followers_url":"https://api.github.com/users/aspnet/followers","following_url":"https://api.github.com/users/aspnet/following{/other_user}","gists_url":"https://api.github.com/users/aspnet/gists{/gist_id}","starred_url":"https://api.github.com/users/aspnet/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/aspnet/subscriptions","organizations_url":"https://api.github.com/users/aspnet/orgs","repos_url":"https://api.github.com/users/aspnet/repos","events_url":"https://api.github.com/users/aspnet/events{/privacy}","received_events_url":"https://api.github.com/users/aspnet/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/aspnet/Docs","description":"Documentation for ASP.NET 5","fork":false,"url":"https://api.github.com/repos/aspnet/Docs","forks_url":"https://api.github.com/repos/aspnet/Docs/forks","keys_url":"https://api.github.com/repos/aspnet/Docs/keys{/key_id}","collaborators_url":"https://api.github.com/repos/aspnet/Docs/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/aspnet/Docs/teams","hooks_url":"https://api.github.com/repos/aspnet/Docs/hooks","issue_events_url":"https://api.github.com/repos/aspnet/Docs/issues/events{/number}","events_url":"https://api.github.com/repos/aspnet/Docs/events","assignees_url":"https://api.github.com/repos/aspnet/Docs/assignees{/user}","branches_url":"https://api.github.com/repos/aspnet/Docs/branches{/branch}","tags_url":"https://api.github.com/repos/aspnet/Docs/tags","blobs_url":"https://api.github.com/repos/aspnet/Docs/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/aspnet/Docs/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/aspnet/Docs/git/refs{/sha}","trees_url":"https://api.github.com/repos/aspnet/Docs/git/trees{/sha}","statuses_url":"https://api.github.com/repos/aspnet/Docs/statuses/{sha}","languages_url":"https://api.github.com/repos/aspnet/Docs/languages","stargazers_url":"https://api.github.com/repos/aspnet/Docs/stargazers","contributors_url":"https://api.github.com/repos/aspnet/Docs/contributors","subscribers_url":"https://api.github.com/repos/aspnet/Docs/subscribers","subscription_url":"https://api.github.com/repos/aspnet/Docs/subscription","commits_url":"https://api.github.com/repos/aspnet/Docs/commits{/sha}","git_commits_url":"https://api.github.com/repos/aspnet/Docs/git/commits{/sha}","comments_url":"https://api.github.com/repos/aspnet/Docs/comments{/number}","issue_comment_url":"https://api.github.com/repos/aspnet/Docs/issues/comments{/number}","contents_url":"https://api.github.com/repos/aspnet/Docs/contents/{+path}","compare_url":"https://api.github.com/repos/aspnet/Docs/compare/{base}...{head}","merges_url":"https://api.github.com/repos/aspnet/Docs/merges","archive_url":"https://api.github.com/repos/aspnet/Docs/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/aspnet/Docs/downloads","issues_url":"https://api.github.com/repos/aspnet/Docs/issues{/number}","pulls_url":"https://api.github.com/repos/aspnet/Docs/pulls{/number}","milestones_url":"https://api.github.com/repos/aspnet/Docs/milestones{/number}","notifications_url":"https://api.github.com/repos/aspnet/Docs/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/aspnet/Docs/labels{/name}","releases_url":"https://api.github.com/repos/aspnet/Docs/releases{/id}","created_at":"2014-12-19T17:38:02Z","updated_at":"2015-10-27T00:18:25Z","pushed_at":"2015-10-28T20:45:52Z","git_url":"git://github.com/aspnet/Docs.git","ssh_url":"git@github.com:aspnet/Docs.git","clone_url":"https://github.com/aspnet/Docs.git","svn_url":"https://github.com/aspnet/Docs","homepage":null,"size":42706,"stargazers_count":228,"watchers_count":228,"language":"C#","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":290,"mirror_url":null,"open_issues_count":196,"forks":290,"open_issues":196,"watchers":228,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/aspnet/Docs/pulls/517"},"html":{"href":"https://github.com/aspnet/Docs/pull/517"},"issue":{"href":"https://api.github.com/repos/aspnet/Docs/issues/517"},"comments":{"href":"https://api.github.com/repos/aspnet/Docs/issues/517/comments"},"review_comments":{"href":"https://api.github.com/repos/aspnet/Docs/pulls/517/comments"},"review_comment":{"href":"https://api.github.com/repos/aspnet/Docs/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/aspnet/Docs/pulls/517/commits"},"statuses":{"href":"https://api.github.com/repos/aspnet/Docs/statuses/7edbdfc7029b717345502ebe4b45b8aea00ca06e"}}}}