public void Apply(ControllerModel controller)
        {
            var routes = routeBuilder.GetTypedRoutes();

            if (routes.ContainsKey(controller.ControllerType))
            {
                var typedRoutes = routes[controller.ControllerType];
                foreach (var route in typedRoutes)
                {
                    var selectorModel = new SelectorModel
                    {
                        AttributeRouteModel = route
                    };

                    var selectors = controller.Selectors;

                    var action = controller.Actions.FirstOrDefault(x => x.ActionMethod == route.ActionMember);
                    if (action != null)
                    {
                        foreach (var constraint in route.Constraints)
                        {
                            selectorModel.ActionConstraints.Add(constraint);
                        }

                        selectors = action.Selectors;
                    }

                    selectors.Clear();
                    selectors.Add(selectorModel);
                }
            }
        }
Esempio n. 2
0
        public SelectorModel(SelectorModel other)
        {
            if (other == null)
            {
                throw new ArgumentNullException(nameof(other));
            }

            ActionConstraints = new List<IActionConstraintMetadata>(other.ActionConstraints);

            if (other.AttributeRouteModel != null)
            {
                AttributeRouteModel = new AttributeRouteModel(other.AttributeRouteModel);
            }
        }
        private static void AddActionConstraints(
            ControllerActionDescriptor actionDescriptor,
            SelectorModel selectorModel,
            IEnumerable <IActionConstraintMetadata> controllerConstraints)
        {
            var constraints = new List <IActionConstraintMetadata>();

            if (selectorModel.ActionConstraints != null)
            {
                constraints.AddRange(selectorModel.ActionConstraints);
            }

            if (controllerConstraints != null)
            {
                constraints.AddRange(controllerConstraints);
            }

            if (constraints.Count > 0)
            {
                actionDescriptor.ActionConstraints = constraints;
            }
        }
        public void CopyConstructor_CopiesAllProperties()
        {
            // Arrange
            var controller = new ControllerModel(
                typeof(TestController).GetTypeInfo(),
                new List <object>()
            {
                new HttpGetAttribute(),
                new MyFilterAttribute(),
            });

            var selectorModel = new SelectorModel();

            selectorModel.ActionConstraints.Add(new HttpMethodActionConstraint(new string[] { "GET" }));
            controller.Selectors.Add(selectorModel);
            controller.Application    = new ApplicationModel();
            controller.ControllerName = "cool";
            controller.Filters.Add(new MyFilterAttribute());
            controller.RouteValues.Add("key", "value");
            controller.Properties.Add(new KeyValuePair <object, object>("test key", "test value"));
            controller.ControllerProperties.Add(
                new PropertyModel(typeof(TestController).GetProperty("TestProperty"), new List <object>()));

            // Act
            var controller2 = new ControllerModel(controller);

            // Assert
            foreach (var property in typeof(ControllerModel).GetProperties())
            {
                if (property.Name.Equals("Actions") ||
                    property.Name.Equals("Selectors") ||
                    property.Name.Equals("ApiExplorer") ||
                    property.Name.Equals("ControllerProperties"))
                {
                    // This test excludes other ApplicationModel objects on purpose because we deep copy them.
                    continue;
                }

                var value1 = property.GetValue(controller);
                var value2 = property.GetValue(controller2);

                if (typeof(IEnumerable <object>).IsAssignableFrom(property.PropertyType))
                {
                    Assert.Equal <object>((IEnumerable <object>)value1, (IEnumerable <object>)value2);

                    // Ensure non-default value
                    Assert.NotEmpty((IEnumerable <object>)value1);
                }
                else if (typeof(IDictionary <string, string>).IsAssignableFrom(property.PropertyType))
                {
                    Assert.Equal(value1, value2);

                    // Ensure non-default value
                    Assert.NotEmpty((IDictionary <string, string>)value1);
                }
                else if (typeof(IDictionary <object, object>).IsAssignableFrom(property.PropertyType))
                {
                    Assert.Equal(value1, value2);

                    // Ensure non-default value
                    Assert.NotEmpty((IDictionary <object, object>)value1);
                }
                else if (property.PropertyType.GetTypeInfo().IsValueType ||
                         Nullable.GetUnderlyingType(property.PropertyType) != null)
                {
                    Assert.Equal(value1, value2);

                    // Ensure non-default value
                    Assert.NotEqual(value1, Activator.CreateInstance(property.PropertyType));
                }
                else if (property.Name.Equals(nameof(ControllerModel.DisplayName)))
                {
                    // DisplayName is re-calculated, hence reference equality wouldn't work.
                    Assert.Equal(value1, value2);
                }
                else
                {
                    Assert.Same(value1, value2);

                    // Ensure non-default value
                    Assert.NotNull(value1);
                }
            }
        }
 private static bool IsEmptySelector(SelectorModel selector)
 {
     return selector.AttributeRouteModel == null && selector.ActionConstraints.IsNullOrEmpty();
 }
        private void AddAbpServiceSelector(string moduleName, string controllerName, ActionModel action, [CanBeNull] AbpServiceControllerSetting configuration)
        {
            var abpServiceSelectorModel = new SelectorModel
            {
                AttributeRouteModel = CreateAbpServiceAttributeRouteModel(moduleName, controllerName, action)
            };

            var verb = configuration?.UseConventionalHttpVerbs == true
                           ? ProxyScriptingHelper.GetConventionalVerbForMethodName(action.ActionName)
                           : ProxyScriptingHelper.DefaultHttpVerb;

            abpServiceSelectorModel.ActionConstraints.Add(new HttpMethodActionConstraint(new[] { verb }));

            action.Selectors.Add(abpServiceSelectorModel);
        }
        public static IEnumerable <SelectorModel> FlattenSelectors(ActionModel actionModel)
        {
            // Loop through all attribute routes defined on the controller.
            // These perform a cross-product with all of the action-level attribute routes.
            var controllerSelectors = actionModel.Controller.Selectors
                                      .Where(sm => sm.AttributeRouteModel != null)
                                      .ToList();

            // We also include metadata and action constraints from the controller
            // even when there are no routes, or when an action overrides the route template.
            SelectorModel?additionalSelector = null;

            if (actionModel.Controller.Selectors.Count > 0)
            {
                // This logic seems arbitrary but there's a good reason for it.
                //
                // When we build the controller level selectors, any metadata or action constraints
                // that aren't IRouteTemplateProvider will be included in all selectors. So we
                // pick any selector and then grab all of the stuff that isn't IRouteTemplateProvider
                // then we've found all of the items that aren't routes.
                //
                // This is fragile wrt application model customizing the data - but no one has
                // run into an issue with this and its pretty esoteric.
                additionalSelector = new SelectorModel(actionModel.Controller.Selectors.First());
                additionalSelector.AttributeRouteModel = null;

                for (var i = additionalSelector.ActionConstraints.Count - 1; i >= 0; i--)
                {
                    if (additionalSelector.ActionConstraints[i] is IRouteTemplateProvider)
                    {
                        additionalSelector.ActionConstraints.RemoveAt(i);
                    }
                }

                for (var i = additionalSelector.EndpointMetadata.Count - 1; i >= 0; i--)
                {
                    if (additionalSelector.EndpointMetadata[i] is IRouteTemplateProvider)
                    {
                        additionalSelector.EndpointMetadata.RemoveAt(i);
                    }
                }
            }

            var actionConstraints = new List <IActionConstraintMetadata>();

            foreach (var actionSelector in actionModel.Selectors)
            {
                var actionRouteModel = actionSelector.AttributeRouteModel;

                // We check the action to see if the template allows combination behavior
                // (It doesn't start with / or ~/) so that in the case where we have multiple
                // [Route] attributes on the controller we don't end up creating multiple
                if (actionRouteModel != null && actionRouteModel.IsAbsoluteTemplate)
                {
                    // We're overriding the routes from the controller, but any *unbound* constraints
                    // still apply.
                    var selector = new SelectorModel(actionSelector);

                    selector.AttributeRouteModel = AttributeRouteModel.CombineAttributeRouteModel(
                        left: null,
                        right: actionRouteModel);

                    AddActionConstraints(selector, additionalSelector?.ActionConstraints);
                    AddEndpointMetadata(selector, additionalSelector?.EndpointMetadata);

                    yield return(selector);
                }
                else if (controllerSelectors.Count > 0)
                {
                    for (var i = 0; i < controllerSelectors.Count; i++)
                    {
                        var controllerSelector = controllerSelectors[i];

                        // We're using the attribute routes from the controller
                        var selector = new SelectorModel(actionSelector);

                        selector.AttributeRouteModel = AttributeRouteModel.CombineAttributeRouteModel(
                            controllerSelector.AttributeRouteModel,
                            actionRouteModel);

                        AddActionConstraints(selector, controllerSelector.ActionConstraints);
                        AddEndpointMetadata(selector, controllerSelector.EndpointMetadata);

                        // No need to include the additional selector here because it would duplicate
                        // data in controllerSelector.

                        yield return(selector);
                    }
                }
                else
                {
                    // There are no routes on the controller, but any *unbound* constraints
                    // still apply.
                    var selector = new SelectorModel(actionSelector);

                    selector.AttributeRouteModel = AttributeRouteModel.CombineAttributeRouteModel(
                        left: null,
                        right: actionRouteModel);

                    AddActionConstraints(selector, additionalSelector?.ActionConstraints);
                    AddEndpointMetadata(selector, additionalSelector?.EndpointMetadata);

                    yield return(selector);
                }
            }
        }
Esempio n. 8
0
        public void CopyConstructor_CopiesAllProperties()
        {
            // Arrange
            var action = new ActionModel(
                typeof(TestController).GetMethod("Edit"),
                new List<object>()
                {
                    new HttpGetAttribute(),
                    new MyFilterAttribute(),
                });

            var selectorModel = new SelectorModel();
            selectorModel.ActionConstraints.Add(new HttpMethodActionConstraint(new string[] { "GET" }));
            action.Selectors.Add(selectorModel);
            action.ActionName = "Edit";

            action.Controller = new ControllerModel(typeof(TestController).GetTypeInfo(),
                                                    new List<object>());
            action.Filters.Add(new MyFilterAttribute());
            action.RouteConstraints.Add(new MyRouteConstraintAttribute());
            action.Properties.Add(new KeyValuePair<object, object>("test key", "test value"));

            // Act
            var action2 = new ActionModel(action);

            // Assert
            foreach (var property in typeof(ActionModel).GetProperties())
            {
                // Reflection is used to make sure the test fails when a new property is added.
                if (property.Name.Equals("ApiExplorer") ||
                    property.Name.Equals("Selectors") ||
                    property.Name.Equals("Parameters"))
                {
                    // This test excludes other ApplicationModel objects on purpose because we deep copy them.
                    continue;
                }

                var value1 = property.GetValue(action);
                var value2 = property.GetValue(action2);

                if (typeof(IEnumerable<object>).IsAssignableFrom(property.PropertyType))
                {
                    Assert.Equal<object>((IEnumerable<object>)value1, (IEnumerable<object>)value2);

                    // Ensure non-default value
                    Assert.NotEmpty((IEnumerable<object>)value1);
                }
                else if (typeof(IDictionary<object, object>).IsAssignableFrom(property.PropertyType))
                {
                    Assert.Equal(value1, value2);

                    // Ensure non-default value
                    Assert.NotEmpty((IDictionary<object, object>)value1);
                }
                else if (property.PropertyType.GetTypeInfo().IsValueType ||
                    Nullable.GetUnderlyingType(property.PropertyType) != null)
                {
                    Assert.Equal(value1, value2);

                    // Ensure non-default value
                    Assert.NotEqual(value1, Activator.CreateInstance(property.PropertyType));
                }
                else
                {
                    Assert.Same(value1, value2);

                    // Ensure non-default value
                    Assert.NotNull(value1);
                }
            }
        }
Esempio n. 9
0
        public void CopyConstructor_CopiesAllProperties()
        {
            // Arrange
            var action = new ActionModel(
                typeof(TestController).GetMethod("Edit"),
                new List <object>()
            {
                new HttpGetAttribute(),
                new MyFilterAttribute(),
            });

            var selectorModel = new SelectorModel();

            selectorModel.ActionConstraints.Add(new HttpMethodActionConstraint(new string[] { "GET" }));
            action.Selectors.Add(selectorModel);
            action.ActionName = "Edit";

            action.Controller = new ControllerModel(typeof(TestController).GetTypeInfo(),
                                                    new List <object>());
            action.Filters.Add(new MyFilterAttribute());
            action.RouteConstraints.Add(new MyRouteConstraintAttribute());
            action.Properties.Add(new KeyValuePair <object, object>("test key", "test value"));

            // Act
            var action2 = new ActionModel(action);

            // Assert
            foreach (var property in typeof(ActionModel).GetProperties())
            {
                // Reflection is used to make sure the test fails when a new property is added.
                if (property.Name.Equals("ApiExplorer") ||
                    property.Name.Equals("Selectors") ||
                    property.Name.Equals("Parameters"))
                {
                    // This test excludes other ApplicationModel objects on purpose because we deep copy them.
                    continue;
                }

                var value1 = property.GetValue(action);
                var value2 = property.GetValue(action2);

                if (typeof(IEnumerable <object>).IsAssignableFrom(property.PropertyType))
                {
                    Assert.Equal <object>((IEnumerable <object>)value1, (IEnumerable <object>)value2);

                    // Ensure non-default value
                    Assert.NotEmpty((IEnumerable <object>)value1);
                }
                else if (typeof(IDictionary <object, object>).IsAssignableFrom(property.PropertyType))
                {
                    Assert.Equal(value1, value2);

                    // Ensure non-default value
                    Assert.NotEmpty((IDictionary <object, object>)value1);
                }
                else if (property.PropertyType.GetTypeInfo().IsValueType ||
                         Nullable.GetUnderlyingType(property.PropertyType) != null)
                {
                    Assert.Equal(value1, value2);

                    // Ensure non-default value
                    Assert.NotEqual(value1, Activator.CreateInstance(property.PropertyType));
                }
                else
                {
                    Assert.Same(value1, value2);

                    // Ensure non-default value
                    Assert.NotNull(value1);
                }
            }
        }
 private static void AddAttributeRoute(ControllerActionDescriptor actionDescriptor, SelectorModel selectorModel)
 {
     if (selectorModel.AttributeRouteModel != null)
     {
         actionDescriptor.AttributeRouteInfo = new AttributeRouteInfo
         {
             Template = selectorModel.AttributeRouteModel.Template,
             Order    = selectorModel.AttributeRouteModel.Order ?? 0,
             Name     = selectorModel.AttributeRouteModel.Name,
             SuppressLinkGeneration = selectorModel.AttributeRouteModel.SuppressLinkGeneration,
             SuppressPathMatching   = selectorModel.AttributeRouteModel.SuppressPathMatching,
         };
     }
 }
 private static void AddEndpointMetadata(ControllerActionDescriptor actionDescriptor, SelectorModel selectorModel)
 {
     if (selectorModel.EndpointMetadata?.Count > 0)
     {
         actionDescriptor.EndpointMetadata = new List <object>(selectorModel.EndpointMetadata);
     }
 }
 private static void AddActionConstraints(ControllerActionDescriptor actionDescriptor, SelectorModel selectorModel)
 {
     if (selectorModel.ActionConstraints?.Count > 0)
     {
         actionDescriptor.ActionConstraints = new List <IActionConstraintMetadata>(selectorModel.ActionConstraints);
     }
 }