Add Service monitoring as middleware to make sure the monitoring doesn't affect autofac services counts
Scoping of three services Caching of action binding context. Make input formatters lazy
This commit is contained in:
parent
e27742fd0b
commit
6aa1f84420
|
|
@ -0,0 +1,108 @@
|
||||||
|
#if NET45
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Autofac.Core;
|
||||||
|
using Microsoft.AspNet.Builder;
|
||||||
|
using Microsoft.AspNet.Http;
|
||||||
|
|
||||||
|
namespace MvcSample.Web
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Summary description for MonitoringMiddlware
|
||||||
|
/// </summary>
|
||||||
|
public class MonitoringMiddlware
|
||||||
|
{
|
||||||
|
private RequestDelegate _next;
|
||||||
|
private IServiceProvider _services;
|
||||||
|
|
||||||
|
public MonitoringMiddlware(RequestDelegate next, IServiceProvider services)
|
||||||
|
{
|
||||||
|
_next = next;
|
||||||
|
_services = services;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task Invoke(HttpContext httpContext)
|
||||||
|
{
|
||||||
|
var url = httpContext.Request.Path.Value;
|
||||||
|
|
||||||
|
if (url.Equals("/Monitoring/Clear", StringComparison.OrdinalIgnoreCase))
|
||||||
|
{
|
||||||
|
MonitoringModule.Clear();
|
||||||
|
httpContext.Response.ContentType = "text/plain";
|
||||||
|
var buffer = Encoding.ASCII.GetBytes("Cleared");
|
||||||
|
httpContext.Response.Body.Write(buffer, 0, buffer.Length);
|
||||||
|
}
|
||||||
|
else if (url.Equals("/Monitoring/ActivatedTypes", StringComparison.OrdinalIgnoreCase))
|
||||||
|
{
|
||||||
|
var data = ActivatedTypes();
|
||||||
|
httpContext.Response.ContentType = "text/plain charset=utf-8";
|
||||||
|
var buffer = Encoding.UTF8.GetBytes(data);
|
||||||
|
|
||||||
|
httpContext.Response.Body.Write(buffer, 0, buffer.Length);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
await _next(httpContext);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public string ActivatedTypes()
|
||||||
|
{
|
||||||
|
var values = MonitoringModule.InstanceCount.ToArray();
|
||||||
|
|
||||||
|
var builder = new StringBuilder();
|
||||||
|
|
||||||
|
Array.Sort(values, new InstancesComparer());
|
||||||
|
|
||||||
|
foreach (var item in values)
|
||||||
|
{
|
||||||
|
builder.AppendLine(GetTypeName(item.Key.Item1) + " " + item.Value);
|
||||||
|
}
|
||||||
|
|
||||||
|
return builder.ToString();
|
||||||
|
}
|
||||||
|
|
||||||
|
private string GetTypeName(Type type)
|
||||||
|
{
|
||||||
|
var name = type.Name;
|
||||||
|
var isArray = false;
|
||||||
|
|
||||||
|
if (typeof(Array).IsAssignableFrom(type))
|
||||||
|
{
|
||||||
|
isArray = true;
|
||||||
|
name = ChopLast2(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
var genericArgs = type.GetGenericArguments().Select(t => t.Name).ToArray();
|
||||||
|
|
||||||
|
if (genericArgs.Length > 0)
|
||||||
|
{
|
||||||
|
name = ChopLast2(name) + "<" + string.Join(",", genericArgs) + ">";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isArray)
|
||||||
|
{
|
||||||
|
name += "[]";
|
||||||
|
}
|
||||||
|
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string ChopLast2(string name)
|
||||||
|
{
|
||||||
|
return name.Remove(name.Length - 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
private class InstancesComparer : IComparer<KeyValuePair<Tuple<Type, IComponentLifetime>, int>>
|
||||||
|
{
|
||||||
|
public int Compare(KeyValuePair<Tuple<Type, IComponentLifetime>, int> x, KeyValuePair<Tuple<Type, IComponentLifetime>, int> y)
|
||||||
|
{
|
||||||
|
return y.Value.CompareTo(x.Value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
@ -0,0 +1,77 @@
|
||||||
|
#if NET45
|
||||||
|
using System;
|
||||||
|
using System.Collections.Concurrent;
|
||||||
|
using Autofac;
|
||||||
|
using Autofac.Core;
|
||||||
|
|
||||||
|
namespace MvcSample.Web
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Summary description for MonitoringModule
|
||||||
|
/// </summary>
|
||||||
|
public class MonitoringModule : Module
|
||||||
|
{
|
||||||
|
private static ConcurrentDictionary<Tuple<Type, IComponentLifetime>, int> _registrations
|
||||||
|
= new ConcurrentDictionary<Tuple<Type, IComponentLifetime>, int>();
|
||||||
|
|
||||||
|
private static ConcurrentDictionary<Tuple<Type, IComponentLifetime>, object> _instances
|
||||||
|
= new ConcurrentDictionary<Tuple<Type, IComponentLifetime>, object>();
|
||||||
|
|
||||||
|
public static readonly ConcurrentDictionary<Tuple<Type, IComponentLifetime>, int> InstanceCount
|
||||||
|
= new ConcurrentDictionary<Tuple<Type, IComponentLifetime>, int>();
|
||||||
|
|
||||||
|
protected override void AttachToComponentRegistration(IComponentRegistry componentRegistry,
|
||||||
|
IComponentRegistration registration)
|
||||||
|
{
|
||||||
|
registration.Activating += Registration_Activating;
|
||||||
|
registration.Activated += Registration_Activated;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Tuple<Type, IComponentLifetime> GetKey(IComponentRegistration context)
|
||||||
|
{
|
||||||
|
var activator = context.Activator;
|
||||||
|
var lifeTime = context.Lifetime;
|
||||||
|
var limitType = context.Activator.LimitType;
|
||||||
|
|
||||||
|
var key = new Tuple<Type, IComponentLifetime>(limitType, lifeTime);
|
||||||
|
|
||||||
|
return key;
|
||||||
|
}
|
||||||
|
private void Registration_Activated(object sender, ActivatedEventArgs<object> e)
|
||||||
|
{
|
||||||
|
object instance;
|
||||||
|
var key = GetKey(e.Component);
|
||||||
|
if (_instances.TryGetValue(key, out instance))
|
||||||
|
{
|
||||||
|
bool same = (e.Instance == instance);
|
||||||
|
InstanceCount.AddOrUpdate(key, 1, (_, count) => same ? 1 : count + 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Registration_Activating(object sender, ActivatingEventArgs<object> e)
|
||||||
|
{
|
||||||
|
var key = GetKey(e.Component);
|
||||||
|
_registrations.AddOrUpdate(key, 1, (k, value) => value + 1);
|
||||||
|
_instances.GetOrAdd(key, e.Instance);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Registration_Preparing(object sender, PreparingEventArgs e)
|
||||||
|
{
|
||||||
|
foreach (var param in e.Parameters)
|
||||||
|
{
|
||||||
|
Console.WriteLine(param.ToString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void Clear()
|
||||||
|
{
|
||||||
|
//string count = InstanceCount.Select(kvp => kvp.Value).Aggregate((c, n) => c + n).ToString() + " instances from " + InstanceCount.Count + " types";
|
||||||
|
InstanceCount.Clear();
|
||||||
|
_instances.Clear();
|
||||||
|
_registrations.Clear();
|
||||||
|
|
||||||
|
// return count;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
@ -61,6 +61,8 @@
|
||||||
<Compile Include="HomeController.cs" />
|
<Compile Include="HomeController.cs" />
|
||||||
<Compile Include="LinkController.cs" />
|
<Compile Include="LinkController.cs" />
|
||||||
<Compile Include="Models\User.cs" />
|
<Compile Include="Models\User.cs" />
|
||||||
|
<Compile Include="Monitoring\MonitoringMiddlware.cs" />
|
||||||
|
<Compile Include="Monitoring\MonitoringModule.cs" />
|
||||||
<Compile Include="OverloadController.cs" />
|
<Compile Include="OverloadController.cs" />
|
||||||
<Compile Include="Services\TestService.cs" />
|
<Compile Include="Services\TestService.cs" />
|
||||||
<Compile Include="SimplePocoController.cs" />
|
<Compile Include="SimplePocoController.cs" />
|
||||||
|
|
@ -69,4 +71,4 @@
|
||||||
<Compile Include="ViewMetadata.cs" />
|
<Compile Include="ViewMetadata.cs" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<Import Project="$(VSToolsPath)\AspNet\Microsoft.Web.AspNet.targets" Condition="'$(VSToolsPath)' != ''" />
|
<Import Project="$(VSToolsPath)\AspNet\Microsoft.Web.AspNet.targets" Condition="'$(VSToolsPath)' != ''" />
|
||||||
</Project>
|
</Project>
|
||||||
|
|
@ -28,6 +28,8 @@ namespace MvcSample.Web
|
||||||
if (configuration.TryGet("DependencyInjection", out diSystem) &&
|
if (configuration.TryGet("DependencyInjection", out diSystem) &&
|
||||||
diSystem.Equals("AutoFac", StringComparison.OrdinalIgnoreCase))
|
diSystem.Equals("AutoFac", StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
|
app.UseMiddleware<MonitoringMiddlware>();
|
||||||
|
|
||||||
var services = new ServiceCollection();
|
var services = new ServiceCollection();
|
||||||
|
|
||||||
services.AddMvc();
|
services.AddMvc();
|
||||||
|
|
@ -45,6 +47,8 @@ namespace MvcSample.Web
|
||||||
services,
|
services,
|
||||||
fallbackServiceProvider: app.ApplicationServices);
|
fallbackServiceProvider: app.ApplicationServices);
|
||||||
|
|
||||||
|
builder.RegisterModule<MonitoringModule>();
|
||||||
|
|
||||||
IContainer container = builder.Build();
|
IContainer container = builder.Build();
|
||||||
|
|
||||||
app.UseServices(container.Resolve<IServiceProvider>());
|
app.UseServices(container.Resolve<IServiceProvider>());
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,7 @@ namespace Microsoft.AspNet.Mvc
|
||||||
"Microsoft.AspNet.Mvc.Razor.Host",
|
"Microsoft.AspNet.Mvc.Razor.Host",
|
||||||
"Microsoft.AspNet.Mvc.Rendering",
|
"Microsoft.AspNet.Mvc.Rendering",
|
||||||
};
|
};
|
||||||
|
|
||||||
private readonly ILibraryManager _libraryManager;
|
private readonly ILibraryManager _libraryManager;
|
||||||
|
|
||||||
public DefaultControllerAssemblyProvider(ILibraryManager libraryManager)
|
public DefaultControllerAssemblyProvider(ILibraryManager libraryManager)
|
||||||
|
|
@ -42,8 +43,8 @@ namespace Microsoft.AspNet.Mvc
|
||||||
// for a given assembly. In our case, we'll gather all assemblies that reference
|
// for a given assembly. In our case, we'll gather all assemblies that reference
|
||||||
// any of the primary Mvc assemblies while ignoring Mvc assemblies.
|
// any of the primary Mvc assemblies while ignoring Mvc assemblies.
|
||||||
return _mvcAssemblyList.SelectMany(_libraryManager.GetReferencingLibraries)
|
return _mvcAssemblyList.SelectMany(_libraryManager.GetReferencingLibraries)
|
||||||
.Distinct()
|
.Distinct()
|
||||||
.Where(IsCandidateLibrary);
|
.Where(IsCandidateLibrary);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Assembly Load(ILibraryInformation library)
|
private static Assembly Load(ILibraryInformation library)
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
|
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
|
||||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
@ -17,6 +18,8 @@ namespace Microsoft.AspNet.Mvc
|
||||||
private readonly IInputFormatterProvider _inputFormatterProvider;
|
private readonly IInputFormatterProvider _inputFormatterProvider;
|
||||||
private readonly IEnumerable<IModelValidatorProvider> _validatorProviders;
|
private readonly IEnumerable<IModelValidatorProvider> _validatorProviders;
|
||||||
|
|
||||||
|
private Tuple<ActionContext, ActionBindingContext> _bindingContext;
|
||||||
|
|
||||||
public DefaultActionBindingContextProvider(IModelMetadataProvider modelMetadataProvider,
|
public DefaultActionBindingContextProvider(IModelMetadataProvider modelMetadataProvider,
|
||||||
IEnumerable<IModelBinder> modelBinders,
|
IEnumerable<IModelBinder> modelBinders,
|
||||||
IEnumerable<IValueProviderFactory> valueProviderFactories,
|
IEnumerable<IValueProviderFactory> valueProviderFactories,
|
||||||
|
|
@ -25,7 +28,7 @@ namespace Microsoft.AspNet.Mvc
|
||||||
{
|
{
|
||||||
_modelMetadataProvider = modelMetadataProvider;
|
_modelMetadataProvider = modelMetadataProvider;
|
||||||
_modelBinders = modelBinders.OrderBy(
|
_modelBinders = modelBinders.OrderBy(
|
||||||
binder => binder.GetType() == typeof(ComplexModelDtoModelBinder) ? 1 : 0);
|
binder => binder.GetType() == typeof(ComplexModelDtoModelBinder) ? 1 : 0).ToArray();
|
||||||
_valueProviderFactories = valueProviderFactories;
|
_valueProviderFactories = valueProviderFactories;
|
||||||
_inputFormatterProvider = inputFormatterProvider;
|
_inputFormatterProvider = inputFormatterProvider;
|
||||||
_validatorProviders = validatorProviders;
|
_validatorProviders = validatorProviders;
|
||||||
|
|
@ -33,12 +36,21 @@ namespace Microsoft.AspNet.Mvc
|
||||||
|
|
||||||
public Task<ActionBindingContext> GetActionBindingContextAsync(ActionContext actionContext)
|
public Task<ActionBindingContext> GetActionBindingContextAsync(ActionContext actionContext)
|
||||||
{
|
{
|
||||||
|
if (_bindingContext != null)
|
||||||
|
{
|
||||||
|
if (actionContext == _bindingContext.Item1)
|
||||||
|
{
|
||||||
|
return Task.FromResult(_bindingContext.Item2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
var factoryContext = new ValueProviderFactoryContext(
|
var factoryContext = new ValueProviderFactoryContext(
|
||||||
actionContext.HttpContext,
|
actionContext.HttpContext,
|
||||||
actionContext.RouteData.Values);
|
actionContext.RouteData.Values);
|
||||||
|
|
||||||
var valueProviders = _valueProviderFactories.Select(factory => factory.GetValueProvider(factoryContext))
|
var valueProviders = _valueProviderFactories.Select(factory => factory.GetValueProvider(factoryContext))
|
||||||
.Where(vp => vp != null);
|
.Where(vp => vp != null);
|
||||||
|
|
||||||
var context = new ActionBindingContext(
|
var context = new ActionBindingContext(
|
||||||
actionContext,
|
actionContext,
|
||||||
_modelMetadataProvider,
|
_modelMetadataProvider,
|
||||||
|
|
@ -47,6 +59,8 @@ namespace Microsoft.AspNet.Mvc
|
||||||
_inputFormatterProvider,
|
_inputFormatterProvider,
|
||||||
_validatorProviders);
|
_validatorProviders);
|
||||||
|
|
||||||
|
_bindingContext = new Tuple<ActionContext, ActionBindingContext>(actionContext, context);
|
||||||
|
|
||||||
return Task.FromResult(context);
|
return Task.FromResult(context);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -5,21 +5,28 @@ using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using Microsoft.Framework.DependencyInjection;
|
||||||
|
|
||||||
namespace Microsoft.AspNet.Mvc.ModelBinding
|
namespace Microsoft.AspNet.Mvc.ModelBinding
|
||||||
{
|
{
|
||||||
public class TempInputFormatterProvider : IInputFormatterProvider
|
public class TempInputFormatterProvider : IInputFormatterProvider
|
||||||
{
|
{
|
||||||
private readonly IInputFormatter[] _formatters;
|
private IInputFormatter[] _formatters;
|
||||||
|
|
||||||
public TempInputFormatterProvider(IEnumerable<IInputFormatter> formatters)
|
|
||||||
{
|
|
||||||
_formatters = formatters.ToArray();
|
|
||||||
}
|
|
||||||
|
|
||||||
public IInputFormatter GetInputFormatter(InputFormatterProviderContext context)
|
public IInputFormatter GetInputFormatter(InputFormatterProviderContext context)
|
||||||
{
|
{
|
||||||
var request = context.HttpContext.Request;
|
var request = context.HttpContext.Request;
|
||||||
|
|
||||||
|
var formatters = _formatters;
|
||||||
|
|
||||||
|
if (formatters == null)
|
||||||
|
{
|
||||||
|
formatters = context.HttpContext.ApplicationServices.GetService<IEnumerable<IInputFormatter>>()
|
||||||
|
.ToArray();
|
||||||
|
|
||||||
|
_formatters = formatters;
|
||||||
|
}
|
||||||
|
|
||||||
var contentType = request.GetContentType();
|
var contentType = request.GetContentType();
|
||||||
if (contentType == null)
|
if (contentType == null)
|
||||||
{
|
{
|
||||||
|
|
@ -27,9 +34,9 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
|
||||||
throw new InvalidOperationException("400: Bad Request");
|
throw new InvalidOperationException("400: Bad Request");
|
||||||
}
|
}
|
||||||
|
|
||||||
for (var i = 0; i < _formatters.Length; i++)
|
for (var i = 0; i < formatters.Length; i++)
|
||||||
{
|
{
|
||||||
var formatter = _formatters[i];
|
var formatter = formatters[i];
|
||||||
if (formatter.SupportedMediaTypes.Contains(contentType.ContentType, StringComparer.OrdinalIgnoreCase))
|
if (formatter.SupportedMediaTypes.Contains(contentType.ContentType, StringComparer.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
return formatter;
|
return formatter;
|
||||||
|
|
|
||||||
|
|
@ -24,12 +24,12 @@
|
||||||
<Compile Include="IMvcRazorHost.cs" />
|
<Compile Include="IMvcRazorHost.cs" />
|
||||||
<Compile Include="InjectChunk.cs" />
|
<Compile Include="InjectChunk.cs" />
|
||||||
<Compile Include="InjectChunkVisitor.cs" />
|
<Compile Include="InjectChunkVisitor.cs" />
|
||||||
|
<Compile Include="InjectParameterGenerator.cs" />
|
||||||
<Compile Include="MvcCSharpCodeBuilder.cs" />
|
<Compile Include="MvcCSharpCodeBuilder.cs" />
|
||||||
<Compile Include="MvcCSharpCodeVistor.cs" />
|
<Compile Include="MvcCSharpCodeVistor.cs" />
|
||||||
<Compile Include="InjectParameterGenerator.cs" />
|
|
||||||
<Compile Include="MvcRazorCodeParser.cs" />
|
<Compile Include="MvcRazorCodeParser.cs" />
|
||||||
<Compile Include="MvcRazorHost.cs" />
|
<Compile Include="MvcRazorHost.cs" />
|
||||||
<Compile Include="Properties\Resources.Designer.cs" />
|
<Compile Include="Properties\Resources.Designer.cs" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<Import Project="$(VSToolsPath)\AspNet\Microsoft.Web.AspNet.targets" Condition="'$(VSToolsPath)' != ''" />
|
<Import Project="$(VSToolsPath)\AspNet\Microsoft.Web.AspNet.targets" Condition="'$(VSToolsPath)' != ''" />
|
||||||
</Project>
|
</Project>
|
||||||
|
|
@ -27,7 +27,7 @@ namespace Microsoft.AspNet.Mvc
|
||||||
|
|
||||||
yield return describe.Transient<IControllerFactory, DefaultControllerFactory>();
|
yield return describe.Transient<IControllerFactory, DefaultControllerFactory>();
|
||||||
yield return describe.Transient<IControllerDescriptorFactory, DefaultControllerDescriptorFactory>();
|
yield return describe.Transient<IControllerDescriptorFactory, DefaultControllerDescriptorFactory>();
|
||||||
yield return describe.Transient<IActionSelector, DefaultActionSelector>();
|
yield return describe.Scoped<IActionSelector, DefaultActionSelector>();
|
||||||
yield return describe.Transient<IActionInvokerFactory, ActionInvokerFactory>();
|
yield return describe.Transient<IActionInvokerFactory, ActionInvokerFactory>();
|
||||||
yield return describe.Transient<IParameterDescriptorFactory, DefaultParameterDescriptorFactory>();
|
yield return describe.Transient<IParameterDescriptorFactory, DefaultParameterDescriptorFactory>();
|
||||||
yield return describe.Transient<IControllerAssemblyProvider, DefaultControllerAssemblyProvider>();
|
yield return describe.Transient<IControllerAssemblyProvider, DefaultControllerAssemblyProvider>();
|
||||||
|
|
@ -39,7 +39,7 @@ namespace Microsoft.AspNet.Mvc
|
||||||
|
|
||||||
yield return describe.Transient<IRazorCompilationService, RazorCompilationService>();
|
yield return describe.Transient<IRazorCompilationService, RazorCompilationService>();
|
||||||
yield return describe.Transient<IVirtualPathViewFactory, VirtualPathViewFactory>();
|
yield return describe.Transient<IVirtualPathViewFactory, VirtualPathViewFactory>();
|
||||||
yield return describe.Transient<IViewEngine, RazorViewEngine>();
|
yield return describe.Scoped<IViewEngine, RazorViewEngine>();
|
||||||
|
|
||||||
yield return describe.Transient<INestedProvider<ActionDescriptorProviderContext>,
|
yield return describe.Transient<INestedProvider<ActionDescriptorProviderContext>,
|
||||||
ReflectedActionDescriptorProvider>();
|
ReflectedActionDescriptorProvider>();
|
||||||
|
|
@ -51,7 +51,7 @@ namespace Microsoft.AspNet.Mvc
|
||||||
DefaultActionDescriptorsCollectionProvider>();
|
DefaultActionDescriptorsCollectionProvider>();
|
||||||
|
|
||||||
yield return describe.Transient<IModelMetadataProvider, DataAnnotationsModelMetadataProvider>();
|
yield return describe.Transient<IModelMetadataProvider, DataAnnotationsModelMetadataProvider>();
|
||||||
yield return describe.Transient<IActionBindingContextProvider, DefaultActionBindingContextProvider>();
|
yield return describe.Scoped<IActionBindingContextProvider, DefaultActionBindingContextProvider>();
|
||||||
|
|
||||||
yield return describe.Transient<IValueProviderFactory, RouteValueValueProviderFactory>();
|
yield return describe.Transient<IValueProviderFactory, RouteValueValueProviderFactory>();
|
||||||
yield return describe.Transient<IValueProviderFactory, QueryStringValueProviderFactory>();
|
yield return describe.Transient<IValueProviderFactory, QueryStringValueProviderFactory>();
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue