Logging assemblies, controllers, and actions

This commit is contained in:
SonjaKhan 2014-11-17 10:52:33 -08:00 committed by Kiran Challa
parent 04c37a8d51
commit c936ae80ca
39 changed files with 1545 additions and 66 deletions

View File

@ -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;
/// <summary>
/// Creates a new <see cref="DefaultControllerModelBuilder"/>.
/// </summary>
/// <param name="actionModelBuilder">The <see cref="IActionModelBuilder"/> used to create actions.</param>
public DefaultControllerModelBuilder(IActionModelBuilder actionModelBuilder)
public DefaultControllerModelBuilder(IActionModelBuilder actionModelBuilder, ILoggerFactory loggerFactory)
{
_actionModelBuilder = actionModelBuilder;
_logger = loggerFactory.Create<DefaultControllerModelBuilder>();
}
/// <inheritdoc />
@ -61,24 +65,42 @@ namespace Microsoft.AspNet.Mvc.ApplicationModels
/// </remarks>
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;
}
/// <summary>

View File

@ -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<IFilter> _globalFilters;
private readonly IEnumerable<IApplicationModelConvention> _modelConventions;
private readonly ILogger _logger;
public ControllerActionDescriptorProvider(IAssemblyProvider assemblyProvider,
IControllerModelBuilder applicationModelBuilder,
IGlobalFilterProvider globalFilters,
IOptions<MvcOptions> optionsAccessor)
public ControllerActionDescriptorProvider([NotNull] IAssemblyProvider assemblyProvider,
[NotNull] IControllerModelBuilder applicationModelBuilder,
[NotNull] IGlobalFilterProvider globalFilters,
[NotNull] IOptions<MvcOptions> optionsAccessor,
[NotNull] ILoggerFactory loggerFactory)
{
_assemblyProvider = assemblyProvider;
_applicationModelBuilder = applicationModelBuilder;
_globalFilters = globalFilters.Filters;
_modelConventions = optionsAccessor.Options.ApplicationModelConventions;
_logger = loggerFactory.Create<ControllerActionDescriptorProvider>();
}
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)
{

View File

@ -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;
/// <summary>
/// Initializes a new instance of the <see cref="DefaultActionDescriptorsCollectionProvider" /> class.
/// </summary>
/// <param name="serviceProvider">The application IServiceProvider.</param>
public DefaultActionDescriptorsCollectionProvider(IServiceProvider serviceProvider)
public DefaultActionDescriptorsCollectionProvider(IServiceProvider serviceProvider, ILoggerFactory factory)
{
_serviceProvider = serviceProvider;
_logger = factory.Create<DefaultActionDescriptorsCollectionProvider>();
}
/// <summary>
@ -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);
}
}

View File

@ -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
{
/// <summary>
/// Logging representation of an <see cref="IActionConstraintMetadata"/>.
/// </summary>
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();
}
/// <summary>
/// The <see cref="Type"/> of this <see cref="IActionConstraintMetadata"/>.
/// </summary>
public Type ActionConstraintMetadataType { get; }
/// <summary>
/// The constraint order if this is an <see cref="IActionConstraint"/>. See <see cref="IActionConstraint.Order"/>.
/// </summary>
public int Order { get; }
/// <summary>
/// Whether the action constraint is an <see cref="IActionConstraint"/>.
/// </summary>
public bool IsConstraint { get; }
/// <summary>
/// Whether the action constraint is an <see cref="IActionConstraintFactory"/>.
/// </summary>
public bool IsFactory { get; }
public override string Format()
{
return LogFormatter.FormatStructure(this);
}
}
}

View File

@ -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
{
/// <summary>
/// Logging representation of the state of an <see cref="ActionDescriptor"/> or
/// <see cref="ControllerActionDescriptor"/>. Logged during action discovery.
/// </summary>
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<HttpMethodConstraint>().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;
}
}
/// <summary>
/// The name of the action. See <see cref="ActionDescriptor.Name"/>.
/// </summary>
public string Name { get; }
/// <summary>
/// A friendly name for the action. See <see cref="ActionDescriptor.DisplayName"/>.
/// </summary>
public string DisplayName { get; }
/// <summary>
/// The parameters of the action as <see cref="ParameterDescriptorValues"/>.
/// See <see cref="ActionDescriptor.Parameters"/>.
/// </summary>
public List<ParameterDescriptorValues> Parameters { get; }
/// <summary>
/// The filters of the action as <see cref="FilterDescriptorValues"/>.
/// See <see cref="ActionDescriptor.FilterDescriptors"/>.
/// </summary>
public List<FilterDescriptorValues> FilterDescriptors { get; }
/// <summary>
/// The route constraints of the action as <see cref="RouteDataActionConstraintValues"/>.
/// See <see cref="ActionDescriptor.RouteConstraints"/>
/// </summary>
public List<RouteDataActionConstraintValues> RouteConstraints { get; }
/// <summary>
/// The attribute route info of the action as <see cref="AttributeRouteInfoValues"/>.
/// See <see cref="ActionDescriptor.AttributeRouteInfo"/>.
/// </summary>
public AttributeRouteInfoValues AttributeRouteInfo { get; }
/// <summary>
/// See <see cref="ActionDescriptor.RouteValueDefaults"/>.
/// </summary>
public Dictionary<string, string> RouteValueDefaults { get; }
/// <summary>
/// The action constraints of the action as <see cref="ActionConstraintValues"/>.
/// See <see cref="ActionDescriptor.ActionConstraints"/>.
/// </summary>
public List<ActionConstraintValues> ActionConstraints { get; }
/// <summary>
/// The http methods this action supports.
/// </summary>
public List<string> HttpMethods { get; }
/// <summary>
/// See <see cref="ActionDescriptor.Properties"/>.
/// </summary>
public Dictionary<string, Type> Properties { get; }
/// <summary>
/// The method info of the action if this is a <see cref="ControllerActionDescriptor"/>.
/// See <see cref="ControllerActionDescriptor.MethodInfo"/>.
/// </summary>
public MethodInfo MethodInfo { get; }
/// <summary>
/// The name of the action's controller if this is a <see cref="ControllerActionDescriptor"/>.
/// See <see cref="ControllerActionDescriptor.ControllerName"/>.
/// </summary>
public string ControllerName { get; }
/// <summary>
/// The type info of the action's controller if this is a <see cref="ControllerActionDescriptor"/>.
/// See <see cref="ControllerActionDescriptor.ControllerTypeInfo"/>.
/// </summary>
public TypeInfo ControllerTypeInfo { get; }
public override string Format()
{
return LogFormatter.FormatStructure(this);
}
}
}

View File

@ -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
{
/// <summary>
/// Represents the state of an <see cref="ActionModel"/>.
/// Logged as a substructure of <see cref="ControllerModelValues"/>
/// </summary>
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();
}
}
/// <summary>
/// The name of the action. See <see cref="ActionModel.ActionName"/>.
/// </summary>
public string ActionName { get; }
/// <summary>
/// The method info of the action. See <see cref="ActionModel.ActionMethod"/>.
/// </summary>
public MethodInfo ActionMethod { get; }
/// <summary>
/// See <see cref="ActionModel.ApiExplorer"/>.
/// </summary>
public ApiExplorerModelValues ApiExplorer { get; }
/// <summary>
/// The parameters of the action as <see cref="ParameterModelValues"/>.
/// See <see cref="ActionModel.Parameters"/>.
/// </summary>
public List<ParameterModelValues> Parameters { get; }
/// <summary>
/// The filters of the action as <see cref="FilterValues"/>.
/// See <see cref="ActionModel.Filters"/>.
/// </summary>
public List<FilterValues> Filters { get; }
/// <summary>
/// The attribute route model of the action as <see cref="AttributeRouteModelValues"/>.
/// See <see cref="ActionModel.AttributeRouteModel"/>.
/// </summary>
public AttributeRouteModelValues AttributeRouteModel { get; }
/// <summary>
/// The http methods this action supports. See <see cref="ActionModel.HttpMethods"/>.
/// </summary>
public List<string> HttpMethods { get; }
/// <summary>
/// The action constraints of the action as <see cref="ActionConstraintValues"/>.
/// See <see cref="ActionModel.ActionConstraints"/>.
/// </summary>
public List<ActionConstraintValues> ActionConstraints { get; }
public override string Format()
{
return LogFormatter.FormatStructure(this);
}
}
}

View File

@ -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
{
/// <summary>
/// Logging representation of an <see cref="ApiExplorerModel"/>.
/// </summary>
public class ApiExplorerModelValues : LoggerStructureBase
{
public ApiExplorerModelValues(ApiExplorerModel inner)
{
if (inner != null)
{
IsVisible = inner.IsVisible;
GroupName = inner.GroupName;
}
}
/// <summary>
/// See <see cref="ApiExplorerModel.IsVisible"/>.
/// </summary>
public bool? IsVisible { get; }
/// <summary>
/// See <see cref="ApiExplorerModel.GroupName"/>.
/// </summary>
public string GroupName { get; }
public override string Format()
{
return LogFormatter.FormatStructure(this);
}
}
}

View File

@ -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
{
/// <summary>
/// Logging representation of the state of an <see cref="Assembly"/>. Logged during Assembly discovery in Startup.
/// </summary>
public class AssemblyValues : LoggerStructureBase
{
public AssemblyValues([NotNull] Assembly inner)
{
AssemblyName = inner.FullName;
#if ASPNET50
Location = inner.Location;
#endif
IsDynamic = inner.IsDynamic;
}
/// <summary>
/// The name of the assembly. See <see cref="Assembly.FullName"/>.
/// </summary>
public string AssemblyName { get; }
#if ASPNET50
/// <summary>
/// The location of the assembly. See <see cref="Assembly.Location"/>.
/// </summary>
public string Location { get; }
#endif
/// <summary>
/// Whether or not the assembly is dynamic. See <see cref="Assembly.IsDynamic"/>.
/// </summary>
public bool IsDynamic { get; }
public override string Format()
{
return LogFormatter.FormatStructure(this);
}
}
}

View File

@ -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
{
/// <summary>
/// Logging representation of the state of a <see cref="AttributeRouteInfo"/>. Logged as a substructure of
/// <see cref="ActionDescriptorValues"/>.
/// </summary>
public class AttributeRouteInfoValues : LoggerStructureBase
{
public AttributeRouteInfoValues(AttributeRouteInfo inner)
{
Template = inner?.Template;
Order = inner?.Order;
Name = inner?.Name;
}
/// <summary>
/// The route template. See <see cref="AttributeRouteInfo.Template"/>.
/// </summary>
public string Template { get; }
/// <summary>
/// The order of the route. See <see cref="AttributeRouteInfo.Order"/>.
/// </summary>
public int? Order { get; }
/// <summary>
/// The name of the route. See <see cref="AttributeRouteInfo.Name"/>.
/// </summary>
public string Name { get; }
public override string Format()
{
return LogFormatter.FormatStructure(this);
}
}
}

View File

@ -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
{
/// <summary>
/// Logging representation of the state of a <see cref="AttributeRouteModel"/>. Logged as a substructure of
/// <see cref="ControllerModelValues"/>.
/// </summary>
public class AttributeRouteModelValues : LoggerStructureBase
{
public AttributeRouteModelValues(AttributeRouteModel inner)
{
if (inner != null)
{
Template = inner.Template;
Order = inner.Order;
Name = inner.Name;
IsAbsoluteTemplate = inner.IsAbsoluteTemplate;
}
}
/// <summary>
/// The template of the route. See <see cref="AttributeRouteModel.Template"/>.
/// </summary>
public string Template { get; }
/// <summary>
/// The order of the route. See <see cref="AttributeRouteModel.Order"/>.
/// </summary>
public int? Order { get; }
/// <summary>
/// The name of the route. See <see cref="AttributeRouteModel.Name"/>.
/// </summary>
public string Name { get; }
/// <summary>
/// Whether or not the template is absolute. See <see cref="AttributeRouteModel.IsAbsoluteTemplate"/>.
/// </summary>
public bool IsAbsoluteTemplate { get; }
public override string Format()
{
return LogFormatter.FormatStructure(this);
}
}
}

View File

@ -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
{
/// <summary>
/// Logging representation of the state of a <see cref="ControllerModel"/>. Logged during controller discovery.
/// </summary>
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();
}
}
/// <summary>
/// The name of the controller. See <see cref="ControllerModel.ControllerName"/>.
/// </summary>
public string ControllerName { get; }
/// <summary>
/// The <see cref="Type"/> of the controller. See <see cref="ControllerModel.ControllerType"/>.
/// </summary>
public Type ControllerType { get; }
/// <summary>
/// See <see cref="ControllerModel.ApiExplorer"/>.
/// </summary>
public ApiExplorerModelValues ApiExplorer { get; }
/// <summary>
/// The actions of the controller as <see cref="ActionModelValues"/>.
/// See <see cref="ControllerModel.Actions"/>.
/// </summary>
public List<ActionModelValues> Actions { get; }
/// <summary>
/// The <see cref="Type"/>s of the controller's attributes.
/// See <see cref="ControllerModel.Attributes"/>.
/// </summary>
public List<Type> Attributes { get; }
/// <summary>
/// The filters on the controller as <see cref="FilterValues"/>.
/// See <see cref="ControllerModel.Filters"/>.
/// </summary>
public List<FilterValues> Filters { get; }
/// <summary>
/// The action constraints on the controller as <see cref="ActionConstraintValues"/>.
/// See <see cref="ControllerModel.ActionConstraints"/>.
/// </summary>
public List<ActionConstraintValues> ActionConstraints { get; }
/// <summary>
/// The route constraints on the controller as <see cref="RouteConstraintAttributeValues"/>.
/// See <see cref="ControllerModel.RouteConstraints"/>.
/// </summary>
public List<RouteConstraintAttributeValues> RouteConstraints { get; set; }
/// <summary>
/// The attribute routes on the controller as <see cref="AttributeRouteModelValues"/>.
/// See <see cref="ControllerModel.AttributeRoutes"/>.
/// </summary>
public List<AttributeRouteModelValues> AttributeRoutes { get; set; }
public override string Format()
{
return LogFormatter.FormatStructure(this);
}
}
}

View File

@ -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
{
/// <summary>
/// Indicates the status of a class during controller discovery.
/// All values except 0 represent a reason why a type is not a controller.
/// </summary>
[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
}
}

View File

@ -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
{
/// <summary>
/// Logging representation of the state of a <see cref="FilterDescriptor"/>. Logged as a substructure of
/// <see cref="ActionDescriptorValues"/>.
/// </summary>
public class FilterDescriptorValues : LoggerStructureBase
{
public FilterDescriptorValues([NotNull] FilterDescriptor inner)
{
Filter = new FilterValues(inner.Filter);
Order = inner.Order;
Scope = inner.Scope;
}
/// <summary>
/// The <see cref="IFilter"/> instance of the filter descriptor as <see cref="FilterValues"/>.
/// See <see cref="FilterDescriptor.Filter"/>.
/// </summary>
public FilterValues Filter { get; }
/// <summary>
/// The filter order. See <see cref="FilterDescriptor.Order"/>.
/// </summary>
public int Order { get; }
/// <summary>
/// The filter scope. See <see cref="FilterDescriptor.Scope"/>.
/// </summary>
public int Scope { get; }
public override string Format()
{
return LogFormatter.FormatStructure(this);
}
}
}

View File

@ -0,0 +1,66 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Framework.Logging;
namespace Microsoft.AspNet.Mvc.Logging
{
/// <summary>
/// Logging representation of an <see cref="IFilter"/>. Logged as a component of
/// <see cref="FilterDescriptorValues"/>, and as a substructure of <see cref="ControllerModelValues"/>
/// and <see cref="ActionModelValues"/>.
/// </summary>
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();
}
}
/// <summary>
/// Whether or not the instance of <see cref="IFilter"/> is an <see cref="IFilterFactory"/>.
/// </summary>
public bool IsFactory { get; }
/// <summary>
/// The metadata type of the <see cref="IFilter"/>.
/// </summary>
public Type FilterMetadataType { get; }
/// <summary>
/// The inner <see cref="Type"/> of the <see cref="IFilter"/> if it is a <see cref="ServiceFilterAttribute"/>
/// or <see cref="TypeFilterAttribute"/>.
/// </summary>
public Type FilterType { get; }
/// <summary>
/// A list of interfaces the <see cref="IFilter"/> implements.
/// </summary>
public List<Type> FilterInterfaces { get; }
public override string Format()
{
return LogFormatter.FormatStructure(this);
}
}
}

View File

@ -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
{
/// <summary>
/// Logged to indicate the state of a class during controller discovery. Logs the type
/// of the controller as well as the <see cref="ControllerStatus"/>.
/// </summary>
public class IsControllerValues : LoggerStructureBase
{
public IsControllerValues(Type type, ControllerStatus status)
{
Type = type;
Status = status;
}
/// <summary>
/// The <see cref="System.Type"/> of the potential <see cref="Controller"/> class.
/// </summary>
public Type Type { get; }
/// <summary>
/// The <see cref="ControllerStatus"/> of the <see cref="Type"/>.
/// </summary>
public ControllerStatus Status { get; }
public override string Format()
{
return LogFormatter.FormatStructure(this);
}
}
}

View File

@ -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
{
/// <summary>
/// A formatter for use with <see cref="Microsoft.Framework.Logging.ILogger.Write(
/// Framework.Logging.LogLevel,
/// int,
/// object,
/// Exception, Func{object, Exception, string})"/>.
/// </summary>
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 "";
}
}
}

View File

@ -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
{
/// <summary>
/// Logging representation of a <see cref="ParameterDescriptor"/>. Logged as a substructure of
/// <see cref="ActionDescriptorValues"/>.
/// </summary>
public class ParameterDescriptorValues : LoggerStructureBase
{
public ParameterDescriptorValues([NotNull] ParameterDescriptor inner)
{
ParameterName = inner.Name;
ParameterType = inner.ParameterType;
BinderMetadataType = inner.BinderMetadata?.GetType();
}
/// <summary>
/// The name of the parameter. See <see cref="ParameterDescriptor.Name"/>.
/// </summary>
public string ParameterName { get; }
/// <summary>
/// The <see cref="Type"/> of the parameter. See <see cref="ParameterDescriptor.ParameterType"/>.
/// </summary>
public Type ParameterType { get; }
/// <summary>
/// The <see cref="Type"/> of the <see cref="ParameterDescriptor.BinderMetadata"/>.
/// </summary>
public Type BinderMetadataType { get; }
public override string Format()
{
return LogFormatter.FormatStructure(this);
}
}
}

View File

@ -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
{
/// <summary>
/// Logging representation of a <see cref="ParameterModel"/>. Logged as a substructure of
/// <see cref="ActionModelValues"/>, this contains the name, type, and
/// binder metadata of the parameter.
/// </summary>
public class ParameterModelValues : LoggerStructureBase
{
public ParameterModelValues([NotNull] ParameterModel inner)
{
ParameterName = inner.ParameterName;
ParameterType = inner.ParameterInfo.ParameterType;
BinderMetadata = inner.BinderMetadata?.GetType();
}
/// <summary>
/// The name of the parameter. See <see cref="ParameterModel.ParameterName"/>.
/// </summary>
public string ParameterName { get; }
/// <summary>
/// The <see cref="Type"/> of the parameter.
/// </summary>
public Type ParameterType { get; }
/// <summary>
/// The <see cref="Type"/> of the <see cref="ParameterModel.BinderMetadata"/>.
/// </summary>
public Type BinderMetadata { get; }
public override string Format()
{
return LogFormatter.FormatStructure(this);
}
}
}

View File

@ -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
{
/// <summary>
/// Logging representation of a <see cref="RouteConstraintAttribute"/>. Logged as a substructure of
/// <see cref="ControllerModelValues"/>
/// </summary>
public class RouteConstraintAttributeValues : LoggerStructureBase
{
public RouteConstraintAttributeValues([NotNull] RouteConstraintAttribute inner)
{
RouteKey = inner.RouteKey;
RouteValue = inner.RouteValue;
RouteKeyHandling = inner.RouteKeyHandling;
BlockNonAttributedActions = inner.BlockNonAttributedActions;
}
/// <summary>
/// The route value key. See <see cref="RouteConstraintAttribute.RouteKey"/>.
/// </summary>
public string RouteKey { get; }
/// <summary>
/// The expected route value. See <see cref="RouteConstraintAttribute.RouteValue"/>.
/// </summary>
public string RouteValue { get; }
/// <summary>
/// The <see cref="RouteKeyHandling"/>. See <see cref="RouteConstraintAttribute.RouteKeyHandling"/>.
/// </summary>
public RouteKeyHandling RouteKeyHandling { get; }
/// <summary>
/// See <see cref="RouteConstraintAttribute.BlockNonAttributedActions"/>.
/// </summary>
public bool BlockNonAttributedActions { get; }
public override string Format()
{
return LogFormatter.FormatStructure(this);
}
}
}

View File

@ -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
{
/// <summary>
/// Logging representation of the state of a <see cref="RouteDataActionConstraint"/>. Logged as a substructure of
/// <see cref="ActionDescriptorValues"/>.
/// </summary>
public class RouteDataActionConstraintValues : LoggerStructureBase
{
public RouteDataActionConstraintValues([NotNull] RouteDataActionConstraint inner)
{
RouteKey = inner.RouteKey;
RouteValue = inner.RouteValue;
KeyHandling = inner.KeyHandling;
}
/// <summary>
/// The route key. See <see cref="RouteDataActionConstraint.RouteKey"/>.
/// </summary>
public string RouteKey { get; }
/// <summary>
/// The route value. See <see cref="RouteDataActionConstraint.RouteValue"/>.
/// </summary>
public string RouteValue { get; }
/// <summary>
/// The <see cref="RouteKeyHandling"/>. See <see cref="RouteDataActionConstraint.KeyHandling"/>.
/// </summary>
public RouteKeyHandling KeyHandling { get; }
public override string Format()
{
return LogFormatter.FormatStructure(this);
}
}
}

View File

@ -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();
}
}
}
}

View File

@ -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);
}
}
}

View File

@ -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);
}
}
}

View File

@ -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));
}
}
}

View File

@ -166,7 +166,7 @@ namespace Microsoft.AspNet.Mvc.ApplicationModels
private class AccessibleControllerModelBuilder : DefaultControllerModelBuilder
{
public AccessibleControllerModelBuilder()
: base(new DefaultActionModelBuilder())
: base(new DefaultActionModelBuilder(), new NullLoggerFactory())
{
}

View File

@ -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);
}
}
}

View File

@ -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));
}
}
}

View File

@ -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<ActionDescriptor> 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();
}

View File

@ -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);
}
}
}

View File

@ -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<ActionDescriptorProviderContext>(new[] { actionDescriptorProvider });
var serviceContainer = new ServiceContainer();
serviceContainer.AddService(typeof(INestedProviderManager<ActionDescriptorProviderContext>),
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<IAssemblyProvider>();
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) { }
}
}
}

View File

@ -739,7 +739,7 @@ namespace Microsoft.AspNet.Mvc
serviceContainer.AddService(typeof(INestedProviderManager<ActionDescriptorProviderContext>),
descriptorProvider);
var actionCollectionDescriptorProvider = new DefaultActionDescriptorsCollectionProvider(serviceContainer);
var actionCollectionDescriptorProvider = new DefaultActionDescriptorsCollectionProvider(serviceContainer, new NullLoggerFactory());
var decisionTreeProvider = new ActionSelectorDecisionTreeProvider(actionCollectionDescriptorProvider);
var actionConstraintProvider = new NestedProviderManager<ActionConstraintProviderContext>(
@ -771,7 +771,8 @@ namespace Microsoft.AspNet.Mvc
assemblyProvider,
modelBuilder,
new TestGlobalFilterProvider(),
new MockMvcOptionsAccessor());
new MockMvcOptionsAccessor(),
new NullLoggerFactory());
}
private static HttpContext GetHttpContext(string httpMethod)

View File

@ -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));
}
}
}

View File

@ -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<Type>() { 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<Type>() { 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<Type>() { 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<Type>() { 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();
}
}
}
}

View File

@ -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;
}

View File

@ -0,0 +1,33 @@
using System;
using System.Linq;
using Xunit;
namespace Microsoft.AspNet.Mvc.Logging
{
public static class PropertiesAssert
{
/// <summary>
/// Given two types, compares their properties and asserts true if they have the same property names.
/// </summary>
/// <param name="original">The original type to compare against.</param>
/// <param name="shadow">The shadow type whose properties will be compared against the original.</param>
/// <param name="exclude">Properties that exist in the original type but not the shadow.</param>
/// <param name="include">Properties that are in the shadow type but not in the original.</param>
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));
}
}
}

View File

@ -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);
}
}
}

View File

@ -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));
}
}
}

View File

@ -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<TypeInfo>(controllerTypes ?? Enumerable.Empty<TypeInfo>());
}

View File

@ -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<ActionDescriptorProviderContext>(
new INestedProvider<ActionDescriptorProviderContext>[]
@ -372,7 +374,7 @@ namespace System.Web.Http
private class NamespaceLimitedActionDiscoveryConventions : DefaultControllerModelBuilder
{
public NamespaceLimitedActionDiscoveryConventions()
: base(new DefaultActionModelBuilder())
: base(new DefaultActionModelBuilder(), new NullLoggerFactory())
{
}