// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using Microsoft.AspNet.Mvc.ApiExplorer;
using Microsoft.AspNet.Authorization;
using Microsoft.AspNet.Cors.Core;
using Microsoft.AspNet.Mvc.Filters;
using Microsoft.AspNet.Mvc.ModelBinding;
using Microsoft.AspNet.Mvc.Routing;
using Microsoft.Framework.Internal;
using Microsoft.Framework.OptionsModel;
namespace Microsoft.AspNet.Mvc.ApplicationModels
{
///
/// A default implementation of .
///
public class DefaultControllerModelBuilder : IControllerModelBuilder
{
private readonly IActionModelBuilder _actionModelBuilder;
private readonly AuthorizationOptions _authorizationOptions;
///
/// Creates a new .
///
/// The used to create actions.
public DefaultControllerModelBuilder(
IActionModelBuilder actionModelBuilder,
IOptions authorizationOptions)
{
_actionModelBuilder = actionModelBuilder;
_authorizationOptions = authorizationOptions?.Options ?? new AuthorizationOptions();
}
///
public ControllerModel BuildControllerModel([NotNull] TypeInfo typeInfo)
{
var controllerModel = CreateControllerModel(typeInfo);
var controllerType = typeInfo.AsType();
foreach (var methodInfo in controllerType.GetMethods())
{
var actionModels = _actionModelBuilder.BuildActionModels(typeInfo, methodInfo);
if (actionModels != null)
{
foreach (var actionModel in actionModels)
{
actionModel.Controller = controllerModel;
controllerModel.Actions.Add(actionModel);
}
}
}
foreach (var propertyHelper in PropertyHelper.GetProperties(controllerType))
{
var propertyInfo = propertyHelper.Property;
var propertyModel = CreatePropertyModel(propertyInfo);
if (propertyModel != null)
{
propertyModel.Controller = controllerModel;
controllerModel.ControllerProperties.Add(propertyModel);
}
}
return controllerModel;
}
///
/// Creates an for the given .
///
/// The .
/// A for the given .
protected virtual ControllerModel CreateControllerModel([NotNull] TypeInfo typeInfo)
{
// For attribute routes on a controller, we want want to support 'overriding' routes on a derived
// class. So we need to walk up the hierarchy looking for the first class to define routes.
//
// Then we want to 'filter' the set of attributes, so that only the effective routes apply.
var currentTypeInfo = typeInfo;
var objectTypeInfo = typeof(object).GetTypeInfo();
IRouteTemplateProvider[] routeAttributes = null;
do
{
routeAttributes = currentTypeInfo
.GetCustomAttributes(inherit: false)
.OfType()
.ToArray();
if (routeAttributes.Length > 0)
{
// Found 1 or more route attributes.
break;
}
currentTypeInfo = currentTypeInfo.BaseType.GetTypeInfo();
}
while (currentTypeInfo != objectTypeInfo);
// CoreCLR returns IEnumerable from GetCustomAttributes - the OfType