Add basic startup experience for MVC.Core

This commit is contained in:
Ryan Nowak 2015-07-08 11:59:44 -07:00
parent fe52c0c0cb
commit 48bfdceea6
41 changed files with 757 additions and 489 deletions

View File

@ -3,6 +3,8 @@
using Microsoft.AspNet.Builder;
using Microsoft.Framework.DependencyInjection;
using Microsoft.Net.Http.Headers;
using Newtonsoft.Json;
namespace MvcMinimalSample.Web
{
@ -10,7 +12,12 @@ namespace MvcMinimalSample.Web
{
public void ConfigureServices(IServiceCollection services)
{
services.AddMinimalMvc();
// Example 1
services
.AddMvcCore()
.AddAuthorization()
.AddFormatterMappings(m => m.SetMediaTypeMappingForFormat("js", new MediaTypeHeaderValue("application/json")))
.AddJsonFormatters(j => j.Formatting = Formatting.Indented);
}
public void Configure(IApplicationBuilder app)

View File

@ -4,6 +4,8 @@
"dependencies": {
"Microsoft.AspNet.Mvc.Core": "6.0.0-*",
"Microsoft.AspNet.Mvc.DataAnnotations": "6.0.0-*",
"Microsoft.AspNet.Mvc.Formatters.Json": "6.0.0-*",
"Microsoft.AspNet.Hosting": "1.0.0-*",
"Microsoft.AspNet.Server.WebListener": "1.0.0-*"
},

View File

@ -0,0 +1,25 @@
// 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.Mvc.ApiExplorer;
using Microsoft.Framework.Internal;
namespace Microsoft.Framework.DependencyInjection
{
public static class MvcApiExplorerMvcBuilderExtensions
{
public static IMvcBuilder AddApiExplorer([NotNull] this IMvcBuilder builder)
{
AddApiExplorerServices(builder.Services);
return builder;
}
// Internal for testing.
internal static void AddApiExplorerServices(IServiceCollection services)
{
services.TryAddSingleton<IApiDescriptionGroupCollectionProvider, ApiDescriptionGroupCollectionProvider>();
services.TryAddEnumerable(
ServiceDescriptor.Transient<IApiDescriptionProvider, DefaultApiDescriptionProvider>());
}
}
}

View File

@ -0,0 +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.
namespace Microsoft.Framework.DependencyInjection
{
public interface IMvcBuilder
{
IServiceCollection Services { get; }
}
}

View File

@ -0,0 +1,66 @@
// 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;
using Microsoft.AspNet.Authorization;
using Microsoft.AspNet.Mvc;
using Microsoft.AspNet.Mvc.ApplicationModels;
namespace Microsoft.Framework.DependencyInjection
{
public static class MvcCoreMvcBuilderExtensions
{
public static IMvcBuilder AddFormatterMappings(this IMvcBuilder builder)
{
AddFormatterMappingsServices(builder.Services);
return builder;
}
public static IMvcBuilder AddFormatterMappings(
this IMvcBuilder builder,
Action<FormatterMappings> setupAction)
{
AddFormatterMappingsServices(builder.Services);
if (setupAction != null)
{
builder.Services.Configure<MvcOptions>((options) => setupAction(options.FormatterMappings));
}
return builder;
}
// Internal for testing.
internal static void AddFormatterMappingsServices(IServiceCollection services)
{
services.TryAddTransient<FormatFilter, FormatFilter>();
}
public static IMvcBuilder AddAuthorization(this IMvcBuilder builder)
{
AddAuthorizationServices(builder.Services);
return builder;
}
public static IMvcBuilder AddAuthorization(this IMvcBuilder builder, Action<AuthorizationOptions> setupAction)
{
AddAuthorizationServices(builder.Services);
if (setupAction != null)
{
builder.Services.Configure(setupAction);
}
return builder;
}
// Internal for testing.
internal static void AddAuthorizationServices(IServiceCollection services)
{
services.AddAuthorization();
services.TryAddEnumerable(
ServiceDescriptor.Transient<IApplicationModelProvider, AuthorizationApplicationModelProvider>());
}
}
}

View File

@ -20,13 +20,26 @@ namespace Microsoft.Framework.DependencyInjection
{
public static class MvcCoreServiceCollectionExtensions
{
public static IServiceCollection AddMinimalMvc([NotNull] this IServiceCollection services)
public static IMvcBuilder AddMvcCore([NotNull] this IServiceCollection services)
{
ConfigureDefaultServices(services);
AddMvcCoreServices(services);
return services;
return new MvcBuilder() { Services = services, };
}
public static IMvcBuilder AddMvcCore(
[NotNull] this IServiceCollection services,
[NotNull] Action<MvcOptions> setupAction)
{
ConfigureDefaultServices(services);
AddMvcCoreServices(services);
services.Configure(setupAction);
return new MvcBuilder() { Services = services, };
}
/// <summary>
@ -48,7 +61,9 @@ namespace Microsoft.Framework.DependencyInjection
// Options
//
services.TryAddEnumerable(
ServiceDescriptor.Transient<IConfigureOptions<MvcOptions>, CoreMvcOptionsSetup>());
ServiceDescriptor.Transient<IConfigureOptions<MvcOptions>, MvcCoreMvcOptionsSetup>());
services.TryAddEnumerable(
ServiceDescriptor.Transient<IConfigureOptions<RouteOptions>, MvcCoreRouteOptionsSetup>());
//
// Action Discovery
@ -138,9 +153,11 @@ namespace Microsoft.Framework.DependencyInjection
services.AddOptions();
services.AddRouting();
services.AddNotifier();
}
services.TryAddEnumerable(
ServiceDescriptor.Transient<IConfigureOptions<RouteOptions>, MvcRouteOptionsSetup>());
private class MvcBuilder : IMvcBuilder
{
public IServiceCollection Services { get; set; }
}
}
}

View File

@ -22,7 +22,7 @@ namespace Microsoft.AspNet.Mvc
/// </summary>
/// <param name="options">The <see cref="IOptions{MvcOptions}"/></param>
/// <param name="actionContext">The <see cref="IScopedInstance{ActionContext}"/></param>
public FormatFilter(IOptions<MvcFormatterMappingOptions> options, IScopedInstance<ActionContext> actionContext)
public FormatFilter(IOptions<MvcOptions> options, IScopedInstance<ActionContext> actionContext)
{
IsActive = true;
Format = GetFormat(actionContext.Value);

View File

@ -1,21 +0,0 @@
// 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;
using System.Collections.Generic;
namespace Microsoft.AspNet.Mvc
{
/// <summary>
/// Provides programmatic configuration for caching in the MVC framework.
/// </summary>
public class MvcCacheOptions
{
/// <summary>
/// Gets a Dictionary of CacheProfile Names, <see cref="CacheProfile"/> which are pre-defined settings for
/// <see cref="ResponseCacheFilter"/>.
/// </summary>
public IDictionary<string, CacheProfile> CacheProfiles { get; } =
new Dictionary<string, CacheProfile>(StringComparer.OrdinalIgnoreCase);
}
}

View File

@ -2,6 +2,7 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using Microsoft.AspNet.Http;
using Microsoft.AspNet.Mvc.ModelBinding;
using Microsoft.AspNet.Mvc.ModelBinding.Metadata;
using Microsoft.AspNet.Mvc.ModelBinding.Validation;
@ -12,9 +13,9 @@ namespace Microsoft.AspNet.Mvc
/// <summary>
/// Sets up default options for <see cref="MvcOptions"/>.
/// </summary>
public class CoreMvcOptionsSetup : ConfigureOptions<MvcOptions>
public class MvcCoreMvcOptionsSetup : ConfigureOptions<MvcOptions>
{
public CoreMvcOptionsSetup()
public MvcCoreMvcOptionsSetup()
: base(ConfigureMvc)
{
Order = DefaultOrder.DefaultFrameworkSortOrder;
@ -60,8 +61,8 @@ namespace Microsoft.AspNet.Mvc
// Any 'known' types that we bind should be marked as excluded from validation.
options.ValidationExcludeFilters.Add(typeof(System.Threading.CancellationToken));
options.ValidationExcludeFilters.Add(typeof(Http.IFormFile));
options.ValidationExcludeFilters.Add(typeof(Http.IFormCollection));
options.ValidationExcludeFilters.Add(typeof(IFormFile));
options.ValidationExcludeFilters.Add(typeof(IFormCollection));
}
}
}

View File

@ -9,9 +9,9 @@ namespace Microsoft.AspNet.Mvc
/// <summary>
/// Sets up MVC default options for <see cref="RouteOptions"/>.
/// </summary>
public class MvcRouteOptionsSetup : ConfigureOptions<RouteOptions>
public class MvcCoreRouteOptionsSetup : ConfigureOptions<RouteOptions>
{
public MvcRouteOptionsSetup()
public MvcCoreRouteOptionsSetup()
: base(ConfigureRouting)
{
Order = DefaultOrder.DefaultFrameworkSortOrder;

View File

@ -1,17 +0,0 @@
// 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.
namespace Microsoft.AspNet.Mvc
{
/// <summary>
/// Provides programmatic configuration for formatter mappings in the MVC framework.
/// </summary>
public class MvcFormatterMappingOptions
{
/// <summary>
/// Used to specify mapping between the URL Format and corresponding
/// <see cref="Net.Http.Headers.MediaTypeHeaderValue"/>.
/// </summary>
public FormatterMappings FormatterMappings { get; } = new FormatterMappings();
}
}

View File

@ -19,8 +19,10 @@ namespace Microsoft.AspNet.Mvc
public MvcOptions()
{
CacheProfiles = new Dictionary<string, CacheProfile>(StringComparer.OrdinalIgnoreCase);
Conventions = new List<IApplicationModelConvention>();
Filters = new List<IFilterMetadata>();
FormatterMappings = new FormatterMappings();
InputFormatters = new List<IInputFormatter>();
OutputFormatters = new List<IOutputFormatter>();
ModelBinders = new List<IModelBinder>();
@ -30,6 +32,18 @@ namespace Microsoft.AspNet.Mvc
ValueProviderFactories = new List<IValueProviderFactory>();
}
/// <summary>
/// Gets a Dictionary of CacheProfile Names, <see cref="CacheProfile"/> which are pre-defined settings for
/// <see cref="ResponseCacheFilter"/>.
/// </summary>
public IDictionary<string, CacheProfile> CacheProfiles { get; }
/// <summary>
/// Gets a list of <see cref="IApplicationModelConvention"/> instances that will be applied to
/// the <see cref="ApplicationModel"/> when discovering actions.
/// </summary>
public IList<IApplicationModelConvention> Conventions { get; }
/// <summary>
/// Gets a list of <see cref="IFilterMetadata"/> which are used to construct filters that
/// apply to all actions.
@ -37,20 +51,16 @@ namespace Microsoft.AspNet.Mvc
public ICollection<IFilterMetadata> Filters { get; }
/// <summary>
/// Gets a list of <see cref="IOutputFormatter"/>s that are used by this application.
/// Used to specify mapping between the URL Format and corresponding
/// <see cref="Net.Http.Headers.MediaTypeHeaderValue"/>.
/// </summary>
public IList<IOutputFormatter> OutputFormatters { get; }
public FormatterMappings FormatterMappings { get; }
/// <summary>
/// Gets a list of <see cref="IInputFormatter"/>s that are used by this application.
/// </summary>
public IList<IInputFormatter> InputFormatters { get; }
/// <summary>
/// Gets a list of <see cref="IModelBinder"/>s used by this application.
/// </summary>
public IList<IModelBinder> ModelBinders { get; }
/// <summary>
/// Gets or sets the maximum number of validation errors that are allowed by this application before further
/// errors are ignored.
@ -70,26 +80,9 @@ namespace Microsoft.AspNet.Mvc
}
/// <summary>
/// Gets a list of <see cref="IModelValidatorProvider"/>s used by this application.
/// Gets a list of <see cref="IModelBinder"/>s used by this application.
/// </summary>
public IList<IModelValidatorProvider> ModelValidatorProviders { get; }
/// <summary>
/// Gets a list of <see cref="IValueProviderFactory"/> used by this application.
/// </summary>
public IList<IValueProviderFactory> ValueProviderFactories { get; }
/// <summary>
/// Gets a list of <see cref="IApplicationModelConvention"/> instances that will be applied to
/// the <see cref="ApplicationModel"/> when discovering actions.
/// </summary>
public IList<IApplicationModelConvention> Conventions { get; }
/// <summary>
/// Gets or sets the flag which causes content negotiation to ignore Accept header
/// when it contains the media type */*. <see langword="false"/> by default.
/// </summary>
public bool RespectBrowserAcceptHeader { get; set; }
public IList<IModelBinder> ModelBinders { get; }
/// <summary>
/// Gets a list of <see cref="IMetadataDetailsProvider"/> instances that will be used to
@ -106,9 +99,30 @@ namespace Microsoft.AspNet.Mvc
/// </remarks>
public IList<IMetadataDetailsProvider> ModelMetadataDetailsProviders { get; }
/// <summary>
/// Gets a list of <see cref="IModelValidatorProvider"/>s used by this application.
/// </summary>
public IList<IModelValidatorProvider> ModelValidatorProviders { get; }
/// <summary>
/// Gets a list of <see cref="IOutputFormatter"/>s that are used by this application.
/// </summary>
public IList<IOutputFormatter> OutputFormatters { get; }
/// <summary>
/// Gets or sets the flag which causes content negotiation to ignore Accept header
/// when it contains the media type */*. <see langword="false"/> by default.
/// </summary>
public bool RespectBrowserAcceptHeader { get; set; }
/// <summary>
/// Gets a list of <see cref="IExcludeTypeValidationFilter"/>s that are used by this application.
/// </summary>
public IList<IExcludeTypeValidationFilter> ValidationExcludeFilters { get; }
/// <summary>
/// Gets a list of <see cref="IValueProviderFactory"/> used by this application.
/// </summary>
public IList<IValueProviderFactory> ValueProviderFactories { get; }
}
}

View File

@ -88,7 +88,7 @@ namespace Microsoft.AspNet.Mvc
public IFilterMetadata CreateInstance([NotNull] IServiceProvider serviceProvider)
{
var optionsAccessor = serviceProvider.GetRequiredService<IOptions<MvcCacheOptions>>();
var optionsAccessor = serviceProvider.GetRequiredService<IOptions<MvcOptions>>();
CacheProfile selectedProfile = null;
if (CacheProfileName != null)

View File

@ -0,0 +1,52 @@
// 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;
using Microsoft.AspNet.Cors.Core;
using Microsoft.AspNet.Mvc;
using Microsoft.AspNet.Mvc.ApplicationModels;
using Microsoft.Framework.Internal;
namespace Microsoft.Framework.DependencyInjection
{
public static class MvcJsonMvcBuilderExtensions
{
public static IMvcBuilder AddCors([NotNull] this IMvcBuilder builder)
{
AddCorsServices(builder.Services);
return builder;
}
public static IMvcBuilder AddCors(
[NotNull] this IMvcBuilder builder,
[NotNull] Action<CorsOptions> setupAction)
{
AddCorsServices(builder.Services);
if (setupAction != null)
{
builder.Services.Configure(setupAction);
}
return builder;
}
public static IMvcBuilder ConfigureCors(
[NotNull] this IMvcBuilder builder,
[NotNull] Action<CorsOptions> setupAction)
{
builder.Services.Configure(setupAction);
return builder;
}
// Internal for testing.
internal static void AddCorsServices(IServiceCollection services)
{
services.AddCors();
services.TryAddEnumerable(
ServiceDescriptor.Transient<IApplicationModelProvider, CorsApplicationModelProvider>());
services.TryAddTransient<CorsAuthorizationFilter, CorsAuthorizationFilter>();
}
}
}

View File

@ -0,0 +1,25 @@
// 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.Mvc;
using Microsoft.Framework.Internal;
using Microsoft.Framework.OptionsModel;
namespace Microsoft.Framework.DependencyInjection
{
public static class MvcDataAnnotationsMvcBuilderExtensions
{
public static IMvcBuilder AddDataAnnotations([NotNull] this IMvcBuilder builder)
{
AddDataAnnotationsServices(builder.Services);
return builder;
}
// Internal for testing.
internal static void AddDataAnnotationsServices(IServiceCollection services)
{
services.TryAddEnumerable(
ServiceDescriptor.Transient<IConfigureOptions<MvcOptions>, MvcDataAnnotationsMvcOptionsSetup>());
}
}
}

View File

@ -1,20 +1,18 @@
// 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.Xml.Linq;
using Microsoft.AspNet.Mvc.ModelBinding.Metadata;
using Microsoft.AspNet.Mvc.ModelBinding.Validation;
using Microsoft.Framework.OptionsModel;
using Newtonsoft.Json.Linq;
namespace Microsoft.AspNet.Mvc
{
/// <summary>
/// Sets up default options for <see cref="MvcOptions"/>.
/// </summary>
public class MvcOptionsSetup : ConfigureOptions<MvcOptions>
public class MvcDataAnnotationsMvcOptionsSetup : ConfigureOptions<MvcOptions>
{
public MvcOptionsSetup()
public MvcDataAnnotationsMvcOptionsSetup()
: base(ConfigureMvc)
{
Order = DefaultOrder.DefaultFrameworkSortOrder + 1;
@ -24,9 +22,6 @@ namespace Microsoft.AspNet.Mvc
{
options.ModelMetadataDetailsProviders.Add(new DataAnnotationsMetadataProvider());
options.ModelValidatorProviders.Add(new DataAnnotationsModelValidatorProvider());
options.ValidationExcludeFilters.Add(typeof(JToken));
}
}
}

View File

@ -0,0 +1,49 @@
// 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;
using Microsoft.AspNet.Mvc;
using Microsoft.Framework.Internal;
using Microsoft.Framework.OptionsModel;
using Newtonsoft.Json;
namespace Microsoft.Framework.DependencyInjection
{
public static class MvcJsonMvcBuilderExtensions
{
public static IMvcBuilder AddJsonFormatters([NotNull] this IMvcBuilder builder)
{
AddJsonFormatterServices(builder.Services);
return builder;
}
public static IMvcBuilder AddJsonFormatters(
[NotNull] this IMvcBuilder builder,
[NotNull] Action<JsonSerializerSettings> setupAction)
{
AddJsonFormatterServices(builder.Services);
if (setupAction != null)
{
builder.Services.Configure<MvcJsonOptions>((options) => setupAction(options.SerializerSettings));
}
return builder;
}
public static IMvcBuilder ConfigureJson(
[NotNull] this IMvcBuilder builder,
[NotNull] Action<MvcJsonOptions> setupAction)
{
builder.Services.Configure(setupAction);
return builder;
}
// Internal for testing.
internal static void AddJsonFormatterServices(IServiceCollection services)
{
services.TryAddEnumerable(
ServiceDescriptor.Transient<IConfigureOptions<MvcOptions>, MvcJsonMvcOptionsSetup>());
}
}
}

View File

@ -2,13 +2,15 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using Microsoft.Framework.OptionsModel;
using Microsoft.Net.Http.Headers;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
namespace Microsoft.AspNet.Mvc
{
public class JsonMvcOptionsSetup : ConfigureOptions<MvcOptions>
public class MvcJsonMvcOptionsSetup : ConfigureOptions<MvcOptions>
{
public JsonMvcOptionsSetup(IOptions<MvcJsonOptions> jsonOptions)
public MvcJsonMvcOptionsSetup(IOptions<MvcJsonOptions> jsonOptions)
: base((_) => ConfigureMvc(_, jsonOptions.Options.SerializerSettings))
{
Order = DefaultOrder.DefaultFrameworkSortOrder + 10;
@ -20,6 +22,10 @@ namespace Microsoft.AspNet.Mvc
options.InputFormatters.Add(new JsonInputFormatter(serializerSettings));
options.InputFormatters.Add(new JsonPatchInputFormatter(serializerSettings));
options.FormatterMappings.SetMediaTypeMappingForFormat("json", MediaTypeHeaderValue.Parse("application/json"));
options.ValidationExcludeFilters.Add(typeof(JToken));
}
}
}

View File

@ -0,0 +1,93 @@
// 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;
using Microsoft.AspNet.Mvc;
using Microsoft.AspNet.Mvc.Razor;
using Microsoft.AspNet.Mvc.Razor.Compilation;
using Microsoft.AspNet.Mvc.Razor.Directives;
using Microsoft.Framework.Caching.Memory;
using Microsoft.Framework.Internal;
using Microsoft.Framework.OptionsModel;
namespace Microsoft.Framework.DependencyInjection
{
public static class MvcRazorMvcBuilderExtensions
{
public static IMvcBuilder AddRazorViewEngine([NotNull] this IMvcBuilder builder)
{
builder.AddViews();
AddRazorViewEngineServices(builder.Services);
return builder;
}
public static IMvcBuilder AddRazorViewEngine(
[NotNull] this IMvcBuilder builder,
[NotNull] Action<RazorViewEngineOptions> setupAction)
{
builder.AddViews();
AddRazorViewEngineServices(builder.Services);
if (setupAction != null)
{
builder.Services.Configure(setupAction);
}
return builder;
}
public static IMvcBuilder ConfigureRazorViewEngine(
[NotNull] this IMvcBuilder builder,
[NotNull] Action<RazorViewEngineOptions> setupAction)
{
builder.Services.Configure(setupAction);
return builder;
}
// Internal for testing.
internal static void AddRazorViewEngineServices(IServiceCollection services)
{
services.TryAddEnumerable(
ServiceDescriptor.Transient<IConfigureOptions<MvcViewOptions>, MvcRazorMvcViewOptionsSetup>());
services.TryAddEnumerable(
ServiceDescriptor.Transient<IConfigureOptions<RazorViewEngineOptions>, RazorViewEngineOptionsSetup>());
// Caches view locations that are valid for the lifetime of the application.
services.TryAddSingleton<IViewLocationCache, DefaultViewLocationCache>();
services.TryAdd(ServiceDescriptor.Singleton<IChunkTreeCache>(serviceProvider =>
{
var cachedFileProvider = serviceProvider.GetRequiredService<IOptions<RazorViewEngineOptions>>();
return new DefaultChunkTreeCache(cachedFileProvider.Options.FileProvider);
}));
// The host is designed to be discarded after consumption and is very inexpensive to initialize.
services.TryAddTransient<IMvcRazorHost, MvcRazorHost>();
// Caches compilation artifacts across the lifetime of the application.
services.TryAddSingleton<ICompilerCache, CompilerCache>();
// This caches compilation related details that are valid across the lifetime of the application
// and is required to be a singleton.
services.TryAddSingleton<ICompilationService, RoslynCompilationService>();
// Both the compiler cache and roslyn compilation service hold on the compilation related
// caches. RazorCompilation service is just an adapter service, and it is transient to ensure
// the IMvcRazorHost dependency does not maintain state.
services.TryAddTransient<IRazorCompilationService, RazorCompilationService>();
// The ViewStartProvider needs to be able to consume scoped instances of IRazorPageFactory
services.TryAddScoped<IViewStartProvider, ViewStartProvider>();
services.TryAddTransient<IRazorViewFactory, RazorViewFactory>();
services.TryAddSingleton<IRazorPageActivator, RazorPageActivator>();
// Virtual path view factory needs to stay scoped so views can get get scoped services.
services.TryAddScoped<IRazorPageFactory, VirtualPathRazorPageFactory>();
// Only want one ITagHelperActivator so it can cache Type activation information. Types won't conflict.
services.TryAddSingleton<ITagHelperActivator, DefaultTagHelperActivator>();
// Consumed by the Cache tag helper to cache results across the lifetime of the application.
services.TryAddSingleton<IMemoryCache, MemoryCache>();
}
}
}

View File

@ -0,0 +1,21 @@
// 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.Framework.OptionsModel;
namespace Microsoft.AspNet.Mvc.Razor
{
public class MvcRazorMvcViewOptionsSetup : ConfigureOptions<MvcViewOptions>
{
public MvcRazorMvcViewOptionsSetup()
: base(ConfigureMvc)
{
Order = DefaultOrder.DefaultFrameworkSortOrder;
}
public static void ConfigureMvc(MvcViewOptions options)
{
options.ViewEngines.Add(typeof(RazorViewEngine));
}
}
}

View File

@ -0,0 +1,102 @@
// 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;
using Microsoft.AspNet.Mvc;
using Microsoft.AspNet.Mvc.Rendering;
using Microsoft.AspNet.Mvc.ViewComponents;
using Microsoft.Framework.Internal;
using Microsoft.Framework.OptionsModel;
namespace Microsoft.Framework.DependencyInjection
{
public static class MvcViewFeaturesMvcBuilderExtensions
{
public static IMvcBuilder AddViews([NotNull] this IMvcBuilder builder)
{
builder.AddDataAnnotations();
AddViewServices(builder.Services);
return builder;
}
public static IMvcBuilder AddViews(
[NotNull] this IMvcBuilder builder,
[NotNull] Action<MvcViewOptions> setupAction)
{
builder.AddDataAnnotations();
AddViewServices(builder.Services);
if (setupAction != null)
{
builder.Services.Configure(setupAction);
}
return builder;
}
public static IMvcBuilder ConfigureViews(
[NotNull] this IMvcBuilder builder,
[NotNull] Action<MvcViewOptions> setupAction)
{
builder.Services.Configure(setupAction);
return builder;
}
// Internal for testing.
internal static void AddViewServices(IServiceCollection services)
{
services.AddDataProtection();
services.AddAntiforgery();
services.AddWebEncoders();
services.TryAddEnumerable(
ServiceDescriptor.Transient<IConfigureOptions<MvcViewOptions>, MvcViewOptionsSetup>());
//
// View Engine and related infrastructure
//
// The provider is inexpensive to initialize and provides ViewEngines that may require request
// specific services.
services.TryAddScoped<ICompositeViewEngine, CompositeViewEngine>();
// Support for activating ViewDataDictionary
services.TryAddEnumerable(
ServiceDescriptor
.Transient<IControllerPropertyActivator, ViewDataDictionaryControllerPropertyActivator>());
//
// HTML Helper
//
services.TryAddTransient<IHtmlHelper, HtmlHelper>();
services.TryAddTransient(typeof(IHtmlHelper<>), typeof(HtmlHelper<>));
// DefaultHtmlGenerator is pretty much stateless but depends on IUrlHelper, which is scoped.
// Therefore it too is scoped.
services.TryAddScoped<IHtmlGenerator, DefaultHtmlGenerator>();
//
// JSON Helper
//
services.TryAddSingleton<IJsonHelper, JsonHelper>();
services.TryAdd(ServiceDescriptor.Singleton<JsonOutputFormatter>(serviceProvider =>
{
var options = serviceProvider.GetRequiredService<IOptions<MvcJsonOptions>>().Options;
return new JsonOutputFormatter(options.SerializerSettings);
}));
//
// View Components
//
// These do caching so they should stay singleton
services.TryAddSingleton<IViewComponentSelector, DefaultViewComponentSelector>();
services.TryAddSingleton<IViewComponentActivator, DefaultViewComponentActivator>();
services.TryAddSingleton<
IViewComponentDescriptorCollectionProvider,
DefaultViewComponentDescriptorCollectionProvider>();
services.TryAddTransient<IViewComponentDescriptorProvider, DefaultViewComponentDescriptorProvider>();
services.TryAddSingleton<IViewComponentInvokerFactory, DefaultViewComponentInvokerFactory>();
services.TryAddTransient<IViewComponentHelper, DefaultViewComponentHelper>();
}
}
}

View File

@ -2,7 +2,6 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using Microsoft.AspNet.Mvc.ModelBinding.Validation;
using Microsoft.AspNet.Mvc.Razor;
using Microsoft.Framework.OptionsModel;
namespace Microsoft.AspNet.Mvc
@ -20,9 +19,6 @@ namespace Microsoft.AspNet.Mvc
public static void ConfigureMvc(MvcViewOptions options)
{
// Set up ViewEngines
options.ViewEngines.Add(typeof(RazorViewEngine));
// Set up client validators
options.ClientModelValidatorProviders.Add(new DefaultClientModelValidatorProvider());
options.ClientModelValidatorProviders.Add(new DataAnnotationsClientModelValidatorProvider());

View File

@ -12,6 +12,7 @@
"Microsoft.AspNet.Antiforgery": "1.0.0-*",
"Microsoft.AspNet.Diagnostics.Abstractions": "1.0.0-*",
"Microsoft.AspNet.Mvc.Core": "6.0.0-*",
"Microsoft.AspNet.Mvc.DataAnnotations": "6.0.0-*",
"Microsoft.AspNet.Mvc.Formatters.Json": "6.0.0-*",
"Microsoft.Framework.BufferEntryCollection.Sources": { "version": "1.0.0-*", "type": "build" },
"Microsoft.Framework.ClosedGenericMatcher.Sources": { "version": "1.0.0-*", "type": "build" },

View File

@ -1,22 +0,0 @@
// 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.Framework.OptionsModel;
using Microsoft.Net.Http.Headers;
namespace Microsoft.AspNet.Mvc
{
public class JsonMvcFormatterMappingOptionsSetup : ConfigureOptions<MvcFormatterMappingOptions>
{
public JsonMvcFormatterMappingOptionsSetup()
: base(ConfigureMvc)
{
Order = DefaultOrder.DefaultFrameworkSortOrder + 10;
}
public static void ConfigureMvc(MvcFormatterMappingOptions options)
{
options.FormatterMappings.SetMediaTypeMappingForFormat("json", MediaTypeHeaderValue.Parse("application/json"));
}
}
}

View File

@ -3,20 +3,11 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using Microsoft.AspNet.Mvc;
using Microsoft.AspNet.Mvc.ApiExplorer;
using Microsoft.AspNet.Mvc.ApplicationModels;
using Microsoft.AspNet.Mvc.Razor;
using Microsoft.AspNet.Mvc.Razor.Compilation;
using Microsoft.AspNet.Mvc.Razor.Directives;
using Microsoft.AspNet.Mvc.Rendering;
using Microsoft.AspNet.Mvc.ViewComponents;
using Microsoft.Framework.Caching.Memory;
using Microsoft.Framework.Internal;
using Microsoft.Framework.OptionsModel;
namespace Microsoft.Framework.DependencyInjection
{
@ -24,35 +15,28 @@ namespace Microsoft.Framework.DependencyInjection
{
public static IServiceCollection AddMvc([NotNull] this IServiceCollection services)
{
services.AddMinimalMvc();
var builder = services.AddMvcCore();
ConfigureDefaultServices(services);
AddMvcServices(services);
builder.AddApiExplorer();
builder.AddAuthorization();
builder.AddCors();
builder.AddDataAnnotations();
builder.AddFormatterMappings();
builder.AddJsonFormatters();
builder.AddViews();
builder.AddRazorViewEngine();
return services;
}
/// <summary>
/// Configures a set of <see cref="MvcFormatterMappingOptions"/> for the application.
/// Configures a set of <see cref="MvcViewOptions"/> for the application.
/// </summary>
/// <param name="services">The services available in the application.</param>
/// <param name="setupAction">The <see cref="MvcCacheOptions"/> which need to be configured.</param>
public static void ConfigureMvcCaching(
/// <param name="setupAction">The <see cref="MvcViewOptions"/> which need to be configured.</param>
public static void ConfigureMvcViews(
[NotNull] this IServiceCollection services,
[NotNull] Action<MvcCacheOptions> setupAction)
{
services.Configure(setupAction);
}
/// <summary>
/// Configures a set of <see cref="MvcFormatterMappingOptions"/> for the application.
/// </summary>
/// <param name="services">The services available in the application.</param>
/// <param name="setupAction">The <see cref="MvcFormatterMappingOptions"/> which need to be configured.</param>
public static void ConfigureMvcFormatterMappings(
[NotNull] this IServiceCollection services,
[NotNull] Action<MvcFormatterMappingOptions> setupAction)
[NotNull] Action<MvcViewOptions> setupAction)
{
services.Configure(setupAction);
}
@ -69,18 +53,6 @@ namespace Microsoft.Framework.DependencyInjection
services.Configure(setupAction);
}
/// <summary>
/// Configures a set of <see cref="MvcViewOptions"/> for the application.
/// </summary>
/// <param name="services">The services available in the application.</param>
/// <param name="setupAction">The <see cref="MvcViewOptions"/> which need to be configured.</param>
public static void ConfigureMvcViews(
[NotNull] this IServiceCollection services,
[NotNull] Action<MvcViewOptions> setupAction)
{
services.Configure(setupAction);
}
/// <summary>
/// Register the specified <paramref name="controllerTypes"/> as services and as a source for controller
/// discovery.
@ -129,116 +101,6 @@ namespace Microsoft.Framework.DependencyInjection
return WithControllersAsServices(services, controllerTypes.Select(type => type.AsType()));
}
// To enable unit testing
internal static void AddMvcServices(IServiceCollection services)
{
// Options - all of these are multi-registration
services.TryAddEnumerable(
ServiceDescriptor.Transient<IConfigureOptions<MvcOptions>, MvcOptionsSetup>());
services.TryAddEnumerable(
ServiceDescriptor.Transient<IConfigureOptions<MvcOptions>, JsonMvcOptionsSetup>());
services.TryAddEnumerable(
ServiceDescriptor
.Transient<IConfigureOptions<MvcFormatterMappingOptions>, JsonMvcFormatterMappingOptionsSetup>());
services.TryAddEnumerable(
ServiceDescriptor.Transient<IConfigureOptions<MvcViewOptions>, MvcViewOptionsSetup>());
services.TryAddEnumerable(
ServiceDescriptor
.Transient<IConfigureOptions<RazorViewEngineOptions>, RazorViewEngineOptionsSetup>());
// Cors
services.TryAddEnumerable(
ServiceDescriptor.Transient<IApplicationModelProvider, CorsApplicationModelProvider>());
services.TryAddTransient<CorsAuthorizationFilter, CorsAuthorizationFilter>();
// Auth
services.TryAddEnumerable(
ServiceDescriptor.Transient<IApplicationModelProvider, AuthorizationApplicationModelProvider>());
// Support for activating ViewDataDictionary
services.TryAddEnumerable(
ServiceDescriptor
.Transient<IControllerPropertyActivator, ViewDataDictionaryControllerPropertyActivator>());
// Formatter Mappings
services.TryAddTransient<FormatFilter, FormatFilter>();
// JsonOutputFormatter should use the SerializerSettings on MvcOptions
services.TryAdd(ServiceDescriptor.Singleton<JsonOutputFormatter>(serviceProvider =>
{
var options = serviceProvider.GetRequiredService<IOptions<MvcJsonOptions>>().Options;
return new JsonOutputFormatter(options.SerializerSettings);
}));
// Razor, Views and runtime compilation
// The provider is inexpensive to initialize and provides ViewEngines that may require request
// specific services.
services.TryAddScoped<ICompositeViewEngine, CompositeViewEngine>();
// Caches view locations that are valid for the lifetime of the application.
services.TryAddSingleton<IViewLocationCache, DefaultViewLocationCache>();
services.TryAdd(ServiceDescriptor.Singleton<IChunkTreeCache>(serviceProvider =>
{
var cachedFileProvider = serviceProvider.GetRequiredService<IOptions<RazorViewEngineOptions>>();
return new DefaultChunkTreeCache(cachedFileProvider.Options.FileProvider);
}));
// The host is designed to be discarded after consumption and is very inexpensive to initialize.
services.TryAddTransient<IMvcRazorHost, MvcRazorHost>();
// Caches compilation artifacts across the lifetime of the application.
services.TryAddSingleton<ICompilerCache, CompilerCache>();
// This caches compilation related details that are valid across the lifetime of the application
// and is required to be a singleton.
services.TryAddSingleton<ICompilationService, RoslynCompilationService>();
// Both the compiler cache and roslyn compilation service hold on the compilation related
// caches. RazorCompilation service is just an adapter service, and it is transient to ensure
// the IMvcRazorHost dependency does not maintain state.
services.TryAddTransient<IRazorCompilationService, RazorCompilationService>();
// The ViewStartProvider needs to be able to consume scoped instances of IRazorPageFactory
services.TryAddScoped<IViewStartProvider, ViewStartProvider>();
services.TryAddTransient<IRazorViewFactory, RazorViewFactory>();
services.TryAddSingleton<IRazorPageActivator, RazorPageActivator>();
// Virtual path view factory needs to stay scoped so views can get get scoped services.
services.TryAddScoped<IRazorPageFactory, VirtualPathRazorPageFactory>();
// View and rendering helpers
services.TryAddTransient<IHtmlHelper, HtmlHelper>();
services.TryAddTransient(typeof(IHtmlHelper<>), typeof(HtmlHelper<>));
services.TryAddSingleton<IJsonHelper, JsonHelper>();
// Only want one ITagHelperActivator so it can cache Type activation information. Types won't conflict.
services.TryAddSingleton<ITagHelperActivator, DefaultTagHelperActivator>();
// Consumed by the Cache tag helper to cache results across the lifetime of the application.
services.TryAddSingleton<IMemoryCache, MemoryCache>();
// DefaultHtmlGenerator is pretty much stateless but depends on IUrlHelper, which is scoped.
// Therefore it too is scoped.
services.TryAddScoped<IHtmlGenerator, DefaultHtmlGenerator>();
// These do caching so they should stay singleton
services.TryAddSingleton<IViewComponentSelector, DefaultViewComponentSelector>();
services.TryAddSingleton<IViewComponentActivator, DefaultViewComponentActivator>();
services.TryAddSingleton<
IViewComponentDescriptorCollectionProvider,
DefaultViewComponentDescriptorCollectionProvider>();
services.TryAddTransient<IViewComponentDescriptorProvider, DefaultViewComponentDescriptorProvider>();
services.TryAddSingleton<IViewComponentInvokerFactory, DefaultViewComponentInvokerFactory>();
services.TryAddTransient<IViewComponentHelper, DefaultViewComponentHelper>();
// Api Description
services.TryAddSingleton<IApiDescriptionGroupCollectionProvider, ApiDescriptionGroupCollectionProvider>();
services.TryAddEnumerable(
ServiceDescriptor.Transient<IApiDescriptionProvider, DefaultApiDescriptionProvider>());
}
/// <summary>
/// Adds Mvc localization to the application.
/// </summary>
@ -266,14 +128,5 @@ namespace Microsoft.Framework.DependencyInjection
return services;
}
private static void ConfigureDefaultServices(IServiceCollection services)
{
services.AddDataProtection();
services.AddAntiforgery();
services.AddCors();
services.AddAuthorization();
services.AddWebEncoders();
}
}
}

View File

@ -43,7 +43,7 @@ namespace Microsoft.AspNet.Mvc
var resultExecutingContext = mockObjects.CreateResultExecutingContext();
var resourceExecutingContext = mockObjects.CreateResourceExecutingContext(new IFilterMetadata[] { });
var filter = new FormatFilter(mockObjects.IOptions, mockObjects.ScopedInstance);
var filter = new FormatFilter(mockObjects.OptionsManager, mockObjects.ScopedInstance);
// Act
filter.OnResourceExecuting(resourceExecutingContext);
@ -90,7 +90,7 @@ namespace Microsoft.AspNet.Mvc
ac,
new IFilterMetadata[] { });
var filter = new FormatFilter(mockObjects.IOptions, mockObjects.ScopedInstance);
var filter = new FormatFilter(mockObjects.OptionsManager, mockObjects.ScopedInstance);
// Act
filter.OnResourceExecuting(resourceExecutingContext);
@ -118,11 +118,11 @@ namespace Microsoft.AspNet.Mvc
var resultExecutingContext = mockObjects.CreateResultExecutingContext();
var resourceExecutingContext = mockObjects.CreateResourceExecutingContext(new IFilterMetadata[] { });
mockObjects.MockFormatterMappingOptions.FormatterMappings.SetMediaTypeMappingForFormat(
mockObjects.Options.FormatterMappings.SetMediaTypeMappingForFormat(
format,
MediaTypeHeaderValue.Parse(contentType));
var filter = new FormatFilter(mockObjects.IOptions, mockObjects.ScopedInstance);
var filter = new FormatFilter(mockObjects.OptionsManager, mockObjects.ScopedInstance);
// Act
filter.OnResourceExecuting(resourceExecutingContext);
@ -145,7 +145,7 @@ namespace Microsoft.AspNet.Mvc
var mockObjects = new MockObjects(format, place);
var resourceExecutingContext = mockObjects.CreateResourceExecutingContext(new IFilterMetadata[] { });
var filter = new FormatFilter(mockObjects.IOptions, mockObjects.ScopedInstance);
var filter = new FormatFilter(mockObjects.OptionsManager, mockObjects.ScopedInstance);
// Act
filter.OnResourceExecuting(resourceExecutingContext);
@ -162,7 +162,7 @@ namespace Microsoft.AspNet.Mvc
var mockObjects = new MockObjects();
var resourceExecutingContext = mockObjects.CreateResourceExecutingContext(new IFilterMetadata[] { });
var filter = new FormatFilter(mockObjects.IOptions, mockObjects.ScopedInstance);
var filter = new FormatFilter(mockObjects.OptionsManager, mockObjects.ScopedInstance);
// Act
filter.OnResourceExecuting(resourceExecutingContext);
@ -184,7 +184,7 @@ namespace Microsoft.AspNet.Mvc
var mockObjects = new MockObjects(format, place);
var resourceExecutingContext = mockObjects.CreateResourceExecutingContext(new IFilterMetadata[] { produces });
var filter = new FormatFilter(mockObjects.IOptions, mockObjects.ScopedInstance);
var filter = new FormatFilter(mockObjects.OptionsManager, mockObjects.ScopedInstance);
// Act
filter.OnResourceExecuting(resourceExecutingContext);
@ -201,11 +201,11 @@ namespace Microsoft.AspNet.Mvc
var mockObjects = new MockObjects("xml", FormatSource.RouteData);
var resourceExecutingContext = mockObjects.CreateResourceExecutingContext(new IFilterMetadata[] { produces });
mockObjects.MockFormatterMappingOptions.FormatterMappings.SetMediaTypeMappingForFormat(
mockObjects.Options.FormatterMappings.SetMediaTypeMappingForFormat(
"xml",
MediaTypeHeaderValue.Parse("application/xml"));
var filter = new FormatFilter(mockObjects.IOptions, mockObjects.ScopedInstance);
var filter = new FormatFilter(mockObjects.OptionsManager, mockObjects.ScopedInstance);
// Act
filter.OnResourceExecuting(resourceExecutingContext);
@ -222,11 +222,11 @@ namespace Microsoft.AspNet.Mvc
var mockObjects = new MockObjects("xml", FormatSource.RouteData);
var resourceExecutingContext = mockObjects.CreateResourceExecutingContext(new IFilterMetadata[] { produces });
mockObjects.MockFormatterMappingOptions.FormatterMappings.SetMediaTypeMappingForFormat(
mockObjects.Options.FormatterMappings.SetMediaTypeMappingForFormat(
"xml",
MediaTypeHeaderValue.Parse("application/xml;version=1"));
var filter = new FormatFilter(mockObjects.IOptions, mockObjects.ScopedInstance);
var filter = new FormatFilter(mockObjects.OptionsManager, mockObjects.ScopedInstance);
// Act
filter.OnResourceExecuting(resourceExecutingContext);
@ -248,11 +248,11 @@ namespace Microsoft.AspNet.Mvc
var mockObjects = new MockObjects(format, place);
var resourceExecutingContext = mockObjects.CreateResourceExecutingContext(new IFilterMetadata[] { produces });
mockObjects.MockFormatterMappingOptions.FormatterMappings.SetMediaTypeMappingForFormat(
mockObjects.Options.FormatterMappings.SetMediaTypeMappingForFormat(
"xml",
MediaTypeHeaderValue.Parse("application/xml"));
var filter = new FormatFilter(mockObjects.IOptions, mockObjects.ScopedInstance);
var filter = new FormatFilter(mockObjects.OptionsManager, mockObjects.ScopedInstance);
// Act
filter.OnResourceExecuting(resourceExecutingContext);
@ -271,7 +271,7 @@ namespace Microsoft.AspNet.Mvc
// Arrange
var mockObjects = new MockObjects(format, place);
var resourceExecutingContext = mockObjects.CreateResourceExecutingContext(new IFilterMetadata[] { });
var filter = new FormatFilter(mockObjects.IOptions, mockObjects.ScopedInstance);
var filter = new FormatFilter(mockObjects.OptionsManager, mockObjects.ScopedInstance);
// Act
filter.OnResourceExecuting(resourceExecutingContext);
@ -294,7 +294,7 @@ namespace Microsoft.AspNet.Mvc
var mockObjects = new MockObjects(format, place);
var resultExecutingContext = mockObjects.CreateResultExecutingContext();
var filterAttribute = new FormatFilterAttribute();
var filter = new FormatFilter(mockObjects.IOptions, mockObjects.ScopedInstance);
var filter = new FormatFilter(mockObjects.OptionsManager, mockObjects.ScopedInstance);
// Act and Assert
Assert.Equal(expected, filter.IsActive);
@ -318,13 +318,12 @@ namespace Microsoft.AspNet.Mvc
private class MockObjects
{
public MvcOptions MockOptions { get; private set; }
public MvcFormatterMappingOptions MockFormatterMappingOptions { get; private set; }
public MvcOptions Options { get; private set; }
public HttpContext MockHttpContext { get; private set; }
public ActionContext MockActionContext { get; private set; }
public IScopedInstance<ActionContext> ScopedInstance { get; private set; }
public IOptions<MvcFormatterMappingOptions> IOptions { get; private set; }
public IOptions<MvcOptions> OptionsManager { get; private set; }
public MockObjects(string format = null, FormatSource? place = null)
{
@ -383,24 +382,21 @@ namespace Microsoft.AspNet.Mvc
string format = null,
FormatSource? place = null)
{
OptionsManager = new TestOptionsManager<MvcOptions>();
// Setup options on mock service provider
MockOptions = new MvcOptions();
MockFormatterMappingOptions = new MvcFormatterMappingOptions();
Options = OptionsManager.Options;
// Set up default output formatters.
MockOptions.OutputFormatters.Add(new HttpNoContentOutputFormatter());
MockOptions.OutputFormatters.Add(new StringOutputFormatter());
MockOptions.OutputFormatters.Add(new JsonOutputFormatter());
Options.OutputFormatters.Add(new HttpNoContentOutputFormatter());
Options.OutputFormatters.Add(new StringOutputFormatter());
Options.OutputFormatters.Add(new JsonOutputFormatter());
// Set up default mapping for json extensions to content type
MockFormatterMappingOptions.FormatterMappings.SetMediaTypeMappingForFormat(
Options.FormatterMappings.SetMediaTypeMappingForFormat(
"json",
MediaTypeHeaderValue.Parse("application/json"));
var mvcOptions = new Mock<IOptions<MvcFormatterMappingOptions>>();
mvcOptions.Setup(o => o.Options).Returns(MockFormatterMappingOptions);
IOptions = mvcOptions.Object;
// Setup MVC services on mock service provider
MockActionContext = CreateMockActionContext(httpContext, format, place);
var scopedInstance = new Mock<IScopedInstance<ActionContext>>();

View File

@ -111,9 +111,7 @@ namespace Microsoft.AspNet.Mvc
private static IServiceProvider GetServiceProvider()
{
var optionsSetup = new MvcOptionsSetup();
var options = new MvcOptions();
optionsSetup.Configure(options);
var optionsAccessor = new Mock<IOptions<MvcOptions>>();
optionsAccessor.SetupGet(o => o.Options).Returns(options);

View File

@ -8,6 +8,7 @@ using Microsoft.AspNet.Mvc.ActionConstraints;
using Microsoft.AspNet.Mvc.ApplicationModels;
using Microsoft.AspNet.Mvc.Core;
using Microsoft.AspNet.Mvc.Filters;
using Microsoft.AspNet.Routing;
using Microsoft.Framework.DependencyInjection;
using Microsoft.Framework.OptionsModel;
using Moq;
@ -125,7 +126,14 @@ namespace Microsoft.AspNet.Mvc
typeof(IConfigureOptions<MvcOptions>),
new Type[]
{
typeof(CoreMvcOptionsSetup),
typeof(MvcCoreMvcOptionsSetup),
}
},
{
typeof(IConfigureOptions<RouteOptions>),
new Type[]
{
typeof(MvcCoreRouteOptionsSetup),
}
},
{

View File

@ -6,13 +6,24 @@ using Xunit;
namespace Microsoft.AspNet.Mvc
{
public class MvcCacheOptionsTest
public class MvcOptionsTest
{
[Fact]
public void MaxValidationError_ThrowsIfValueIsOutOfRange()
{
// Arrange
var options = new MvcOptions();
// Act & Assert
var ex = Assert.Throws<ArgumentOutOfRangeException>(() => options.MaxModelValidationErrors = -1);
Assert.Equal("value", ex.ParamName);
}
[Fact]
public void ThrowsWhenMultipleCacheProfilesWithSameNameAreAdded()
{
// Arrange
var options = new MvcCacheOptions();
var options = new MvcOptions();
options.CacheProfiles.Add("HelloWorld", new CacheProfile { Duration = 10 });
// Act & Assert

View File

@ -1,22 +0,0 @@
// 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;
using Xunit;
namespace Microsoft.AspNet.Mvc.Core.Test
{
public class MvcOptionsTests
{
[Fact]
public void MaxValidationError_ThrowsIfValueIsOutOfRange()
{
// Arrange
var options = new MvcOptions();
// Act & Assert
var ex = Assert.Throws<ArgumentOutOfRangeException>(() => options.MaxModelValidationErrors = -1);
Assert.Equal("value", ex.ParamName);
}
}
}

View File

@ -946,9 +946,7 @@ namespace Microsoft.AspNet.Mvc.Core.Test.ActionResults
private static IServiceProvider GetServiceProvider()
{
var optionsSetup = new MvcOptionsSetup();
var options = new MvcOptions();
optionsSetup.Configure(options);
var optionsAccessor = new Mock<IOptions<MvcOptions>>();
optionsAccessor.SetupGet(o => o.Options).Returns(options);

View File

@ -18,7 +18,8 @@ namespace Microsoft.AspNet.Mvc
public void CreateInstance_SelectsTheAppropriateCacheProfile(string profileName)
{
// Arrange
var responseCache = new ResponseCacheAttribute() {
var responseCache = new ResponseCacheAttribute()
{
CacheProfileName = profileName
};
var cacheProfiles = new Dictionary<string, CacheProfile>();
@ -173,29 +174,27 @@ namespace Microsoft.AspNet.Mvc
cacheProfiles.Add("Test", new CacheProfile { NoStore = false });
// Act
var filter = responseCache.CreateInstance(GetServiceProvider(cacheProfiles));
var filter = responseCache.CreateInstance(GetServiceProvider(cacheProfiles));
// Assert
Assert.NotNull(filter);
// Assert
Assert.NotNull(filter);
}
private IServiceProvider GetServiceProvider(Dictionary<string, CacheProfile> cacheProfiles)
{
var serviceProvider = new Mock<IServiceProvider>();
var optionsAccessor = new Mock<IOptions<MvcCacheOptions>>();
var options = new MvcCacheOptions();
var optionsAccessor = new TestOptionsManager<MvcOptions>();
if (cacheProfiles != null)
{
foreach (var p in cacheProfiles)
{
options.CacheProfiles.Add(p.Key, p.Value);
optionsAccessor.Options.CacheProfiles.Add(p.Key, p.Value);
}
}
optionsAccessor.SetupGet(o => o.Options).Returns(options);
serviceProvider
.Setup(s => s.GetService(typeof(IOptions<MvcCacheOptions>)))
.Returns(optionsAccessor.Object);
.Setup(s => s.GetService(typeof(IOptions<MvcOptions>)))
.Returns(optionsAccessor);
return serviceProvider.Object;
}

View File

@ -12,9 +12,9 @@ namespace Microsoft.AspNet.Mvc.IntegrationTests
public TestMvcOptions()
{
Options = new MvcOptions();
CoreMvcOptionsSetup.ConfigureMvc(Options);
MvcOptionsSetup.ConfigureMvc(Options);
JsonMvcOptionsSetup.ConfigureMvc(Options, SerializerSettingsProvider.CreateSerializerSettings());
MvcCoreMvcOptionsSetup.ConfigureMvc(Options);
MvcDataAnnotationsMvcOptionsSetup.ConfigureMvc(Options);
MvcJsonMvcOptionsSetup.ConfigureMvc(Options, SerializerSettingsProvider.CreateSerializerSettings());
}
public MvcOptions Options { get; }

View File

@ -7,6 +7,7 @@ using System.Xml.Linq;
using Microsoft.AspNet.Mvc.ModelBinding;
using Microsoft.AspNet.Mvc.ModelBinding.Validation;
using Microsoft.AspNet.Mvc.Razor;
using Microsoft.Framework.DependencyInjection;
using Microsoft.Framework.OptionsModel;
using Newtonsoft.Json.Linq;
using Xunit;
@ -18,62 +19,46 @@ namespace Microsoft.AspNet.Mvc
[Fact]
public void Setup_SetsUpViewEngines()
{
// Arrange
var mvcOptions = new MvcViewOptions();
var setup = new MvcViewOptionsSetup();
// Act
setup.Configure(mvcOptions);
// Arrange & Act
var options = GetOptions<MvcViewOptions>();
// Assert
Assert.Equal(1, mvcOptions.ViewEngines.Count);
Assert.Equal(typeof(RazorViewEngine), mvcOptions.ViewEngines[0].ViewEngineType);
Assert.Equal(1, options.ViewEngines.Count);
Assert.Equal(typeof(RazorViewEngine), options.ViewEngines[0].ViewEngineType);
}
[Fact]
public void Setup_SetsUpModelBinders()
{
// Arrange
var mvcOptions = new MvcOptions();
var setup1 = new CoreMvcOptionsSetup();
var setup2 = new MvcOptionsSetup();
// Act
setup1.Configure(mvcOptions);
setup2.Configure(mvcOptions);
// Arrange & Act
var options = GetOptions<MvcOptions>();
// Assert
var i = 0;
Assert.Equal(13, mvcOptions.ModelBinders.Count);
Assert.IsType(typeof(BinderTypeBasedModelBinder), mvcOptions.ModelBinders[i++]);
Assert.IsType(typeof(ServicesModelBinder), mvcOptions.ModelBinders[i++]);
Assert.IsType(typeof(BodyModelBinder), mvcOptions.ModelBinders[i++]);
Assert.IsType(typeof(HeaderModelBinder), mvcOptions.ModelBinders[i++]);
Assert.IsType(typeof(TypeConverterModelBinder), mvcOptions.ModelBinders[i++]);
Assert.IsType(typeof(TypeMatchModelBinder), mvcOptions.ModelBinders[i++]);
Assert.IsType(typeof(CancellationTokenModelBinder), mvcOptions.ModelBinders[i++]);
Assert.IsType(typeof(ByteArrayModelBinder), mvcOptions.ModelBinders[i++]);
Assert.IsType(typeof(FormFileModelBinder), mvcOptions.ModelBinders[i++]);
Assert.IsType(typeof(FormCollectionModelBinder), mvcOptions.ModelBinders[i++]);
Assert.IsType(typeof(GenericModelBinder), mvcOptions.ModelBinders[i++]);
Assert.IsType(typeof(MutableObjectModelBinder), mvcOptions.ModelBinders[i++]);
Assert.IsType(typeof(ComplexModelDtoModelBinder), mvcOptions.ModelBinders[i++]);
Assert.Equal(13, options.ModelBinders.Count);
Assert.IsType(typeof(BinderTypeBasedModelBinder), options.ModelBinders[i++]);
Assert.IsType(typeof(ServicesModelBinder), options.ModelBinders[i++]);
Assert.IsType(typeof(BodyModelBinder), options.ModelBinders[i++]);
Assert.IsType(typeof(HeaderModelBinder), options.ModelBinders[i++]);
Assert.IsType(typeof(TypeConverterModelBinder), options.ModelBinders[i++]);
Assert.IsType(typeof(TypeMatchModelBinder), options.ModelBinders[i++]);
Assert.IsType(typeof(CancellationTokenModelBinder), options.ModelBinders[i++]);
Assert.IsType(typeof(ByteArrayModelBinder), options.ModelBinders[i++]);
Assert.IsType(typeof(FormFileModelBinder), options.ModelBinders[i++]);
Assert.IsType(typeof(FormCollectionModelBinder), options.ModelBinders[i++]);
Assert.IsType(typeof(GenericModelBinder), options.ModelBinders[i++]);
Assert.IsType(typeof(MutableObjectModelBinder), options.ModelBinders[i++]);
Assert.IsType(typeof(ComplexModelDtoModelBinder), options.ModelBinders[i++]);
}
[Fact]
public void Setup_SetsUpValueProviders()
{
// Arrange
var mvcOptions = new MvcOptions();
var setup1 = new CoreMvcOptionsSetup();
var setup2 = new MvcOptionsSetup();
// Act
setup1.Configure(mvcOptions);
setup2.Configure(mvcOptions);
// Arrange & Act
var options = GetOptions<MvcOptions>();
// Assert
var valueProviders = mvcOptions.ValueProviderFactories;
var valueProviders = options.ValueProviderFactories;
Assert.Equal(3, valueProviders.Count);
Assert.IsType<RouteValueValueProviderFactory>(valueProviders[0]);
Assert.IsType<QueryStringValueProviderFactory>(valueProviders[1]);
@ -83,150 +68,111 @@ namespace Microsoft.AspNet.Mvc
[Fact]
public void Setup_SetsUpOutputFormatters()
{
// Arrange
var mvcOptions = new MvcOptions();
var setup1 = new CoreMvcOptionsSetup();
var setup2 = new MvcOptionsSetup();
var setup3 = new JsonMvcOptionsSetup(new OptionsManager<MvcJsonOptions>(
Enumerable.Empty<IConfigureOptions<MvcJsonOptions>>()));
// Act
setup1.Configure(mvcOptions);
setup2.Configure(mvcOptions);
setup3.Configure(mvcOptions);
// Arrange & Act
var options = GetOptions<MvcOptions>();
// Assert
Assert.Equal(4, mvcOptions.OutputFormatters.Count);
Assert.IsType<HttpNoContentOutputFormatter>(mvcOptions.OutputFormatters[0]);
Assert.IsType<StringOutputFormatter>(mvcOptions.OutputFormatters[1]);
Assert.IsType<StreamOutputFormatter>(mvcOptions.OutputFormatters[2]);
Assert.IsType<JsonOutputFormatter>(mvcOptions.OutputFormatters[3]);
Assert.Equal(4, options.OutputFormatters.Count);
Assert.IsType<HttpNoContentOutputFormatter>(options.OutputFormatters[0]);
Assert.IsType<StringOutputFormatter>(options.OutputFormatters[1]);
Assert.IsType<StreamOutputFormatter>(options.OutputFormatters[2]);
Assert.IsType<JsonOutputFormatter>(options.OutputFormatters[3]);
}
[Fact]
public void Setup_SetsUpInputFormatters()
{
// Arrange
var mvcOptions = new MvcOptions();
var setup1 = new CoreMvcOptionsSetup();
var setup2 = new MvcOptionsSetup();
var setup3 = new JsonMvcOptionsSetup(new OptionsManager<MvcJsonOptions>(
Enumerable.Empty<IConfigureOptions<MvcJsonOptions>>()));
// Act
setup1.Configure(mvcOptions);
setup2.Configure(mvcOptions);
setup3.Configure(mvcOptions);
// Arrange & Act
var options = GetOptions<MvcOptions>();
// Assert
Assert.Equal(2, mvcOptions.InputFormatters.Count);
Assert.IsType<JsonInputFormatter>(mvcOptions.InputFormatters[0]);
Assert.IsType<JsonPatchInputFormatter>(mvcOptions.InputFormatters[1]);
Assert.Equal(2, options.InputFormatters.Count);
Assert.IsType<JsonInputFormatter>(options.InputFormatters[0]);
Assert.IsType<JsonPatchInputFormatter>(options.InputFormatters[1]);
}
[Fact]
public void Setup_SetsUpModelValidatorProviders()
{
// Arrange
var mvcOptions = new MvcOptions();
var setup1 = new CoreMvcOptionsSetup();
var setup2 = new MvcOptionsSetup();
// Act
setup1.Configure(mvcOptions);
setup2.Configure(mvcOptions);
// Arrange & Act
var options = GetOptions<MvcOptions>();
// Assert
Assert.Equal(2, mvcOptions.ModelValidatorProviders.Count);
Assert.IsType<DefaultModelValidatorProvider>(mvcOptions.ModelValidatorProviders[0]);
Assert.IsType<DataAnnotationsModelValidatorProvider>(mvcOptions.ModelValidatorProviders[1]);
Assert.Equal(2, options.ModelValidatorProviders.Count);
Assert.IsType<DefaultModelValidatorProvider>(options.ModelValidatorProviders[0]);
Assert.IsType<DataAnnotationsModelValidatorProvider>(options.ModelValidatorProviders[1]);
}
[Fact]
public void Setup_SetsUpClientModelValidatorProviders()
{
// Arrange
var mvcOptions = new MvcViewOptions();
var setup = new MvcViewOptionsSetup();
// Act
setup.Configure(mvcOptions);
// Arrange & Act
var options = GetOptions<MvcViewOptions>();
// Assert
Assert.Equal(2, mvcOptions.ClientModelValidatorProviders.Count);
Assert.IsType<DefaultClientModelValidatorProvider>(mvcOptions.ClientModelValidatorProviders[0]);
Assert.IsType<DataAnnotationsClientModelValidatorProvider>(mvcOptions.ClientModelValidatorProviders[1]);
Assert.Equal(2, options.ClientModelValidatorProviders.Count);
Assert.IsType<DefaultClientModelValidatorProvider>(options.ClientModelValidatorProviders[0]);
Assert.IsType<DataAnnotationsClientModelValidatorProvider>(options.ClientModelValidatorProviders[1]);
}
[Fact]
public void Setup_IgnoresAcceptHeaderHavingWildCardMediaAndSubMediaTypes()
{
// Arrange
var mvcOptions = new MvcOptions();
var setup = new CoreMvcOptionsSetup();
// Act
setup.Configure(mvcOptions);
// Arrange & Act
var options = GetOptions<MvcOptions>();
// Assert
Assert.False(mvcOptions.RespectBrowserAcceptHeader);
Assert.False(options.RespectBrowserAcceptHeader);
}
[Fact]
public void Setup_SetsUpExcludeFromValidationDelegates()
{
// Arrange
var mvcOptions = new MvcOptions();
var setup1 = new CoreMvcOptionsSetup();
var setup2 = new MvcOptionsSetup();
// Act
setup1.Configure(mvcOptions);
setup2.Configure(mvcOptions);
mvcOptions.AddXmlDataContractSerializerFormatter();
// Arrange & Act
var options = GetOptions<MvcOptions>(_ => _.ConfigureMvc(o => o.AddXmlDataContractSerializerFormatter()));
// Assert
Assert.Equal(8, mvcOptions.ValidationExcludeFilters.Count);
Assert.Equal(8, options.ValidationExcludeFilters.Count);
var i = 0;
// Verify if the delegates registered by default exclude the given types.
Assert.IsType(typeof(SimpleTypesExcludeFilter), mvcOptions.ValidationExcludeFilters[i++]);
Assert.IsType(typeof(SimpleTypesExcludeFilter), options.ValidationExcludeFilters[i++]);
Assert.IsType(typeof(DefaultTypeBasedExcludeFilter), mvcOptions.ValidationExcludeFilters[i]);
Assert.IsType(typeof(DefaultTypeBasedExcludeFilter), options.ValidationExcludeFilters[i]);
var typeFilter
= Assert.IsType<DefaultTypeBasedExcludeFilter>(mvcOptions.ValidationExcludeFilters[i++]);
= Assert.IsType<DefaultTypeBasedExcludeFilter>(options.ValidationExcludeFilters[i++]);
Assert.Equal(typeFilter.ExcludedType, typeof(Type));
Assert.IsType(typeof(DefaultTypeBasedExcludeFilter), mvcOptions.ValidationExcludeFilters[i]);
Assert.IsType(typeof(DefaultTypeBasedExcludeFilter), options.ValidationExcludeFilters[i]);
var cancellationTokenFilter
= Assert.IsType<DefaultTypeBasedExcludeFilter>(mvcOptions.ValidationExcludeFilters[i++]);
= Assert.IsType<DefaultTypeBasedExcludeFilter>(options.ValidationExcludeFilters[i++]);
Assert.Equal(cancellationTokenFilter.ExcludedType, typeof(System.Threading.CancellationToken));
Assert.IsType(typeof(DefaultTypeBasedExcludeFilter), mvcOptions.ValidationExcludeFilters[i]);
Assert.IsType(typeof(DefaultTypeBasedExcludeFilter), options.ValidationExcludeFilters[i]);
var formFileFilter
= Assert.IsType<DefaultTypeBasedExcludeFilter>(mvcOptions.ValidationExcludeFilters[i++]);
= Assert.IsType<DefaultTypeBasedExcludeFilter>(options.ValidationExcludeFilters[i++]);
Assert.Equal(formFileFilter.ExcludedType, typeof(Http.IFormFile));
Assert.IsType(
typeof(DefaultTypeBasedExcludeFilter),
mvcOptions.ValidationExcludeFilters[i]);
options.ValidationExcludeFilters[i]);
var formCollectionFilter
= Assert.IsType<DefaultTypeBasedExcludeFilter>(mvcOptions.ValidationExcludeFilters[i++]);
= Assert.IsType<DefaultTypeBasedExcludeFilter>(options.ValidationExcludeFilters[i++]);
Assert.Equal(formCollectionFilter.ExcludedType, typeof(Http.IFormCollection));
Assert.IsType(typeof(DefaultTypeBasedExcludeFilter), mvcOptions.ValidationExcludeFilters[i]);
Assert.IsType(typeof(DefaultTypeBasedExcludeFilter), options.ValidationExcludeFilters[i]);
var jTokenFilter
= Assert.IsType<DefaultTypeBasedExcludeFilter>(mvcOptions.ValidationExcludeFilters[i++]);
= Assert.IsType<DefaultTypeBasedExcludeFilter>(options.ValidationExcludeFilters[i++]);
Assert.Equal(jTokenFilter.ExcludedType, typeof(JToken));
Assert.IsType(typeof(DefaultTypeNameBasedExcludeFilter), mvcOptions.ValidationExcludeFilters[i]);
Assert.IsType(typeof(DefaultTypeNameBasedExcludeFilter), options.ValidationExcludeFilters[i]);
var xObjectFilter
= Assert.IsType<DefaultTypeNameBasedExcludeFilter>(mvcOptions.ValidationExcludeFilters[i++]);
= Assert.IsType<DefaultTypeNameBasedExcludeFilter>(options.ValidationExcludeFilters[i++]);
Assert.Equal(xObjectFilter.ExcludedTypeName, typeof(XObject).FullName);
Assert.IsType(typeof(DefaultTypeNameBasedExcludeFilter), mvcOptions.ValidationExcludeFilters[i]);
Assert.IsType(typeof(DefaultTypeNameBasedExcludeFilter), options.ValidationExcludeFilters[i]);
var xmlNodeFilter =
Assert.IsType<DefaultTypeNameBasedExcludeFilter>(mvcOptions.ValidationExcludeFilters[i++]);
Assert.IsType<DefaultTypeNameBasedExcludeFilter>(options.ValidationExcludeFilters[i++]);
Assert.Equal(xmlNodeFilter.ExcludedTypeName, "System.Xml.XmlNode");
}
@ -234,27 +180,45 @@ namespace Microsoft.AspNet.Mvc
public void Setup_JsonFormattersUseSerializerSettings()
{
// Arrange
var jsonOptionsAccessor = new OptionsManager<MvcJsonOptions>(
Enumerable.Empty<IConfigureOptions<MvcJsonOptions>>());
var mvcOptions = new MvcOptions();
var setup = new JsonMvcOptionsSetup(jsonOptionsAccessor);
var services = GetServiceProvider();
// Act
setup.Configure(mvcOptions);
var options = services.GetRequiredService<IOptions<MvcOptions>>().Options;
var jsonOptions = services.GetRequiredService<IOptions<MvcJsonOptions>>().Options;
// Assert
var jsonInputFormatters = mvcOptions.InputFormatters.OfType<JsonInputFormatter>();
var jsonInputFormatters = options.InputFormatters.OfType<JsonInputFormatter>();
foreach (var jsonInputFormatter in jsonInputFormatters)
{
Assert.Same(jsonOptionsAccessor.Options.SerializerSettings, jsonInputFormatter.SerializerSettings);
Assert.Same(jsonOptions.SerializerSettings, jsonInputFormatter.SerializerSettings);
}
var jsonOuputFormatters = mvcOptions.OutputFormatters.OfType<JsonOutputFormatter>();
var jsonOuputFormatters = options.OutputFormatters.OfType<JsonOutputFormatter>();
foreach (var jsonOuputFormatter in jsonOuputFormatters)
{
Assert.Same(jsonOptionsAccessor.Options.SerializerSettings, jsonOuputFormatter.SerializerSettings);
Assert.Same(jsonOptions.SerializerSettings, jsonOuputFormatter.SerializerSettings);
}
}
private static T GetOptions<T>(Action<IServiceCollection> action = null)
where T : class, new()
{
var serviceProvider = GetServiceProvider(action);
return serviceProvider.GetRequiredService<IOptions<T>>().Options;
}
private static IServiceProvider GetServiceProvider(Action<IServiceCollection> action = null)
{
var serviceCollection = new ServiceCollection();
serviceCollection.AddMvc();
if (action != null)
{
action(serviceCollection);
}
var serviceProvider = serviceCollection.BuildServiceProvider();
return serviceProvider;
}
}
}
}

View File

@ -5,6 +5,8 @@ using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using Microsoft.AspNet.Antiforgery;
using Microsoft.AspNet.Authorization;
using Microsoft.AspNet.Mvc.ActionConstraints;
using Microsoft.AspNet.Mvc.ApiExplorer;
using Microsoft.AspNet.Mvc.ApplicationModels;
@ -12,6 +14,7 @@ using Microsoft.AspNet.Mvc.Core;
using Microsoft.AspNet.Mvc.Filters;
using Microsoft.AspNet.Mvc.MvcServiceCollectionExtensionsTestControllers;
using Microsoft.AspNet.Mvc.Razor;
using Microsoft.AspNet.Routing;
using Microsoft.Framework.DependencyInjection;
using Microsoft.Framework.OptionsModel;
using Moq;
@ -106,7 +109,7 @@ namespace Microsoft.AspNet.Mvc
}
// Act
MvcServiceCollectionExtensions.AddMvcServices(services);
services.AddMvc();
// Assert
foreach (var serviceType in MutliRegistrationServiceTypes)
@ -134,7 +137,7 @@ namespace Microsoft.AspNet.Mvc
}
// Act
MvcServiceCollectionExtensions.AddMvcServices(services);
services.AddMvc();
// Assert
foreach (var singleRegistrationType in SingleRegistrationServiceTypes)
@ -150,8 +153,8 @@ namespace Microsoft.AspNet.Mvc
var services = new ServiceCollection();
// Act
MvcServiceCollectionExtensions.AddMvcServices(services);
MvcServiceCollectionExtensions.AddMvcServices(services);
services.AddMvc();
services.AddMvc();
// Assert
var singleRegistrationServiceTypes = SingleRegistrationServiceTypes;
@ -162,6 +165,10 @@ namespace Microsoft.AspNet.Mvc
// 'single-registration' services should only have one implementation registered.
AssertServiceCountEquals(services, service.ServiceType, 1);
}
else if (service.ImplementationType != null && !service.ImplementationType.Assembly.FullName.Contains("Mvc"))
{
// Ignore types that don't come from MVC
}
else
{
// 'multi-registration' services should only have one *instance* of each implementation registered.
@ -175,11 +182,12 @@ namespace Microsoft.AspNet.Mvc
get
{
var services = new ServiceCollection();
MvcServiceCollectionExtensions.AddMvcServices(services);
services.AddMvc();
var multiRegistrationServiceTypes = MutliRegistrationServiceTypes;
return services
.Where(sd => !multiRegistrationServiceTypes.Keys.Contains(sd.ServiceType))
.Where(sd => sd.ServiceType.Assembly.FullName.Contains("Mvc"))
.Select(sd => sd.ServiceType);
}
}
@ -194,15 +202,16 @@ namespace Microsoft.AspNet.Mvc
typeof(IConfigureOptions<MvcOptions>),
new Type[]
{
typeof(MvcOptionsSetup),
typeof(JsonMvcOptionsSetup),
typeof(MvcCoreMvcOptionsSetup),
typeof(MvcDataAnnotationsMvcOptionsSetup),
typeof(MvcJsonMvcOptionsSetup),
}
},
{
typeof(IConfigureOptions<MvcFormatterMappingOptions>),
typeof(IConfigureOptions<RouteOptions>),
new Type[]
{
typeof(JsonMvcFormatterMappingOptionsSetup),
typeof(MvcCoreRouteOptionsSetup),
}
},
{
@ -210,6 +219,7 @@ namespace Microsoft.AspNet.Mvc
new Type[]
{
typeof(MvcViewOptionsSetup),
typeof(MvcRazorMvcViewOptionsSetup),
}
},
{
@ -219,17 +229,39 @@ namespace Microsoft.AspNet.Mvc
typeof(RazorViewEngineOptionsSetup),
}
},
{
typeof(IApiDescriptionProvider),
{
typeof(IActionConstraintProvider),
new Type[]
{
typeof(DefaultApiDescriptionProvider),
typeof(DefaultActionConstraintProvider),
}
},
{
typeof(IActionDescriptorProvider),
new Type[]
{
typeof(ControllerActionDescriptorProvider),
}
},
{
typeof(IActionInvokerProvider),
new Type[]
{
typeof(ControllerActionInvokerProvider),
}
},
{
typeof(IFilterProvider),
new Type[]
{
typeof(DefaultFilterProvider),
}
},
{
typeof(IControllerPropertyActivator),
new Type[]
{
typeof(DefaultControllerPropertyActivator),
typeof(ViewDataDictionaryControllerPropertyActivator),
}
},
@ -237,10 +269,18 @@ namespace Microsoft.AspNet.Mvc
typeof(IApplicationModelProvider),
new Type[]
{
typeof(DefaultApplicationModelProvider),
typeof(CorsApplicationModelProvider),
typeof(AuthorizationApplicationModelProvider),
}
},
{
typeof(IApiDescriptionProvider),
new Type[]
{
typeof(DefaultApiDescriptionProvider),
}
},
};
}
}

View File

@ -5,6 +5,7 @@
"dependencies": {
"Microsoft.AspNet.Mvc": "6.0.0-*",
"Microsoft.AspNet.Mvc.Formatters.Xml": "6.0.0-*",
"Microsoft.Framework.DependencyInjection": "1.0.0-*",
"xunit.runner.aspnet": "2.0.0-aspnet-*"
},
"commands": {

View File

@ -24,7 +24,7 @@ namespace FormatFilterWebSite
var customFormatter = new CustomFormatter("application/custom");
options.OutputFormatters.Add(customFormatter);
});
services.ConfigureMvcFormatterMappings(options =>
services.ConfigureMvc(options =>
{
options.FormatterMappings.SetMediaTypeMappingForFormat(
"custom",

View File

@ -13,7 +13,7 @@ namespace ResponseCacheWebSite
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc();
services.ConfigureMvcCaching(options =>
services.ConfigureMvc(options =>
{
options.CacheProfiles.Add(
"PublicCache30Sec", new CacheProfile