Update MVC Enumerable service registrations
Updates MVC service registration code to use the new TryAddEnumerable overload (idempotence++). Some other misc cleanup to improve idempotence.
This commit is contained in:
parent
37f056ce2b
commit
f055618c8c
|
|
@ -2,8 +2,6 @@
|
|||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using Microsoft.AspNet.Mvc;
|
||||
using Microsoft.AspNet.Mvc.ActionConstraints;
|
||||
using Microsoft.AspNet.Mvc.ApplicationModels;
|
||||
|
|
@ -48,8 +46,7 @@ namespace Microsoft.Framework.DependencyInjection
|
|||
{
|
||||
// Options
|
||||
//
|
||||
TryAddMultiRegistrationService(
|
||||
services,
|
||||
services.TryAddEnumerable(
|
||||
ServiceDescriptor.Transient<IConfigureOptions<MvcOptions>, CoreMvcOptionsSetup>());
|
||||
|
||||
// Action Discovery
|
||||
|
|
@ -57,11 +54,9 @@ namespace Microsoft.Framework.DependencyInjection
|
|||
// These are consumed only when creating action descriptors, then they can be de-allocated
|
||||
services.TryAdd(ServiceDescriptor.Transient<IAssemblyProvider, DefaultAssemblyProvider>());
|
||||
services.TryAdd(ServiceDescriptor.Transient<IControllerTypeProvider, DefaultControllerTypeProvider>()); ;
|
||||
TryAddMultiRegistrationService(
|
||||
services,
|
||||
services.TryAddEnumerable(
|
||||
ServiceDescriptor.Transient<IApplicationModelProvider, DefaultApplicationModelProvider>());
|
||||
TryAddMultiRegistrationService(
|
||||
services,
|
||||
services.TryAddEnumerable(
|
||||
ServiceDescriptor.Transient<IActionDescriptorProvider, ControllerActionDescriptorProvider>());
|
||||
services.TryAdd(ServiceDescriptor
|
||||
.Singleton<IActionDescriptorsCollectionProvider, DefaultActionDescriptorsCollectionProvider>());
|
||||
|
|
@ -74,8 +69,7 @@ namespace Microsoft.Framework.DependencyInjection
|
|||
.Singleton<IActionSelectorDecisionTreeProvider, ActionSelectorDecisionTreeProvider>());
|
||||
// This provider needs access to the per-request services, but might be used many times for a given
|
||||
// request.
|
||||
TryAddMultiRegistrationService(
|
||||
services,
|
||||
services.TryAddEnumerable(
|
||||
ServiceDescriptor.Transient<IActionConstraintProvider, DefaultActionConstraintProvider>());
|
||||
|
||||
// Action Invoker
|
||||
|
|
@ -87,14 +81,11 @@ namespace Microsoft.Framework.DependencyInjection
|
|||
services.TryAdd(ServiceDescriptor.Transient<IActionInvokerFactory, ActionInvokerFactory>());
|
||||
services.TryAdd(ServiceDescriptor
|
||||
.Transient<IControllerActionArgumentBinder, DefaultControllerActionArgumentBinder>());
|
||||
TryAddMultiRegistrationService(
|
||||
services,
|
||||
services.TryAddEnumerable(
|
||||
ServiceDescriptor.Transient<IActionInvokerProvider, ControllerActionInvokerProvider>());
|
||||
TryAddMultiRegistrationService(
|
||||
services,
|
||||
services.TryAddEnumerable(
|
||||
ServiceDescriptor.Transient<IFilterProvider, DefaultFilterProvider>());
|
||||
TryAddMultiRegistrationService(
|
||||
services,
|
||||
services.TryAddEnumerable(
|
||||
ServiceDescriptor.Transient<IControllerPropertyActivator, DefaultControllerPropertyActivator>());
|
||||
|
||||
// ModelBinding, Validation and Formatting
|
||||
|
|
@ -127,34 +118,14 @@ namespace Microsoft.Framework.DependencyInjection
|
|||
services.TryAdd(ServiceDescriptor.Scoped<IUrlHelper, UrlHelper>());
|
||||
}
|
||||
|
||||
// Adds a service if the service type and implementation type hasn't been added yet. This is needed for
|
||||
// services like IConfigureOptions<MvcOptions> or IApplicationModelProvider where you need the ability
|
||||
// to register multiple implementation types for the same service type.
|
||||
private static bool TryAddMultiRegistrationService(IServiceCollection services, ServiceDescriptor descriptor)
|
||||
{
|
||||
// This can't work when registering a factory or instance, you have to register a type.
|
||||
// Additionally, if any existing registrations use a factory or instance, we can't check those, but we don't
|
||||
// assert that because it might be added by user-code.
|
||||
Debug.Assert(descriptor.ImplementationType != null);
|
||||
|
||||
if (services.Any(d =>
|
||||
d.ServiceType == descriptor.ServiceType &&
|
||||
d.ImplementationType == descriptor.ImplementationType))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
services.Add(descriptor);
|
||||
return true;
|
||||
}
|
||||
|
||||
private static void ConfigureDefaultServices(IServiceCollection services)
|
||||
{
|
||||
services.AddOptions();
|
||||
services.AddRouting();
|
||||
services.AddNotifier();
|
||||
services.Configure<RouteOptions>(
|
||||
routeOptions => routeOptions.ConstraintMap.Add("exists", typeof(KnownRouteValueConstraint)));
|
||||
|
||||
services.TryAddEnumerable(
|
||||
ServiceDescriptor.Transient<IConfigureOptions<RouteOptions>, MvcRouteOptionsSetup>());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using Microsoft.AspNet.Routing;
|
||||
using Microsoft.Framework.OptionsModel;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc
|
||||
{
|
||||
/// <summary>
|
||||
/// Sets up MVC default options for <see cref="RouteOptions"/>.
|
||||
/// </summary>
|
||||
public class MvcRouteOptionsSetup : ConfigureOptions<RouteOptions>
|
||||
{
|
||||
public MvcRouteOptionsSetup()
|
||||
: base(ConfigureRouting)
|
||||
{
|
||||
Order = DefaultOrder.DefaultFrameworkSortOrder;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Configures the <see cref="RouteOptions"/>.
|
||||
/// </summary>
|
||||
/// <param name="options">The <see cref="RouteOptions"/>.</param>
|
||||
public static void ConfigureRouting(RouteOptions options)
|
||||
{
|
||||
options.ConstraintMap.Add("exists", typeof(KnownRouteValueConstraint));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,6 +1,7 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System.Net.Http;
|
||||
using System.Net.Http.Formatting;
|
||||
using Microsoft.Framework.OptionsModel;
|
||||
|
||||
|
|
@ -35,6 +36,8 @@ namespace Microsoft.AspNet.Mvc.WebApiCompatShim
|
|||
|
||||
// Add a formatter to write out an HttpResponseMessage to the response
|
||||
options.OutputFormatters.Insert(0, new HttpResponseMessageOutputFormatter());
|
||||
|
||||
options.ValidationExcludeFilters.Add(typeof(HttpResponseMessage));
|
||||
}
|
||||
|
||||
public void Configure(WebApiCompatShimOptions options, string name = "")
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System.Net.Http;
|
||||
using System.Net.Http.Formatting;
|
||||
using Microsoft.AspNet.Mvc;
|
||||
using Microsoft.AspNet.Mvc.WebApiCompatShim;
|
||||
using Microsoft.Framework.OptionsModel;
|
||||
|
||||
namespace Microsoft.Framework.DependencyInjection
|
||||
{
|
||||
|
|
@ -12,15 +12,14 @@ namespace Microsoft.Framework.DependencyInjection
|
|||
{
|
||||
public static IServiceCollection AddWebApiConventions(this IServiceCollection services)
|
||||
{
|
||||
services.ConfigureOptions<WebApiCompatShimOptionsSetup>();
|
||||
services.TryAddEnumerable(
|
||||
ServiceDescriptor.Transient<IConfigureOptions<MvcOptions>, WebApiCompatShimOptionsSetup>());
|
||||
services.TryAddEnumerable(
|
||||
ServiceDescriptor.Transient<IConfigureOptions<WebApiCompatShimOptions>, WebApiCompatShimOptionsSetup>());
|
||||
|
||||
// The constructors on DefaultContentNegotiator aren't DI friendly, so just
|
||||
// new it up.
|
||||
services.AddInstance<IContentNegotiator>(new DefaultContentNegotiator());
|
||||
services.Configure<MvcOptions>(options =>
|
||||
{
|
||||
options.ValidationExcludeFilters.Add(typeof(HttpRequestMessage));
|
||||
});
|
||||
services.TryAdd(ServiceDescriptor.Instance<IContentNegotiator>(new DefaultContentNegotiator()));
|
||||
|
||||
return services;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -145,38 +145,30 @@ namespace Microsoft.Framework.DependencyInjection
|
|||
internal static void AddMvcServices(IServiceCollection services)
|
||||
{
|
||||
// Options - all of these are multi-registration
|
||||
TryAddMultiRegistrationService(
|
||||
services,
|
||||
services.TryAddEnumerable(
|
||||
ServiceDescriptor.Transient<IConfigureOptions<MvcOptions>, MvcOptionsSetup>());
|
||||
TryAddMultiRegistrationService(
|
||||
services,
|
||||
services.TryAddEnumerable(
|
||||
ServiceDescriptor.Transient<IConfigureOptions<MvcOptions>, JsonMvcOptionsSetup>());
|
||||
TryAddMultiRegistrationService(
|
||||
services,
|
||||
services.TryAddEnumerable(
|
||||
ServiceDescriptor
|
||||
.Transient<IConfigureOptions<MvcFormatterMappingOptions>, JsonMvcFormatterMappingOptionsSetup>());
|
||||
TryAddMultiRegistrationService(
|
||||
services,
|
||||
services.TryAddEnumerable(
|
||||
ServiceDescriptor.Transient<IConfigureOptions<MvcViewOptions>, MvcViewOptionsSetup>());
|
||||
TryAddMultiRegistrationService(
|
||||
services,
|
||||
services.TryAddEnumerable(
|
||||
ServiceDescriptor
|
||||
.Transient<IConfigureOptions<RazorViewEngineOptions>, RazorViewEngineOptionsSetup>());
|
||||
|
||||
// Cors
|
||||
TryAddMultiRegistrationService(
|
||||
services,
|
||||
services.TryAddEnumerable(
|
||||
ServiceDescriptor.Transient<IApplicationModelProvider, CorsApplicationModelProvider>());
|
||||
services.TryAdd(ServiceDescriptor.Transient<CorsAuthorizationFilter, CorsAuthorizationFilter>());
|
||||
|
||||
// Auth
|
||||
TryAddMultiRegistrationService(
|
||||
services,
|
||||
services.TryAddEnumerable(
|
||||
ServiceDescriptor.Transient<IApplicationModelProvider, AuthorizationApplicationModelProvider>());
|
||||
|
||||
// Support for activating ViewDataDictionary
|
||||
TryAddMultiRegistrationService(
|
||||
services,
|
||||
services.TryAddEnumerable(
|
||||
ServiceDescriptor
|
||||
.Transient<IControllerPropertyActivator, ViewDataDictionaryControllerPropertyActivator>());
|
||||
|
||||
|
|
@ -264,8 +256,7 @@ namespace Microsoft.Framework.DependencyInjection
|
|||
// Api Description
|
||||
services.TryAdd(ServiceDescriptor
|
||||
.Singleton<IApiDescriptionGroupCollectionProvider, ApiDescriptionGroupCollectionProvider>());
|
||||
TryAddMultiRegistrationService(
|
||||
services,
|
||||
services.TryAddEnumerable(
|
||||
ServiceDescriptor.Transient<IApiDescriptionProvider, DefaultApiDescriptionProvider>());
|
||||
}
|
||||
|
||||
|
|
@ -297,27 +288,6 @@ namespace Microsoft.Framework.DependencyInjection
|
|||
return services;
|
||||
}
|
||||
|
||||
// Adds a service if the service type and implementation type hasn't been added yet. This is needed for
|
||||
// services like IConfigureOptions<MvcOptions> or IApplicationModelProvider where you need the ability
|
||||
// to register multiple implementation types for the same service type.
|
||||
private static bool TryAddMultiRegistrationService(IServiceCollection services, ServiceDescriptor descriptor)
|
||||
{
|
||||
// This can't work when registering a factory or instance, you have to register a type.
|
||||
// Additionally, if any existing registrations use a factory or instance, we can't check those, but we don't
|
||||
// assert that because it might be added by user-code.
|
||||
Debug.Assert(descriptor.ImplementationType != null);
|
||||
|
||||
if (services.Any(d =>
|
||||
d.ServiceType == descriptor.ServiceType &&
|
||||
d.ImplementationType == descriptor.ImplementationType))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
services.Add(descriptor);
|
||||
return true;
|
||||
}
|
||||
|
||||
private static void ConfigureDefaultServices(IServiceCollection services)
|
||||
{
|
||||
services.AddDataProtection();
|
||||
|
|
|
|||
Loading…
Reference in New Issue