diff --git a/src/Microsoft.AspNet.Mvc.Core/ApplicationModels/DefaultControllerModelBuilder.cs b/src/Microsoft.AspNet.Mvc.Core/ApplicationModels/DefaultControllerModelBuilder.cs
index f58c3e1989..0e1dc06014 100644
--- a/src/Microsoft.AspNet.Mvc.Core/ApplicationModels/DefaultControllerModelBuilder.cs
+++ b/src/Microsoft.AspNet.Mvc.Core/ApplicationModels/DefaultControllerModelBuilder.cs
@@ -5,7 +5,9 @@ using System;
using System.Linq;
using System.Reflection;
using Microsoft.AspNet.Mvc.Description;
+using Microsoft.AspNet.Mvc.Logging;
using Microsoft.AspNet.Mvc.Routing;
+using Microsoft.Framework.Logging;
namespace Microsoft.AspNet.Mvc.ApplicationModels
{
@@ -15,14 +17,16 @@ namespace Microsoft.AspNet.Mvc.ApplicationModels
public class DefaultControllerModelBuilder : IControllerModelBuilder
{
private readonly IActionModelBuilder _actionModelBuilder;
+ private readonly ILogger _logger;
///
/// Creates a new .
///
/// The used to create actions.
- public DefaultControllerModelBuilder(IActionModelBuilder actionModelBuilder)
+ public DefaultControllerModelBuilder(IActionModelBuilder actionModelBuilder, ILoggerFactory loggerFactory)
{
_actionModelBuilder = actionModelBuilder;
+ _logger = loggerFactory.Create();
}
///
@@ -61,24 +65,42 @@ namespace Microsoft.AspNet.Mvc.ApplicationModels
///
protected virtual bool IsController([NotNull] TypeInfo typeInfo)
{
- if (!typeInfo.IsClass ||
- typeInfo.IsAbstract ||
+ var status = ControllerStatus.IsController;
- // We only consider public top-level classes as controllers. IsPublic returns false for nested
- // classes, regardless of visibility modifiers.
- !typeInfo.IsPublic ||
- typeInfo.ContainsGenericParameters)
+ if (!typeInfo.IsClass)
{
- return false;
+ status |= ControllerStatus.IsNotAClass;
+ }
+ if (typeInfo.IsAbstract)
+ {
+ status |= ControllerStatus.IsAbstract;
+ }
+ // We only consider public top-level classes as controllers. IsPublic returns false for nested
+ // classes, regardless of visibility modifiers
+ if (!typeInfo.IsPublic)
+ {
+ status |= ControllerStatus.IsNotPublicOrTopLevel;
+ }
+ if (typeInfo.ContainsGenericParameters)
+ {
+ status |= ControllerStatus.ContainsGenericParameters;
}
-
if (typeInfo.Name.Equals("Controller", StringComparison.OrdinalIgnoreCase))
{
- return false;
+ status |= ControllerStatus.NameIsController;
}
-
- return typeInfo.Name.EndsWith("Controller", StringComparison.OrdinalIgnoreCase) ||
- typeof(Controller).GetTypeInfo().IsAssignableFrom(typeInfo);
+ if (!typeInfo.Name.EndsWith("Controller", StringComparison.OrdinalIgnoreCase) &&
+ !typeof(Controller).GetTypeInfo().IsAssignableFrom(typeInfo))
+ {
+ status |= ControllerStatus.DoesNotEndWithControllerAndIsNotAssignable;
+ }
+ if (_logger.IsEnabled(LogLevel.Verbose))
+ {
+ _logger.WriteVerbose(new IsControllerValues(
+ typeInfo.AsType(),
+ status));
+ }
+ return status == ControllerStatus.IsController;
}
///
diff --git a/src/Microsoft.AspNet.Mvc.Core/ControllerActionDescriptorProvider.cs b/src/Microsoft.AspNet.Mvc.Core/ControllerActionDescriptorProvider.cs
index c5bffe2322..c727fea474 100644
--- a/src/Microsoft.AspNet.Mvc.Core/ControllerActionDescriptorProvider.cs
+++ b/src/Microsoft.AspNet.Mvc.Core/ControllerActionDescriptorProvider.cs
@@ -5,7 +5,9 @@ using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.AspNet.Mvc.ApplicationModels;
+using Microsoft.AspNet.Mvc.Logging;
using Microsoft.AspNet.Mvc.Filters;
+using Microsoft.Framework.Logging;
using Microsoft.Framework.OptionsModel;
namespace Microsoft.AspNet.Mvc
@@ -16,16 +18,19 @@ namespace Microsoft.AspNet.Mvc
private readonly IAssemblyProvider _assemblyProvider;
private readonly IReadOnlyList _globalFilters;
private readonly IEnumerable _modelConventions;
+ private readonly ILogger _logger;
- public ControllerActionDescriptorProvider(IAssemblyProvider assemblyProvider,
- IControllerModelBuilder applicationModelBuilder,
- IGlobalFilterProvider globalFilters,
- IOptions optionsAccessor)
+ public ControllerActionDescriptorProvider([NotNull] IAssemblyProvider assemblyProvider,
+ [NotNull] IControllerModelBuilder applicationModelBuilder,
+ [NotNull] IGlobalFilterProvider globalFilters,
+ [NotNull] IOptions optionsAccessor,
+ [NotNull] ILoggerFactory loggerFactory)
{
_assemblyProvider = assemblyProvider;
_applicationModelBuilder = applicationModelBuilder;
_globalFilters = globalFilters.Filters;
_modelConventions = optionsAccessor.Options.ApplicationModelConventions;
+ _logger = loggerFactory.Create();
}
public int Order
@@ -43,6 +48,13 @@ namespace Microsoft.AspNet.Mvc
{
var applicationModel = BuildModel();
ApplicationModelConventions.ApplyConventions(applicationModel, _modelConventions);
+ if (_logger.IsEnabled(LogLevel.Verbose))
+ {
+ foreach (var controller in applicationModel.Controllers)
+ {
+ _logger.WriteVerbose(new ControllerModelValues(controller));
+ }
+ }
return ControllerActionDescriptorBuilder.Build(applicationModel);
}
@@ -53,6 +65,13 @@ namespace Microsoft.AspNet.Mvc
var assemblies = _assemblyProvider.CandidateAssemblies;
var types = assemblies.SelectMany(a => a.DefinedTypes);
+ if (_logger.IsEnabled(LogLevel.Verbose))
+ {
+ foreach (var assembly in assemblies)
+ {
+ _logger.WriteVerbose(new AssemblyValues(assembly));
+ }
+ }
foreach (var type in types)
{
diff --git a/src/Microsoft.AspNet.Mvc.Core/DefaultActionDescriptorsCollectionProvider.cs b/src/Microsoft.AspNet.Mvc.Core/DefaultActionDescriptorsCollectionProvider.cs
index f48415b83c..0ab1a13760 100644
--- a/src/Microsoft.AspNet.Mvc.Core/DefaultActionDescriptorsCollectionProvider.cs
+++ b/src/Microsoft.AspNet.Mvc.Core/DefaultActionDescriptorsCollectionProvider.cs
@@ -2,7 +2,9 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
+using Microsoft.AspNet.Mvc.Logging;
using Microsoft.Framework.DependencyInjection;
+using Microsoft.Framework.Logging;
namespace Microsoft.AspNet.Mvc
{
@@ -13,15 +15,17 @@ namespace Microsoft.AspNet.Mvc
public class DefaultActionDescriptorsCollectionProvider : IActionDescriptorsCollectionProvider
{
private readonly IServiceProvider _serviceProvider;
+ private readonly ILogger _logger;
private ActionDescriptorsCollection _collection;
///
/// Initializes a new instance of the class.
///
/// The application IServiceProvider.
- public DefaultActionDescriptorsCollectionProvider(IServiceProvider serviceProvider)
+ public DefaultActionDescriptorsCollectionProvider(IServiceProvider serviceProvider, ILoggerFactory factory)
{
_serviceProvider = serviceProvider;
+ _logger = factory.Create();
}
///
@@ -48,6 +52,14 @@ namespace Microsoft.AspNet.Mvc
actionDescriptorProvider.Invoke(actionDescriptorProviderContext);
+ if (_logger.IsEnabled(LogLevel.Verbose))
+ {
+ foreach (var actionDescriptor in actionDescriptorProviderContext.Results)
+ {
+ _logger.WriteVerbose(new ActionDescriptorValues(actionDescriptor));
+ }
+ }
+
return new ActionDescriptorsCollection(actionDescriptorProviderContext.Results, 0);
}
}
diff --git a/src/Microsoft.AspNet.Mvc.Core/Logging/ActionConstraintValues.cs b/src/Microsoft.AspNet.Mvc.Core/Logging/ActionConstraintValues.cs
new file mode 100644
index 0000000000..9b68e6729b
--- /dev/null
+++ b/src/Microsoft.AspNet.Mvc.Core/Logging/ActionConstraintValues.cs
@@ -0,0 +1,54 @@
+// 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.
+
+using System;
+using Microsoft.Framework.Logging;
+
+namespace Microsoft.AspNet.Mvc.Logging
+{
+ ///
+ /// Logging representation of an .
+ ///
+ public class ActionConstraintValues : LoggerStructureBase
+ {
+ public ActionConstraintValues(IActionConstraintMetadata inner)
+ {
+ var constraint = inner as IActionConstraint;
+ if (constraint != null)
+ {
+ IsConstraint = true;
+ Order = constraint.Order;
+ }
+ if (inner is IActionConstraintFactory)
+ {
+ IsFactory = true;
+ }
+ ActionConstraintMetadataType = inner.GetType();
+ }
+
+ ///
+ /// The of this .
+ ///
+ public Type ActionConstraintMetadataType { get; }
+
+ ///
+ /// The constraint order if this is an . See .
+ ///
+ public int Order { get; }
+
+ ///
+ /// Whether the action constraint is an .
+ ///
+ public bool IsConstraint { get; }
+
+ ///
+ /// Whether the action constraint is an .
+ ///
+ public bool IsFactory { get; }
+
+ public override string Format()
+ {
+ return LogFormatter.FormatStructure(this);
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Microsoft.AspNet.Mvc.Core/Logging/ActionDescriptorValues.cs b/src/Microsoft.AspNet.Mvc.Core/Logging/ActionDescriptorValues.cs
new file mode 100644
index 0000000000..0e7c488ea2
--- /dev/null
+++ b/src/Microsoft.AspNet.Mvc.Core/Logging/ActionDescriptorValues.cs
@@ -0,0 +1,117 @@
+// 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.
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Reflection;
+using Microsoft.Framework.Logging;
+
+namespace Microsoft.AspNet.Mvc.Logging
+{
+ ///
+ /// Logging representation of the state of an or
+ /// . Logged during action discovery.
+ ///
+ public class ActionDescriptorValues : LoggerStructureBase
+ {
+ public ActionDescriptorValues([NotNull] ActionDescriptor inner)
+ {
+ Name = inner.Name;
+ DisplayName = inner.DisplayName;
+ Parameters = inner.Parameters.Select(p => new ParameterDescriptorValues(p)).ToList();
+ FilterDescriptors = inner.FilterDescriptors.Select(f => new FilterDescriptorValues(f)).ToList();
+ RouteConstraints = inner.RouteConstraints.Select(r => new RouteDataActionConstraintValues(r)).ToList();
+ AttributeRouteInfo = new AttributeRouteInfoValues(inner.AttributeRouteInfo);
+ RouteValueDefaults = inner.RouteValueDefaults.ToDictionary(i => i.Key, i => i.Value.ToString());
+ ActionConstraints = inner.ActionConstraints?.Select(a => new ActionConstraintValues(a))?.ToList();
+ HttpMethods = inner.ActionConstraints?.OfType().SelectMany(c => c.HttpMethods).ToList();
+ Properties = inner.Properties.ToDictionary(i => i.Key.ToString(), i => i.Value.GetType());
+ var controllerActionDescriptor = inner as ControllerActionDescriptor;
+ if (controllerActionDescriptor != null)
+ {
+ MethodInfo = controllerActionDescriptor.MethodInfo;
+ ControllerName = controllerActionDescriptor.ControllerName;
+ ControllerTypeInfo = controllerActionDescriptor.ControllerTypeInfo;
+ }
+ }
+
+ ///
+ /// The name of the action. See .
+ ///
+ public string Name { get; }
+
+ ///
+ /// A friendly name for the action. See .
+ ///
+ public string DisplayName { get; }
+
+ ///
+ /// The parameters of the action as .
+ /// See .
+ ///
+ public List Parameters { get; }
+
+ ///
+ /// The filters of the action as .
+ /// See .
+ ///
+ public List FilterDescriptors { get; }
+
+ ///
+ /// The route constraints of the action as .
+ /// See
+ ///
+ public List RouteConstraints { get; }
+
+ ///
+ /// The attribute route info of the action as .
+ /// See .
+ ///
+ public AttributeRouteInfoValues AttributeRouteInfo { get; }
+
+ ///
+ /// See .
+ ///
+ public Dictionary RouteValueDefaults { get; }
+
+ ///
+ /// The action constraints of the action as .
+ /// See .
+ ///
+ public List ActionConstraints { get; }
+
+ ///
+ /// The http methods this action supports.
+ ///
+ public List HttpMethods { get; }
+
+ ///
+ /// See .
+ ///
+ public Dictionary Properties { get; }
+
+ ///
+ /// The method info of the action if this is a .
+ /// See .
+ ///
+ public MethodInfo MethodInfo { get; }
+
+ ///
+ /// The name of the action's controller if this is a .
+ /// See .
+ ///
+ public string ControllerName { get; }
+
+ ///
+ /// The type info of the action's controller if this is a .
+ /// See .
+ ///
+ public TypeInfo ControllerTypeInfo { get; }
+
+ public override string Format()
+ {
+ return LogFormatter.FormatStructure(this);
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Microsoft.AspNet.Mvc.Core/Logging/ActionModelValues.cs b/src/Microsoft.AspNet.Mvc.Core/Logging/ActionModelValues.cs
new file mode 100644
index 0000000000..a4c5344f01
--- /dev/null
+++ b/src/Microsoft.AspNet.Mvc.Core/Logging/ActionModelValues.cs
@@ -0,0 +1,86 @@
+// 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.
+
+using System.Collections.Generic;
+using System.Linq;
+using System.Reflection;
+using Microsoft.AspNet.Mvc.ApplicationModels;
+using Microsoft.Framework.Logging;
+
+namespace Microsoft.AspNet.Mvc.Logging
+{
+ ///
+ /// Represents the state of an .
+ /// Logged as a substructure of
+ ///
+ public class ActionModelValues : LoggerStructureBase
+ {
+ // note: omit the controller as this structure is nested inside the ControllerModelValues it belongs to
+ public ActionModelValues(ActionModel inner)
+ {
+ if (inner != null)
+ {
+ ActionName = inner.ActionName;
+ ActionMethod = inner.ActionMethod;
+ ApiExplorer = new ApiExplorerModelValues(inner.ApiExplorer);
+ Parameters = inner.Parameters.Select(p => new ParameterModelValues(p)).ToList();
+ Filters = inner.Filters.Select(f => new FilterValues(f)).ToList();
+ if (inner.AttributeRouteModel != null)
+ {
+ AttributeRouteModel = new AttributeRouteModelValues(inner.AttributeRouteModel);
+ }
+ HttpMethods = inner.HttpMethods;
+ ActionConstraints = inner.ActionConstraints?.Select(a => new ActionConstraintValues(a))?.ToList();
+ }
+ }
+
+ ///
+ /// The name of the action. See .
+ ///
+ public string ActionName { get; }
+
+ ///
+ /// The method info of the action. See .
+ ///
+ public MethodInfo ActionMethod { get; }
+
+ ///
+ /// See .
+ ///
+ public ApiExplorerModelValues ApiExplorer { get; }
+
+ ///
+ /// The parameters of the action as .
+ /// See .
+ ///
+ public List Parameters { get; }
+
+ ///
+ /// The filters of the action as .
+ /// See .
+ ///
+ public List Filters { get; }
+
+ ///
+ /// The attribute route model of the action as .
+ /// See .
+ ///
+ public AttributeRouteModelValues AttributeRouteModel { get; }
+
+ ///
+ /// The http methods this action supports. See .
+ ///
+ public List HttpMethods { get; }
+
+ ///
+ /// The action constraints of the action as .
+ /// See .
+ ///
+ public List ActionConstraints { get; }
+
+ public override string Format()
+ {
+ return LogFormatter.FormatStructure(this);
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Microsoft.AspNet.Mvc.Core/Logging/ApiExplorerModelValues.cs b/src/Microsoft.AspNet.Mvc.Core/Logging/ApiExplorerModelValues.cs
new file mode 100644
index 0000000000..8cf64ae7a1
--- /dev/null
+++ b/src/Microsoft.AspNet.Mvc.Core/Logging/ApiExplorerModelValues.cs
@@ -0,0 +1,38 @@
+// 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.
+
+using Microsoft.AspNet.Mvc.ApplicationModels;
+using Microsoft.Framework.Logging;
+
+namespace Microsoft.AspNet.Mvc.Logging
+{
+ ///
+ /// Logging representation of an .
+ ///
+ public class ApiExplorerModelValues : LoggerStructureBase
+ {
+ public ApiExplorerModelValues(ApiExplorerModel inner)
+ {
+ if (inner != null)
+ {
+ IsVisible = inner.IsVisible;
+ GroupName = inner.GroupName;
+ }
+ }
+
+ ///
+ /// See .
+ ///
+ public bool? IsVisible { get; }
+
+ ///
+ /// See .
+ ///
+ public string GroupName { get; }
+
+ public override string Format()
+ {
+ return LogFormatter.FormatStructure(this);
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Microsoft.AspNet.Mvc.Core/Logging/AssemblyValues.cs b/src/Microsoft.AspNet.Mvc.Core/Logging/AssemblyValues.cs
new file mode 100644
index 0000000000..cc1dae48f7
--- /dev/null
+++ b/src/Microsoft.AspNet.Mvc.Core/Logging/AssemblyValues.cs
@@ -0,0 +1,45 @@
+// 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.
+
+using System.Reflection;
+using Microsoft.Framework.Logging;
+
+namespace Microsoft.AspNet.Mvc.Logging
+{
+ ///
+ /// Logging representation of the state of an . Logged during Assembly discovery in Startup.
+ ///
+ public class AssemblyValues : LoggerStructureBase
+ {
+ public AssemblyValues([NotNull] Assembly inner)
+ {
+ AssemblyName = inner.FullName;
+#if ASPNET50
+ Location = inner.Location;
+#endif
+ IsDynamic = inner.IsDynamic;
+ }
+
+ ///
+ /// The name of the assembly. See .
+ ///
+ public string AssemblyName { get; }
+
+#if ASPNET50
+ ///
+ /// The location of the assembly. See .
+ ///
+ public string Location { get; }
+#endif
+
+ ///
+ /// Whether or not the assembly is dynamic. See .
+ ///
+ public bool IsDynamic { get; }
+
+ public override string Format()
+ {
+ return LogFormatter.FormatStructure(this);
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Microsoft.AspNet.Mvc.Core/Logging/AttributeRouteInfoValues.cs b/src/Microsoft.AspNet.Mvc.Core/Logging/AttributeRouteInfoValues.cs
new file mode 100644
index 0000000000..ae983214ff
--- /dev/null
+++ b/src/Microsoft.AspNet.Mvc.Core/Logging/AttributeRouteInfoValues.cs
@@ -0,0 +1,42 @@
+// 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.
+
+using Microsoft.AspNet.Mvc.Routing;
+using Microsoft.Framework.Logging;
+
+namespace Microsoft.AspNet.Mvc.Logging
+{
+ ///
+ /// Logging representation of the state of a . Logged as a substructure of
+ /// .
+ ///
+ public class AttributeRouteInfoValues : LoggerStructureBase
+ {
+ public AttributeRouteInfoValues(AttributeRouteInfo inner)
+ {
+ Template = inner?.Template;
+ Order = inner?.Order;
+ Name = inner?.Name;
+ }
+
+ ///
+ /// The route template. See .
+ ///
+ public string Template { get; }
+
+ ///
+ /// The order of the route. See .
+ ///
+ public int? Order { get; }
+
+ ///
+ /// The name of the route. See .
+ ///
+ public string Name { get; }
+
+ public override string Format()
+ {
+ return LogFormatter.FormatStructure(this);
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Microsoft.AspNet.Mvc.Core/Logging/AttributeRouteModelValues.cs b/src/Microsoft.AspNet.Mvc.Core/Logging/AttributeRouteModelValues.cs
new file mode 100644
index 0000000000..7a5167b4f7
--- /dev/null
+++ b/src/Microsoft.AspNet.Mvc.Core/Logging/AttributeRouteModelValues.cs
@@ -0,0 +1,51 @@
+// 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.
+
+using Microsoft.Framework.Logging;
+using Microsoft.AspNet.Mvc.ApplicationModels;
+
+namespace Microsoft.AspNet.Mvc.Logging
+{
+ ///
+ /// Logging representation of the state of a . Logged as a substructure of
+ /// .
+ ///
+ public class AttributeRouteModelValues : LoggerStructureBase
+ {
+ public AttributeRouteModelValues(AttributeRouteModel inner)
+ {
+ if (inner != null)
+ {
+ Template = inner.Template;
+ Order = inner.Order;
+ Name = inner.Name;
+ IsAbsoluteTemplate = inner.IsAbsoluteTemplate;
+ }
+ }
+
+ ///
+ /// The template of the route. See .
+ ///
+ public string Template { get; }
+
+ ///
+ /// The order of the route. See .
+ ///
+ public int? Order { get; }
+
+ ///
+ /// The name of the route. See .
+ ///
+ public string Name { get; }
+
+ ///
+ /// Whether or not the template is absolute. See .
+ ///
+ public bool IsAbsoluteTemplate { get; }
+
+ public override string Format()
+ {
+ return LogFormatter.FormatStructure(this);
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Microsoft.AspNet.Mvc.Core/Logging/ControllerModelValues.cs b/src/Microsoft.AspNet.Mvc.Core/Logging/ControllerModelValues.cs
new file mode 100644
index 0000000000..7682934bb3
--- /dev/null
+++ b/src/Microsoft.AspNet.Mvc.Core/Logging/ControllerModelValues.cs
@@ -0,0 +1,91 @@
+// 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.
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using Microsoft.Framework.Logging;
+using Microsoft.AspNet.Mvc.ApplicationModels;
+
+namespace Microsoft.AspNet.Mvc.Logging
+{
+ ///
+ /// Logging representation of the state of a . Logged during controller discovery.
+ ///
+ public class ControllerModelValues : LoggerStructureBase
+ {
+ public ControllerModelValues(ControllerModel inner)
+ {
+ if (inner != null)
+ {
+ ControllerName = inner.ControllerName;
+ ControllerType = inner.ControllerType.AsType();
+ ApiExplorer = new ApiExplorerModelValues(inner.ApiExplorer);
+ Actions = inner.Actions.Select(a => new ActionModelValues(a)).ToList();
+ Attributes = inner.Attributes.Select(a => a.GetType()).ToList();
+ Filters = inner.Filters.Select(f => new FilterValues(f)).ToList();
+ ActionConstraints = inner.ActionConstraints?.Select(a => new ActionConstraintValues(a))?.ToList();
+ RouteConstraints = inner.RouteConstraints.Select(
+ r => new RouteConstraintAttributeValues(r)).ToList();
+ AttributeRoutes = inner.AttributeRoutes.Select(
+ a => new AttributeRouteModelValues(a)).ToList();
+ }
+ }
+
+ ///
+ /// The name of the controller. See .
+ ///
+ public string ControllerName { get; }
+
+ ///
+ /// The of the controller. See .
+ ///
+ public Type ControllerType { get; }
+
+ ///
+ /// See .
+ ///
+ public ApiExplorerModelValues ApiExplorer { get; }
+
+ ///
+ /// The actions of the controller as .
+ /// See .
+ ///
+ public List Actions { get; }
+
+ ///
+ /// The s of the controller's attributes.
+ /// See .
+ ///
+ public List Attributes { get; }
+
+ ///
+ /// The filters on the controller as .
+ /// See .
+ ///
+ public List Filters { get; }
+
+ ///
+ /// The action constraints on the controller as .
+ /// See .
+ ///
+ public List ActionConstraints { get; }
+
+ ///
+ /// The route constraints on the controller as .
+ /// See .
+ ///
+ public List RouteConstraints { get; set; }
+
+ ///
+ /// The attribute routes on the controller as .
+ /// See .
+ ///
+ public List AttributeRoutes { get; set; }
+
+ public override string Format()
+ {
+ return LogFormatter.FormatStructure(this);
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Microsoft.AspNet.Mvc.Core/Logging/ControllerStatus.cs b/src/Microsoft.AspNet.Mvc.Core/Logging/ControllerStatus.cs
new file mode 100644
index 0000000000..d64b8f8483
--- /dev/null
+++ b/src/Microsoft.AspNet.Mvc.Core/Logging/ControllerStatus.cs
@@ -0,0 +1,24 @@
+// 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.
+
+using System;
+
+namespace Microsoft.AspNet.Mvc.Logging
+{
+ ///
+ /// Indicates the status of a class during controller discovery.
+ /// All values except 0 represent a reason why a type is not a controller.
+ ///
+ [Flags]
+ public enum ControllerStatus
+ {
+ IsController = 0,
+ IsNotAClass = 1,
+ IsNotPublicOrTopLevel = 2,
+ IsAbstract = 4,
+ ContainsGenericParameters = 8,
+ // The name of the controller class is "Controller"
+ NameIsController = 16,
+ DoesNotEndWithControllerAndIsNotAssignable = 32
+ }
+}
\ No newline at end of file
diff --git a/src/Microsoft.AspNet.Mvc.Core/Logging/FilterDescriptorValues.cs b/src/Microsoft.AspNet.Mvc.Core/Logging/FilterDescriptorValues.cs
new file mode 100644
index 0000000000..53c3a95f18
--- /dev/null
+++ b/src/Microsoft.AspNet.Mvc.Core/Logging/FilterDescriptorValues.cs
@@ -0,0 +1,42 @@
+// 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.
+
+using Microsoft.Framework.Logging;
+
+namespace Microsoft.AspNet.Mvc.Logging
+{
+ ///
+ /// Logging representation of the state of a . Logged as a substructure of
+ /// .
+ ///
+ public class FilterDescriptorValues : LoggerStructureBase
+ {
+ public FilterDescriptorValues([NotNull] FilterDescriptor inner)
+ {
+ Filter = new FilterValues(inner.Filter);
+ Order = inner.Order;
+ Scope = inner.Scope;
+ }
+
+ ///
+ /// The instance of the filter descriptor as .
+ /// See .
+ ///
+ public FilterValues Filter { get; }
+
+ ///
+ /// The filter order. See .
+ ///
+ public int Order { get; }
+
+ ///
+ /// The filter scope. See .
+ ///
+ public int Scope { get; }
+
+ public override string Format()
+ {
+ return LogFormatter.FormatStructure(this);
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Microsoft.AspNet.Mvc.Core/Logging/FilterValues.cs b/src/Microsoft.AspNet.Mvc.Core/Logging/FilterValues.cs
new file mode 100644
index 0000000000..60151950cb
--- /dev/null
+++ b/src/Microsoft.AspNet.Mvc.Core/Logging/FilterValues.cs
@@ -0,0 +1,66 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using Microsoft.Framework.Logging;
+
+namespace Microsoft.AspNet.Mvc.Logging
+{
+ ///
+ /// Logging representation of an . Logged as a component of
+ /// , and as a substructure of
+ /// and .
+ ///
+ public class FilterValues : LoggerStructureBase
+ {
+ public FilterValues(IFilter inner)
+ {
+ FilterMetadataType = inner.GetType();
+ if (inner is IFilterFactory)
+ {
+ IsFactory = true;
+ if (inner is ServiceFilterAttribute)
+ {
+ FilterType = ((ServiceFilterAttribute)inner).ServiceType;
+ }
+ else if (inner is TypeFilterAttribute)
+ {
+ FilterType = ((TypeFilterAttribute)inner).ImplementationType;
+ }
+ }
+ if (FilterType != null)
+ {
+ FilterInterfaces = FilterType.GetInterfaces().ToList();
+ }
+ else
+ {
+ FilterInterfaces = FilterMetadataType.GetInterfaces().ToList();
+ }
+ }
+
+ ///
+ /// Whether or not the instance of is an .
+ ///
+ public bool IsFactory { get; }
+
+ ///
+ /// The metadata type of the .
+ ///
+ public Type FilterMetadataType { get; }
+
+ ///
+ /// The inner of the if it is a
+ /// or .
+ ///
+ public Type FilterType { get; }
+
+ ///
+ /// A list of interfaces the implements.
+ ///
+ public List FilterInterfaces { get; }
+
+ public override string Format()
+ {
+ return LogFormatter.FormatStructure(this);
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Microsoft.AspNet.Mvc.Core/Logging/IsControllerValues.cs b/src/Microsoft.AspNet.Mvc.Core/Logging/IsControllerValues.cs
new file mode 100644
index 0000000000..3d6ddb8b9e
--- /dev/null
+++ b/src/Microsoft.AspNet.Mvc.Core/Logging/IsControllerValues.cs
@@ -0,0 +1,36 @@
+// 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.
+
+using System;
+using Microsoft.Framework.Logging;
+
+namespace Microsoft.AspNet.Mvc.Logging
+{
+ ///
+ /// Logged to indicate the state of a class during controller discovery. Logs the type
+ /// of the controller as well as the .
+ ///
+ public class IsControllerValues : LoggerStructureBase
+ {
+ public IsControllerValues(Type type, ControllerStatus status)
+ {
+ Type = type;
+ Status = status;
+ }
+
+ ///
+ /// The of the potential class.
+ ///
+ public Type Type { get; }
+
+ ///
+ /// The of the .
+ ///
+ public ControllerStatus Status { get; }
+
+ public override string Format()
+ {
+ return LogFormatter.FormatStructure(this);
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Microsoft.AspNet.Mvc.Core/Logging/LogFormatter.cs b/src/Microsoft.AspNet.Mvc.Core/Logging/LogFormatter.cs
deleted file mode 100644
index e9d1e7d0a1..0000000000
--- a/src/Microsoft.AspNet.Mvc.Core/Logging/LogFormatter.cs
+++ /dev/null
@@ -1,37 +0,0 @@
-// 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.
-
-using System;
-
-namespace Microsoft.AspNet.Mvc.Logging
-{
- public static class LogFormatter
- {
- ///
- /// A formatter for use with .
- ///
- public static string Formatter(object o, Exception e)
- {
- if (o != null && e != null)
- {
- return o + Environment.NewLine + e;
- }
-
- if (o != null)
- {
- return o.ToString();
- }
-
- if (e != null)
- {
- return e.ToString();
- }
-
- return "";
- }
- }
-}
\ No newline at end of file
diff --git a/src/Microsoft.AspNet.Mvc.Core/Logging/ParameterDescriptorValues.cs b/src/Microsoft.AspNet.Mvc.Core/Logging/ParameterDescriptorValues.cs
new file mode 100644
index 0000000000..3a8cc407a0
--- /dev/null
+++ b/src/Microsoft.AspNet.Mvc.Core/Logging/ParameterDescriptorValues.cs
@@ -0,0 +1,42 @@
+// 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.
+
+using System;
+using Microsoft.Framework.Logging;
+
+namespace Microsoft.AspNet.Mvc.Logging
+{
+ ///
+ /// Logging representation of a . Logged as a substructure of
+ /// .
+ ///
+ public class ParameterDescriptorValues : LoggerStructureBase
+ {
+ public ParameterDescriptorValues([NotNull] ParameterDescriptor inner)
+ {
+ ParameterName = inner.Name;
+ ParameterType = inner.ParameterType;
+ BinderMetadataType = inner.BinderMetadata?.GetType();
+ }
+
+ ///
+ /// The name of the parameter. See .
+ ///
+ public string ParameterName { get; }
+
+ ///
+ /// The of the parameter. See .
+ ///
+ public Type ParameterType { get; }
+
+ ///
+ /// The of the .
+ ///
+ public Type BinderMetadataType { get; }
+
+ public override string Format()
+ {
+ return LogFormatter.FormatStructure(this);
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Microsoft.AspNet.Mvc.Core/Logging/ParameterModelValues.cs b/src/Microsoft.AspNet.Mvc.Core/Logging/ParameterModelValues.cs
new file mode 100644
index 0000000000..62b179ece5
--- /dev/null
+++ b/src/Microsoft.AspNet.Mvc.Core/Logging/ParameterModelValues.cs
@@ -0,0 +1,44 @@
+// 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.
+
+using System;
+using Microsoft.AspNet.Mvc.ApplicationModels;
+using Microsoft.Framework.Logging;
+
+namespace Microsoft.AspNet.Mvc.Logging
+{
+ ///
+ /// Logging representation of a . Logged as a substructure of
+ /// , this contains the name, type, and
+ /// binder metadata of the parameter.
+ ///
+ public class ParameterModelValues : LoggerStructureBase
+ {
+ public ParameterModelValues([NotNull] ParameterModel inner)
+ {
+ ParameterName = inner.ParameterName;
+ ParameterType = inner.ParameterInfo.ParameterType;
+ BinderMetadata = inner.BinderMetadata?.GetType();
+ }
+
+ ///
+ /// The name of the parameter. See .
+ ///
+ public string ParameterName { get; }
+
+ ///
+ /// The of the parameter.
+ ///
+ public Type ParameterType { get; }
+
+ ///
+ /// The of the .
+ ///
+ public Type BinderMetadata { get; }
+
+ public override string Format()
+ {
+ return LogFormatter.FormatStructure(this);
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Microsoft.AspNet.Mvc.Core/Logging/RouteConstraintAttributeValues.cs b/src/Microsoft.AspNet.Mvc.Core/Logging/RouteConstraintAttributeValues.cs
new file mode 100644
index 0000000000..75638d97b8
--- /dev/null
+++ b/src/Microsoft.AspNet.Mvc.Core/Logging/RouteConstraintAttributeValues.cs
@@ -0,0 +1,47 @@
+// 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.
+
+using Microsoft.Framework.Logging;
+
+namespace Microsoft.AspNet.Mvc.Logging
+{
+ ///
+ /// Logging representation of a . Logged as a substructure of
+ ///
+ ///
+ public class RouteConstraintAttributeValues : LoggerStructureBase
+ {
+ public RouteConstraintAttributeValues([NotNull] RouteConstraintAttribute inner)
+ {
+ RouteKey = inner.RouteKey;
+ RouteValue = inner.RouteValue;
+ RouteKeyHandling = inner.RouteKeyHandling;
+ BlockNonAttributedActions = inner.BlockNonAttributedActions;
+ }
+
+ ///
+ /// The route value key. See .
+ ///
+ public string RouteKey { get; }
+
+ ///
+ /// The expected route value. See .
+ ///
+ public string RouteValue { get; }
+
+ ///
+ /// The . See .
+ ///
+ public RouteKeyHandling RouteKeyHandling { get; }
+
+ ///
+ /// See .
+ ///
+ public bool BlockNonAttributedActions { get; }
+
+ public override string Format()
+ {
+ return LogFormatter.FormatStructure(this);
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Microsoft.AspNet.Mvc.Core/Logging/RouteDataActionConstraintValues.cs b/src/Microsoft.AspNet.Mvc.Core/Logging/RouteDataActionConstraintValues.cs
new file mode 100644
index 0000000000..e1e066d454
--- /dev/null
+++ b/src/Microsoft.AspNet.Mvc.Core/Logging/RouteDataActionConstraintValues.cs
@@ -0,0 +1,41 @@
+// 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.
+
+using Microsoft.Framework.Logging;
+
+namespace Microsoft.AspNet.Mvc.Logging
+{
+ ///
+ /// Logging representation of the state of a . Logged as a substructure of
+ /// .
+ ///
+ public class RouteDataActionConstraintValues : LoggerStructureBase
+ {
+ public RouteDataActionConstraintValues([NotNull] RouteDataActionConstraint inner)
+ {
+ RouteKey = inner.RouteKey;
+ RouteValue = inner.RouteValue;
+ KeyHandling = inner.KeyHandling;
+ }
+
+ ///
+ /// The route key. See .
+ ///
+ public string RouteKey { get; }
+
+ ///
+ /// The route value. See .
+ ///
+ public string RouteValue { get; }
+
+ ///
+ /// The . See .
+ ///
+ public RouteKeyHandling KeyHandling { get; }
+
+ public override string Format()
+ {
+ return LogFormatter.FormatStructure(this);
+ }
+ }
+}
\ No newline at end of file
diff --git a/test/Microsoft.AspNet.Mvc.Core.Test/ActionConstraintValuesTest.cs b/test/Microsoft.AspNet.Mvc.Core.Test/ActionConstraintValuesTest.cs
new file mode 100644
index 0000000000..804673d333
--- /dev/null
+++ b/test/Microsoft.AspNet.Mvc.Core.Test/ActionConstraintValuesTest.cs
@@ -0,0 +1,84 @@
+// 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.
+
+using System;
+using Xunit;
+
+namespace Microsoft.AspNet.Mvc.Logging
+{
+ public class ActionConstraintValuesTest
+ {
+ [Fact]
+ public void IActionConstraintMetadata_InitializesCorrectValues()
+ {
+ // Arrange
+ var constraint = new TestConstraintMetadata();
+
+ // Act
+ var constraintValues = new ActionConstraintValues(constraint);
+
+ // Assert
+ Assert.False(constraintValues.IsConstraint);
+ Assert.False(constraintValues.IsFactory);
+ Assert.Equal(0, constraintValues.Order);
+ Assert.Equal(typeof(TestConstraintMetadata), constraintValues.ActionConstraintMetadataType);
+ }
+
+ [Fact]
+ public void IActionConstraint_InitializesCorrectValues()
+ {
+ // Arrange
+ var constraint = new TestConstraint();
+
+ // Act
+ var constraintValues = new ActionConstraintValues(constraint);
+
+ // Assert
+ Assert.True(constraintValues.IsConstraint);
+ Assert.False(constraintValues.IsFactory);
+ Assert.Equal(23, constraintValues.Order);
+ Assert.Equal(typeof(TestConstraint), constraintValues.ActionConstraintMetadataType);
+ }
+
+ [Fact]
+ public void IActionConstraintFactory_InitializesCorrectValues()
+ {
+ // Arrange
+ var constraint = new TestFactory();
+
+ // Act
+ var constraintValues = new ActionConstraintValues(constraint);
+
+ // Assert
+ Assert.False(constraintValues.IsConstraint);
+ Assert.True(constraintValues.IsFactory);
+ Assert.Equal(0, constraintValues.Order);
+ Assert.Equal(typeof(TestFactory), constraintValues.ActionConstraintMetadataType);
+ }
+
+ private class TestConstraintMetadata : IActionConstraintMetadata
+ {
+ }
+
+ private class TestConstraint : IActionConstraint
+ {
+ public int Order
+ {
+ get { return 23; }
+ }
+
+ public bool Accept(ActionConstraintContext context)
+ {
+ return false;
+ }
+ }
+
+ private class TestFactory : IActionConstraintFactory
+ {
+ public IActionConstraint CreateInstance(IServiceProvider services)
+ {
+ return new TestConstraint();
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/test/Microsoft.AspNet.Mvc.Core.Test/ActionDescriptorValuesTest.cs b/test/Microsoft.AspNet.Mvc.Core.Test/ActionDescriptorValuesTest.cs
new file mode 100644
index 0000000000..9ad84e2a34
--- /dev/null
+++ b/test/Microsoft.AspNet.Mvc.Core.Test/ActionDescriptorValuesTest.cs
@@ -0,0 +1,23 @@
+// 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.
+
+using Xunit;
+
+namespace Microsoft.AspNet.Mvc.Logging
+{
+ public class ActionDescriptorValuesTest
+ {
+ [Fact]
+ public void ActionDescriptorValues_IncludesAllProperties()
+ {
+ // Arrange
+ var include = new[] { "HttpMethods" };
+
+ // Assert
+ PropertiesAssert.PropertiesAreTheSame(
+ typeof(ControllerActionDescriptor),
+ typeof(ActionDescriptorValues),
+ include: include);
+ }
+ }
+}
\ No newline at end of file
diff --git a/test/Microsoft.AspNet.Mvc.Core.Test/ActionModelValuesTest.cs b/test/Microsoft.AspNet.Mvc.Core.Test/ActionModelValuesTest.cs
new file mode 100644
index 0000000000..ec058efb7d
--- /dev/null
+++ b/test/Microsoft.AspNet.Mvc.Core.Test/ActionModelValuesTest.cs
@@ -0,0 +1,24 @@
+// 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.
+
+using Microsoft.AspNet.Mvc.ApplicationModels;
+using Xunit;
+
+namespace Microsoft.AspNet.Mvc.Logging
+{
+ public class ActionModelValuesTest
+ {
+ [Fact]
+ public void ActionModelValues_IncludesAllProperties()
+ {
+ // Arrange
+ var exclude = new[] { "Controller", "Attributes", "IsActionNameMatchRequired" };
+
+ // Assert
+ PropertiesAssert.PropertiesAreTheSame(
+ typeof(ActionModel),
+ typeof(ActionModelValues),
+ exclude);
+ }
+ }
+}
\ No newline at end of file
diff --git a/test/Microsoft.AspNet.Mvc.Core.Test/ApiExplorerModelValuesTest.cs b/test/Microsoft.AspNet.Mvc.Core.Test/ApiExplorerModelValuesTest.cs
new file mode 100644
index 0000000000..8ff5eb427a
--- /dev/null
+++ b/test/Microsoft.AspNet.Mvc.Core.Test/ApiExplorerModelValuesTest.cs
@@ -0,0 +1,20 @@
+// 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.
+
+using Microsoft.AspNet.Mvc.ApplicationModels;
+using Xunit;
+
+namespace Microsoft.AspNet.Mvc.Logging
+{
+ public class ApiExplorerModelValuesTest
+ {
+ [Fact]
+ public void ApiExplorerModelValues_IncludesAllProperties()
+ {
+ // Assert
+ PropertiesAssert.PropertiesAreTheSame(
+ typeof(ApiExplorerModel),
+ typeof(ApiExplorerModelValues));
+ }
+ }
+}
\ No newline at end of file
diff --git a/test/Microsoft.AspNet.Mvc.Core.Test/ApplicationModel/DefaultControllerModelBuilderTest.cs b/test/Microsoft.AspNet.Mvc.Core.Test/ApplicationModel/DefaultControllerModelBuilderTest.cs
index e02d2431c6..87481ef450 100644
--- a/test/Microsoft.AspNet.Mvc.Core.Test/ApplicationModel/DefaultControllerModelBuilderTest.cs
+++ b/test/Microsoft.AspNet.Mvc.Core.Test/ApplicationModel/DefaultControllerModelBuilderTest.cs
@@ -166,7 +166,7 @@ namespace Microsoft.AspNet.Mvc.ApplicationModels
private class AccessibleControllerModelBuilder : DefaultControllerModelBuilder
{
public AccessibleControllerModelBuilder()
- : base(new DefaultActionModelBuilder())
+ : base(new DefaultActionModelBuilder(), new NullLoggerFactory())
{
}
diff --git a/test/Microsoft.AspNet.Mvc.Core.Test/AttributeRouteInfoValuesTest.cs b/test/Microsoft.AspNet.Mvc.Core.Test/AttributeRouteInfoValuesTest.cs
new file mode 100644
index 0000000000..f9da445d10
--- /dev/null
+++ b/test/Microsoft.AspNet.Mvc.Core.Test/AttributeRouteInfoValuesTest.cs
@@ -0,0 +1,24 @@
+// 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.
+
+using Microsoft.AspNet.Mvc.ApplicationModels;
+using Xunit;
+
+namespace Microsoft.AspNet.Mvc.Logging
+{
+ public class AttributeRouteInfoValuesTest
+ {
+ [Fact]
+ public void AttributeRouteModelValues_IncludesAllProperties()
+ {
+ // Arrange
+ var exclude = new[] { "Attribute" };
+
+ // Assert
+ PropertiesAssert.PropertiesAreTheSame(
+ typeof(AttributeRouteModel),
+ typeof(AttributeRouteModelValues),
+ exclude);
+ }
+ }
+}
\ No newline at end of file
diff --git a/test/Microsoft.AspNet.Mvc.Core.Test/AttributeRouteModelValuesTest.cs b/test/Microsoft.AspNet.Mvc.Core.Test/AttributeRouteModelValuesTest.cs
new file mode 100644
index 0000000000..07b45ef980
--- /dev/null
+++ b/test/Microsoft.AspNet.Mvc.Core.Test/AttributeRouteModelValuesTest.cs
@@ -0,0 +1,20 @@
+// 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.
+
+using Microsoft.AspNet.Mvc.Routing;
+using Xunit;
+
+namespace Microsoft.AspNet.Mvc.Logging
+{
+ public class AttributeRouteModelValuesTest
+ {
+ [Fact]
+ public void AttributeRouteInfoValues_IncludesAllProperties()
+ {
+ // Assert
+ PropertiesAssert.PropertiesAreTheSame(
+ typeof(AttributeRouteInfo),
+ typeof(AttributeRouteInfoValues));
+ }
+ }
+}
\ No newline at end of file
diff --git a/test/Microsoft.AspNet.Mvc.Core.Test/ControllerActionDescriptorProviderTests.cs b/test/Microsoft.AspNet.Mvc.Core.Test/ControllerActionDescriptorProviderTests.cs
index 286f311e67..6e9034a301 100644
--- a/test/Microsoft.AspNet.Mvc.Core.Test/ControllerActionDescriptorProviderTests.cs
+++ b/test/Microsoft.AspNet.Mvc.Core.Test/ControllerActionDescriptorProviderTests.cs
@@ -1340,7 +1340,8 @@ namespace Microsoft.AspNet.Mvc.Test
assemblyProvider.Object,
modelBuilder,
new TestGlobalFilterProvider(filters),
- new MockMvcOptionsAccessor());
+ new MockMvcOptionsAccessor(),
+ new NullLoggerFactory());
return provider;
}
@@ -1359,7 +1360,8 @@ namespace Microsoft.AspNet.Mvc.Test
assemblyProvider.Object,
modelBuilder,
new TestGlobalFilterProvider(),
- new MockMvcOptionsAccessor());
+ new MockMvcOptionsAccessor(),
+ new NullLoggerFactory());
return provider;
}
@@ -1379,7 +1381,8 @@ namespace Microsoft.AspNet.Mvc.Test
assemblyProvider.Object,
modelBuilder,
new TestGlobalFilterProvider(),
- options);
+ options,
+ new NullLoggerFactory());
}
private IEnumerable GetDescriptors(params TypeInfo[] controllerTypeInfos)
@@ -1395,7 +1398,8 @@ namespace Microsoft.AspNet.Mvc.Test
assemblyProvider.Object,
modelBuilder,
new TestGlobalFilterProvider(),
- new MockMvcOptionsAccessor());
+ new MockMvcOptionsAccessor(),
+ new NullLoggerFactory());
return provider.GetDescriptors();
}
diff --git a/test/Microsoft.AspNet.Mvc.Core.Test/ControllerModelValuesTest.cs b/test/Microsoft.AspNet.Mvc.Core.Test/ControllerModelValuesTest.cs
new file mode 100644
index 0000000000..b1b089943e
--- /dev/null
+++ b/test/Microsoft.AspNet.Mvc.Core.Test/ControllerModelValuesTest.cs
@@ -0,0 +1,24 @@
+// 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.
+
+using Microsoft.AspNet.Mvc.ApplicationModels;
+using Xunit;
+
+namespace Microsoft.AspNet.Mvc.Logging
+{
+ public class ControllerModelValuesTest
+ {
+ [Fact]
+ public void ControllerModelValues_IncludesAllProperties()
+ {
+ // Arrange
+ var exclude = new[] { "Application" };
+
+ // Assert
+ PropertiesAssert.PropertiesAreTheSame(
+ typeof(ControllerModel),
+ typeof(ControllerModelValues),
+ exclude);
+ }
+ }
+}
\ No newline at end of file
diff --git a/test/Microsoft.AspNet.Mvc.Core.Test/DefaultActionDescriptorCollectionProviderLoggingTest.cs b/test/Microsoft.AspNet.Mvc.Core.Test/DefaultActionDescriptorCollectionProviderLoggingTest.cs
new file mode 100644
index 0000000000..5e8761f81c
--- /dev/null
+++ b/test/Microsoft.AspNet.Mvc.Core.Test/DefaultActionDescriptorCollectionProviderLoggingTest.cs
@@ -0,0 +1,177 @@
+// 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.
+
+using System.ComponentModel.Design;
+using System.Linq;
+using System.Reflection;
+using Microsoft.AspNet.Mvc.ApplicationModels;
+using Microsoft.Framework.DependencyInjection;
+using Microsoft.Framework.DependencyInjection.NestedProviders;
+using Microsoft.Framework.Logging;
+using Moq;
+using Xunit;
+
+namespace Microsoft.AspNet.Mvc.Logging
+{
+ public class DefaultActionDescriptorCollectionProviderLoggingTest
+ {
+ [Fact]
+ public void SimpleController_AssemblyDiscovery()
+ {
+ // Arrange
+ var sink = new TestSink();
+ var loggerFactory = new TestLoggerFactory(sink);
+
+ // Act
+ var provider = GetProvider(loggerFactory, typeof(SimpleController).GetTypeInfo());
+ provider.BuildModel();
+
+ // Assert
+ Assert.Single(sink.Writes);
+
+ var assemblyValues = sink.Writes[0].State as AssemblyValues;
+ Assert.NotNull(assemblyValues);
+ Assert.True(assemblyValues.AssemblyName.Contains("Microsoft.AspNet.Mvc.Core.Test"));
+ }
+
+ [Fact]
+ public void ControllerDiscovery()
+ {
+ // Arrange
+ var sink = new TestSink();
+ var loggerFactory = new TestLoggerFactory(sink);
+
+ // Act
+ var provider = GetProvider(
+ loggerFactory,
+ typeof(SimpleController).GetTypeInfo(),
+ typeof(BasicController).GetTypeInfo());
+ provider.GetDescriptors();
+
+ // Assert
+ // 1 assembly, 2 controllers
+ Assert.Equal(3, sink.Writes.Count);
+
+ var controllerModelValues = sink.Writes[1].State as ControllerModelValues;
+ Assert.NotNull(controllerModelValues);
+ Assert.Equal("Simple", controllerModelValues.ControllerName);
+ Assert.Equal(typeof(SimpleController), controllerModelValues.ControllerType);
+ Assert.Single(controllerModelValues.Actions);
+ Assert.Empty(controllerModelValues.AttributeRoutes);
+ Assert.Empty(controllerModelValues.RouteConstraints);
+ Assert.Empty(controllerModelValues.Attributes);
+ Assert.Empty(controllerModelValues.Filters);
+
+ controllerModelValues = sink.Writes[2].State as ControllerModelValues;
+ Assert.NotNull(controllerModelValues);
+ Assert.Equal("Basic", controllerModelValues.ControllerName);
+ Assert.Equal(typeof(BasicController), controllerModelValues.ControllerType);
+ Assert.Equal(2, controllerModelValues.Actions.Count);
+ Assert.Equal("GET", controllerModelValues.Actions[0].HttpMethods.FirstOrDefault());
+ Assert.Equal("POST", controllerModelValues.Actions[1].HttpMethods.FirstOrDefault());
+ Assert.Empty(controllerModelValues.AttributeRoutes);
+ Assert.Empty(controllerModelValues.RouteConstraints);
+ Assert.NotEmpty(controllerModelValues.Attributes);
+ Assert.Single(controllerModelValues.Filters);
+ }
+
+ [Fact]
+ public void ActionDiscovery()
+ {
+ // Arrange
+ var sink = new TestSink();
+ var loggerFactory = new TestLoggerFactory(sink);
+
+ // Act
+ CreateActionDescriptors(loggerFactory,
+ typeof(SimpleController).GetTypeInfo(),
+ typeof(BasicController).GetTypeInfo());
+
+ // Assert
+ // 1 assembly, 2 controllers, 3 actions
+ Assert.Equal(6, sink.Writes.Count);
+
+ var actionDescriptorValues = sink.Writes[3].State as ActionDescriptorValues;
+ Assert.NotNull(actionDescriptorValues);
+ Assert.Equal("EmptyAction", actionDescriptorValues.Name);
+ Assert.Equal("Simple", actionDescriptorValues.ControllerName);
+ Assert.Equal(typeof(SimpleController), actionDescriptorValues.ControllerTypeInfo);
+ Assert.Null(actionDescriptorValues.AttributeRouteInfo.Name);
+ Assert.Null(actionDescriptorValues.ActionConstraints);
+ Assert.Empty(actionDescriptorValues.FilterDescriptors);
+ Assert.Empty(actionDescriptorValues.Parameters);
+
+ actionDescriptorValues = sink.Writes[4].State as ActionDescriptorValues;
+ Assert.NotNull(actionDescriptorValues);
+ Assert.Equal("Basic", actionDescriptorValues.Name);
+ Assert.Equal("Basic", actionDescriptorValues.ControllerName);
+ Assert.Equal(typeof(BasicController), actionDescriptorValues.ControllerTypeInfo);
+ Assert.Null(actionDescriptorValues.AttributeRouteInfo.Name);
+ Assert.NotEmpty(actionDescriptorValues.ActionConstraints);
+ Assert.Equal(2, actionDescriptorValues.FilterDescriptors.Count);
+ Assert.Empty(actionDescriptorValues.Parameters);
+
+ actionDescriptorValues = sink.Writes[5].State as ActionDescriptorValues;
+ Assert.NotNull(actionDescriptorValues);
+ Assert.Equal("Basic", actionDescriptorValues.Name);
+ Assert.Equal("Basic", actionDescriptorValues.ControllerName);
+ Assert.Equal(typeof(BasicController), actionDescriptorValues.ControllerTypeInfo);
+ Assert.Null(actionDescriptorValues.AttributeRouteInfo.Name);
+ Assert.NotEmpty(actionDescriptorValues.ActionConstraints);
+ Assert.Single(actionDescriptorValues.FilterDescriptors);
+ Assert.Single(actionDescriptorValues.RouteConstraints);
+ Assert.Single(actionDescriptorValues.Parameters);
+ }
+
+ private void CreateActionDescriptors(ILoggerFactory loggerFactory, params TypeInfo[] controllerTypeInfo)
+ {
+ var actionDescriptorProvider = GetProvider(loggerFactory, controllerTypeInfo);
+ var descriptorProvider =
+ new NestedProviderManager(new[] { actionDescriptorProvider });
+
+ var serviceContainer = new ServiceContainer();
+ serviceContainer.AddService(typeof(INestedProviderManager),
+ descriptorProvider);
+
+ var actionCollectionDescriptorProvider = new DefaultActionDescriptorsCollectionProvider(serviceContainer, loggerFactory);
+ var descriptors = actionCollectionDescriptorProvider.ActionDescriptors;
+ }
+
+ private ControllerActionDescriptorProvider GetProvider(
+ ILoggerFactory loggerFactory, params TypeInfo[] controllerTypeInfo)
+ {
+ var modelBuilder = new StaticControllerModelBuilder(controllerTypeInfo);
+
+ var assemblyProvider = new Mock();
+ assemblyProvider
+ .SetupGet(ap => ap.CandidateAssemblies)
+ .Returns(new Assembly[] { controllerTypeInfo.First().Assembly });
+
+ var provider = new ControllerActionDescriptorProvider(
+ assemblyProvider.Object,
+ modelBuilder,
+ new TestGlobalFilterProvider(),
+ new MockMvcOptionsAccessor(),
+ loggerFactory);
+
+ return provider;
+ }
+
+ private class SimpleController
+ {
+ public void EmptyAction() { }
+ }
+
+ [Authorize]
+ private class BasicController
+ {
+ [HttpGet]
+ [AllowAnonymous]
+ public void Basic() { }
+
+ [HttpPost]
+ [Route("/Basic")]
+ public void Basic(int id) { }
+ }
+ }
+}
\ No newline at end of file
diff --git a/test/Microsoft.AspNet.Mvc.Core.Test/DefaultActionSelectorTests.cs b/test/Microsoft.AspNet.Mvc.Core.Test/DefaultActionSelectorTests.cs
index c8b5b71b49..dddfeac1cc 100644
--- a/test/Microsoft.AspNet.Mvc.Core.Test/DefaultActionSelectorTests.cs
+++ b/test/Microsoft.AspNet.Mvc.Core.Test/DefaultActionSelectorTests.cs
@@ -739,7 +739,7 @@ namespace Microsoft.AspNet.Mvc
serviceContainer.AddService(typeof(INestedProviderManager),
descriptorProvider);
- var actionCollectionDescriptorProvider = new DefaultActionDescriptorsCollectionProvider(serviceContainer);
+ var actionCollectionDescriptorProvider = new DefaultActionDescriptorsCollectionProvider(serviceContainer, new NullLoggerFactory());
var decisionTreeProvider = new ActionSelectorDecisionTreeProvider(actionCollectionDescriptorProvider);
var actionConstraintProvider = new NestedProviderManager(
@@ -771,7 +771,8 @@ namespace Microsoft.AspNet.Mvc
assemblyProvider,
modelBuilder,
new TestGlobalFilterProvider(),
- new MockMvcOptionsAccessor());
+ new MockMvcOptionsAccessor(),
+ new NullLoggerFactory());
}
private static HttpContext GetHttpContext(string httpMethod)
diff --git a/test/Microsoft.AspNet.Mvc.Core.Test/FilterDescriptorValuesTest.cs b/test/Microsoft.AspNet.Mvc.Core.Test/FilterDescriptorValuesTest.cs
new file mode 100644
index 0000000000..4850d4d5c8
--- /dev/null
+++ b/test/Microsoft.AspNet.Mvc.Core.Test/FilterDescriptorValuesTest.cs
@@ -0,0 +1,20 @@
+// 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.
+
+using Microsoft.AspNet.Mvc.Logging;
+using Xunit;
+
+namespace Microsoft.AspNet.Mvc.Test.Logging
+{
+ public class FilterDescriptorValuesTest
+ {
+ [Fact]
+ public void FilterDescriptorValues_IncludesAllProperties()
+ {
+ // Assert
+ PropertiesAssert.PropertiesAreTheSame(
+ typeof(FilterDescriptor),
+ typeof(FilterDescriptorValues));
+ }
+ }
+}
\ No newline at end of file
diff --git a/test/Microsoft.AspNet.Mvc.Core.Test/FilterValuesTest.cs b/test/Microsoft.AspNet.Mvc.Core.Test/FilterValuesTest.cs
new file mode 100644
index 0000000000..446273d69e
--- /dev/null
+++ b/test/Microsoft.AspNet.Mvc.Core.Test/FilterValuesTest.cs
@@ -0,0 +1,99 @@
+// 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.
+
+using System;
+using System.Collections.Generic;
+using Xunit;
+
+namespace Microsoft.AspNet.Mvc.Logging
+{
+ public class FilterValuesTest
+ {
+ [Fact]
+ public void IFilter_InitializesCorrectValues()
+ {
+ // Arrange
+ var filter = new TestFilter();
+
+ // Act
+ var filterValues = new FilterValues(filter);
+
+ // Assert
+ Assert.False(filterValues.IsFactory);
+ Assert.Null(filterValues.FilterType);
+ Assert.Equal(typeof(TestFilter), filterValues.FilterMetadataType);
+ Assert.Equal(
+ new List() { typeof(IFilter), typeof(IExceptionFilter) },
+ filterValues.FilterInterfaces);
+ }
+
+ [Fact]
+ public void IFilterFactory_InitializesCorrectValues()
+ {
+ // Arrange
+ var filter = new TestFactory();
+
+ // Act
+ var filterValues = new FilterValues(filter);
+
+ // Assert
+ Assert.True(filterValues.IsFactory);
+ Assert.Null(filterValues.FilterType);
+ Assert.Equal(typeof(TestFactory), filterValues.FilterMetadataType);
+ Assert.Equal(
+ new List() { typeof(IFilterFactory), typeof(IFilter) },
+ filterValues.FilterInterfaces);
+ }
+
+ [Fact]
+ public void ServiceFilterAttribute_InitializesCorrectValues()
+ {
+ // Arrange
+ var filter = new ServiceFilterAttribute(typeof(TestFilter));
+
+ // Act
+ var filterValues = new FilterValues(filter);
+
+ // Assert
+ Assert.True(filterValues.IsFactory);
+ Assert.Equal(typeof(TestFilter), filterValues.FilterType);
+ Assert.Equal(typeof(ServiceFilterAttribute), filterValues.FilterMetadataType);
+ Assert.Equal(
+ new List() { typeof(IFilter), typeof(IExceptionFilter) },
+ filterValues.FilterInterfaces);
+ }
+
+ [Fact]
+ public void TypeFilterAttribute_InitializesCorrectValues()
+ {
+ // Arrange
+ var filter = new TypeFilterAttribute(typeof(TestFilter));
+
+ // Act
+ var filterValues = new FilterValues(filter);
+
+ // Assert
+ Assert.True(filterValues.IsFactory);
+ Assert.Equal(typeof(TestFilter), filterValues.FilterType);
+ Assert.Equal(typeof(TypeFilterAttribute), filterValues.FilterMetadataType);
+ Assert.Equal(
+ new List() { typeof(IFilter), typeof(IExceptionFilter) },
+ filterValues.FilterInterfaces);
+ }
+
+ private class TestFilter : IFilter, IExceptionFilter
+ {
+ public void OnException(ExceptionContext context)
+ {
+ }
+ }
+
+ private class TestFactory : IFilterFactory
+ {
+ public IFilter CreateInstance(IServiceProvider serviceProvider)
+ {
+ return new TestFilter();
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/test/Microsoft.AspNet.Mvc.Core.Test/KnownRouteValueConstraintTests.cs b/test/Microsoft.AspNet.Mvc.Core.Test/KnownRouteValueConstraintTests.cs
index 9afcdac612..4cda51fa84 100644
--- a/test/Microsoft.AspNet.Mvc.Core.Test/KnownRouteValueConstraintTests.cs
+++ b/test/Microsoft.AspNet.Mvc.Core.Test/KnownRouteValueConstraintTests.cs
@@ -164,7 +164,7 @@ namespace Microsoft.AspNet.Routing.Tests
.Returns(actionProvider.Object);
context.Setup(o => o.RequestServices
.GetService(typeof(IActionDescriptorsCollectionProvider)))
- .Returns(new DefaultActionDescriptorsCollectionProvider(context.Object.RequestServices));
+ .Returns(new DefaultActionDescriptorsCollectionProvider(context.Object.RequestServices, new NullLoggerFactory()));
return context.Object;
}
diff --git a/test/Microsoft.AspNet.Mvc.Core.Test/Logging/PropertiesAssert.cs b/test/Microsoft.AspNet.Mvc.Core.Test/Logging/PropertiesAssert.cs
new file mode 100644
index 0000000000..851883accd
--- /dev/null
+++ b/test/Microsoft.AspNet.Mvc.Core.Test/Logging/PropertiesAssert.cs
@@ -0,0 +1,33 @@
+using System;
+using System.Linq;
+using Xunit;
+
+namespace Microsoft.AspNet.Mvc.Logging
+{
+ public static class PropertiesAssert
+ {
+ ///
+ /// Given two types, compares their properties and asserts true if they have the same property names.
+ ///
+ /// The original type to compare against.
+ /// The shadow type whose properties will be compared against the original.
+ /// Properties that exist in the original type but not the shadow.
+ /// Properties that are in the shadow type but not in the original.
+ public static void PropertiesAreTheSame(Type original, Type shadow, string[] exclude = null, string[] include = null)
+ {
+ var originalProperties = original.GetProperties().Where(p => !exclude?.Contains(p.Name) ?? true)
+ .Select(p => p.Name);
+ if (include != null)
+ {
+ originalProperties = originalProperties.Concat(include.ToList());
+ }
+ originalProperties = originalProperties.OrderBy(n => n);
+
+ // Message is a property on all ILoggerStructures
+ var shadowProperties = shadow.GetProperties().Where(p => !string.Equals("Message", p.Name))
+ .Select(p => p.Name).OrderBy(n => n);
+
+ Assert.True(originalProperties.SequenceEqual(shadowProperties));
+ }
+ }
+}
\ No newline at end of file
diff --git a/test/Microsoft.AspNet.Mvc.Core.Test/RouteConstraintAttributeValuesTest.cs b/test/Microsoft.AspNet.Mvc.Core.Test/RouteConstraintAttributeValuesTest.cs
new file mode 100644
index 0000000000..a184379dcf
--- /dev/null
+++ b/test/Microsoft.AspNet.Mvc.Core.Test/RouteConstraintAttributeValuesTest.cs
@@ -0,0 +1,23 @@
+// 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.
+
+using Xunit;
+
+namespace Microsoft.AspNet.Mvc.Logging
+{
+ public class RouteConstraintAttributeValuesTest
+ {
+ [Fact]
+ public void RouteConstraintAttributeValues_IncludesAllProperties()
+ {
+ // Arrange
+ var exclude = new[] { "TypeId" };
+
+ // Assert
+ PropertiesAssert.PropertiesAreTheSame(
+ typeof(RouteConstraintAttribute),
+ typeof(RouteConstraintAttributeValues),
+ exclude);
+ }
+ }
+}
\ No newline at end of file
diff --git a/test/Microsoft.AspNet.Mvc.Core.Test/RouteDataActionConstraintValuesTest.cs b/test/Microsoft.AspNet.Mvc.Core.Test/RouteDataActionConstraintValuesTest.cs
new file mode 100644
index 0000000000..63b6d4311d
--- /dev/null
+++ b/test/Microsoft.AspNet.Mvc.Core.Test/RouteDataActionConstraintValuesTest.cs
@@ -0,0 +1,19 @@
+// 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.
+
+using Xunit;
+
+namespace Microsoft.AspNet.Mvc.Logging
+{
+ public class RouteDataActionConstraintValuesTest
+ {
+ [Fact]
+ public void RouteDataActionConstraintValues_IncludesAllProperties()
+ {
+ // Assert
+ PropertiesAssert.PropertiesAreTheSame(
+ typeof(RouteDataActionConstraint),
+ typeof(RouteDataActionConstraintValues));
+ }
+ }
+}
\ No newline at end of file
diff --git a/test/Microsoft.AspNet.Mvc.Core.Test/StaticControllerModelBuilder.cs b/test/Microsoft.AspNet.Mvc.Core.Test/StaticControllerModelBuilder.cs
index 7b8af20b09..1ea00f6030 100644
--- a/test/Microsoft.AspNet.Mvc.Core.Test/StaticControllerModelBuilder.cs
+++ b/test/Microsoft.AspNet.Mvc.Core.Test/StaticControllerModelBuilder.cs
@@ -14,7 +14,7 @@ namespace Microsoft.AspNet.Mvc.ApplicationModels
public class StaticControllerModelBuilder : DefaultControllerModelBuilder
{
public StaticControllerModelBuilder(params TypeInfo[] controllerTypes)
- : base(new DefaultActionModelBuilder())
+ : base(new DefaultActionModelBuilder(), new NullLoggerFactory())
{
ControllerTypes = new List(controllerTypes ?? Enumerable.Empty());
}
diff --git a/test/Microsoft.AspNet.Mvc.WebApiCompatShimTest/ApiControllerActionDiscoveryTest.cs b/test/Microsoft.AspNet.Mvc.WebApiCompatShimTest/ApiControllerActionDiscoveryTest.cs
index 190d4df449..4fd2013829 100644
--- a/test/Microsoft.AspNet.Mvc.WebApiCompatShimTest/ApiControllerActionDiscoveryTest.cs
+++ b/test/Microsoft.AspNet.Mvc.WebApiCompatShimTest/ApiControllerActionDiscoveryTest.cs
@@ -12,6 +12,7 @@ using Microsoft.AspNet.Mvc.Filters;
using Microsoft.AspNet.Mvc.WebApiCompatShim;
using Microsoft.Framework.DependencyInjection;
using Microsoft.Framework.DependencyInjection.NestedProviders;
+using Microsoft.Framework.Logging;
using Microsoft.Framework.OptionsModel;
using Moq;
using Xunit;
@@ -360,7 +361,8 @@ namespace System.Web.Http
assemblyProvider.Object,
new NamespaceLimitedActionDiscoveryConventions(),
filterProvider.Object,
- optionsAccessor.Object);
+ optionsAccessor.Object,
+ new NullLoggerFactory());
return new NestedProviderManager(
new INestedProvider[]
@@ -372,7 +374,7 @@ namespace System.Web.Http
private class NamespaceLimitedActionDiscoveryConventions : DefaultControllerModelBuilder
{
public NamespaceLimitedActionDiscoveryConventions()
- : base(new DefaultActionModelBuilder())
+ : base(new DefaultActionModelBuilder(), new NullLoggerFactory())
{
}