Пример #1
0
        /// <inheritdoc />
        public void Apply(ActionModel action)
        {
            var attribute = action.Attributes.OfType <WebHookAttribute>().FirstOrDefault();

            if (attribute == null)
            {
                // Not a WebHook handler.
                return;
            }

            var template  = ChooseTemplate(action.RouteValues);
            var selectors = action.Selectors;

            if (selectors.Count == 0)
            {
                var selector = new SelectorModel();
                selectors.Add(selector);

                AddTemplate(attribute, template, selector);
            }
            else
            {
                for (var i = 0; i < selectors.Count; i++)
                {
                    var selector = selectors[i];
                    AddTemplate(attribute, template, selector);
                }
            }

            AddConstraints(attribute, selectors);
            AddConstraints(action.Properties, selectors);

            if (action.Properties.TryGetValue(typeof(IWebHookBodyTypeMetadata), out var bodyTypeMetadata))
            {
                action.Filters.Add(new WebHookVerifyBodyTypeFilter(
                                       (IWebHookBodyTypeMetadata)bodyTypeMetadata,
                                       _loggerFactory));
            }
        }
Пример #2
0
        public void AppliesToActionForPostActionWorksAsExpected(string actionName, string expected)
        {
            // Arrange
            ControllerModel controller = ControllerModelHelpers.BuildControllerModel <CustomersController>(actionName);
            ActionModel     action     = controller.Actions.First();

            ODataControllerActionContext context = ODataControllerActionContextHelpers.BuildContext(string.Empty, EdmModel, controller);

            context.Action = controller.Actions.First();

            EntitySetRoutingConvention entitySetConvention = ConventionHelpers.CreateConvention <EntitySetRoutingConvention>();

            // Act
            bool returnValue = entitySetConvention.AppliesToAction(context);

            Assert.True(returnValue);

            // Assert
            SelectorModel selector = Assert.Single(action.Selectors);

            Assert.Equal(expected, selector.AttributeRouteModel.Template);
        }
Пример #3
0
        // this method refers to the similar method in ASP.NET Core
        internal static SelectorModel CreateSelectorModel(IReadOnlyList <object> attributes)
        {
            var selectorModel = new SelectorModel();

            AddRange(selectorModel.ActionConstraints, attributes.OfType <IActionConstraintMetadata>());
            AddRange(selectorModel.EndpointMetadata, attributes);

            // Simple case, all HTTP method attributes apply
            var httpMethods = attributes
                              .OfType <IActionHttpMethodProvider>()
                              .SelectMany(a => a.HttpMethods)
                              .Distinct(StringComparer.OrdinalIgnoreCase)
                              .ToArray();

            if (httpMethods.Length > 0)
            {
                selectorModel.ActionConstraints.Add(new HttpMethodActionConstraint(httpMethods));
                selectorModel.EndpointMetadata.Add(new HttpMethodMetadata(httpMethods));
            }

            return(selectorModel);
        }
Пример #4
0
        public void AppliesToActionForEntityActionWithDerivedEntityTypeWorksAsExpected(string actionName)
        {
            // Arrange
            ControllerModel controller = ControllerModelHelpers.BuildControllerModel <CustomersController>(actionName);
            ActionModel     action     = controller.Actions.First();

            ODataControllerActionContext context = ODataControllerActionContextHelpers.BuildContext(string.Empty, EdmModel, controller);

            context.Action = action;

            EntityRoutingConvention entityConvention = ConventionHelpers.CreateConvention <EntityRoutingConvention>();

            // Act
            bool returnValue = entityConvention.AppliesToAction(context);

            Assert.True(returnValue);

            // Assert
            SelectorModel selector = Assert.Single(action.Selectors);

            Assert.Equal("Customers(FirstName={keyFirstName},LastName={keyLastName})/NS.VipCustomer", selector.AttributeRouteModel.Template);
        }
        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;
            }
        }
Пример #6
0
        public void AppliesToActionDoesNothingForNotSupportedAction(string actionName)
        {
            // Arrange
            ControllerModel controller = ControllerModelHelpers.BuildControllerModel <AnotherCustomersController>(actionName);
            ActionModel     action     = controller.Actions.First();

            ODataControllerActionContext context = ODataControllerActionContextHelpers.BuildContext(string.Empty, EdmModel, controller);

            context.Action = controller.Actions.First();

            EntityRoutingConvention entityConvention = ConventionHelpers.CreateConvention <EntityRoutingConvention>();

            // Act
            bool returnValue = entityConvention.AppliesToAction(context);

            Assert.False(returnValue);

            // Assert
            SelectorModel selector = Assert.Single(action.Selectors);

            Assert.Null(selector.AttributeRouteModel);
        }
Пример #7
0
        protected virtual void TranslateActionRoute(ActionModel localizedActionModel, SelectorModel originalSelectorModel,
                                                    string template, string culture)
        {
            Logger.LogDebug(
                $"Add translated selector for action {localizedActionModel.Controller.ControllerName}:{localizedActionModel.ActionName} with \"{template}\" ({culture}).");

            localizedActionModel.ThrowIfNotLocalizedModel(RouteTranslationConfiguration.Localizer);

            if (RouteTranslationConfiguration.ValidateUrl)
            {
                ValidateUrl(originalSelectorModel.AttributeRouteModel.Template, template);
            }

            // Don't add RoutePrefix twice
            if (RouteTranslationConfiguration.AddCultureAsRoutePrefix && !localizedActionModel.Controller
                .GetOriginalModel(RouteTranslationConfiguration.Localizer)
                .HasAttributeRoutes())
            {
                template = RouteTranslationConfiguration.Localizer.ApplyRouteCulturePrefix(template, culture);
            }

            SelectorModel localizedSelectorModel = new SelectorModel(originalSelectorModel)
            {
                AttributeRouteModel =
                {
                    Template = template,
                },
            };

            localizedActionModel.Selectors.Add(localizedSelectorModel);

            RouteTranslationConfiguration.OnActionRouteTranslated(this, new OnActionRouteTranslatedEventArgs()
            {
                OriginalActionModel    = localizedActionModel.GetOriginalModel(RouteTranslationConfiguration.Localizer),
                LocalizedActionModel   = localizedActionModel,
                OriginalSelectorModel  = originalSelectorModel,
                LocalizedSelectorModel = localizedSelectorModel,
            });
        }
Пример #8
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="action"></param>
        /// <param name="prefix"></param>
        /// <param name="model"></param>
        /// <param name="template"></param>
        public static void AddSelector(this ActionModel action, string prefix, IEdmModel model, ODataPathTemplate template)
        {
            if (action == null)
            {
                throw new ArgumentNullException(nameof(action));
            }

            if (prefix == null)
            {
                throw new ArgumentNullException(nameof(prefix));
            }

            if (model == null)
            {
                throw new ArgumentNullException(nameof(model));
            }

            if (template == null)
            {
                throw new ArgumentNullException(nameof(template));
            }

            SelectorModel selectorModel = action.Selectors.FirstOrDefault(s => s.AttributeRouteModel == null);

            if (selectorModel == null)
            {
                selectorModel = new SelectorModel();
                action.Selectors.Add(selectorModel);
            }

            string templateStr = string.IsNullOrEmpty(prefix) ? template.Template : $"{prefix}/{template.Template}";

            selectorModel.AttributeRouteModel = new AttributeRouteModel(new RouteAttribute(templateStr)
            {
                Name = templateStr
            });
            selectorModel.EndpointMetadata.Add(new ODataEndpointMetadata(prefix, model, template));
        }
        public void AppliesToActionForSingletonDoesnotWorksAsExpected()
        {
            // Arrange
            ControllerModel controller = ControllerModelHelpers.BuildControllerModel <SingletonTestControllerWithPrefix>("GetVipCustomerAliasWithPrefix");
            ActionModel     action     = controller.Actions.First();

            ODataControllerActionContext context = new ODataControllerActionContext(string.Empty, _edmModel, controller);

            context.Action  = action;
            context.Options = _options;

            // Act
            bool ok = _attributeConvention.AppliesToAction(context);

            Assert.False(ok);

            // Assert
            SelectorModel selector = Assert.Single(action.Selectors);

            Assert.NotNull(selector.AttributeRouteModel);
            Assert.Equal("Alias", selector.AttributeRouteModel.Template);
            Assert.DoesNotContain(selector.EndpointMetadata, a => a is ODataRoutingMetadata);
        }
Пример #10
0
        public string Search(string regName, string key, string ds, int?pageSize, int?pageIndex)
        {
            var pagination = new Pagination();

            pagination.PageSize  = pageSize ?? 28;
            pagination.PageIndex = pageIndex ?? 0;
            SetPostDataSet(ds);
            key = key ?? "";
            var dt = GetCodeTableInstance(regName);

            pagination.AppendToDataSet(PostDataSet, regName);
            var res = dt.Search(PostDataSet, key);
            //pagination.TotalCount = res.Count();
            SelectorModel model = new SelectorModel();

            model.List  = res.ToList();
            model.Index = pagination.PageIndex;
            model.Size  = pagination.PageSize;
            model.Total = PostDataSet.Tables[regName + "_PAGER"].Rows[0]["TotalCount"].Value <int>();

            //res = res.Skip((pagination.PageIndex - 1) * pagination.PageSize).Take(pagination.PageSize).ToList();
            return(ReturnJson(model == null ? new SelectorModel() : model));
        }
        public void AppliesToAction_Works_ForPatchActionWorksAsExpected(Type controllerType, string actionName, string expected, bool ignoreCase)
        {
            // Arrange
            ControllerModel controller = ControllerModelHelpers.BuildControllerModel(controllerType, actionName);
            ActionModel     action     = controller.Actions.First();

            ODataControllerActionContext context = ODataControllerActionContextHelpers.BuildContext(string.Empty, EdmModel, controller);

            context.Action = controller.Actions.First();
            context.Options.RouteOptions.EnableActionNameCaseInsensitive = ignoreCase;

            EntitySetRoutingConvention entitySetConvention = ConventionHelpers.CreateConvention <EntitySetRoutingConvention>();

            // Act
            bool returnValue = entitySetConvention.AppliesToAction(context);

            Assert.True(returnValue);

            // Assert
            SelectorModel selector = Assert.Single(action.Selectors);

            Assert.Equal(expected, selector.AttributeRouteModel.Template);
        }
        public void Apply(ControllerModel controller)
        {
            if (!options.Controllers.TryGetValue(controller.ControllerType, out var metadata))
            {
                return;
            }

            var model = new SelectorModel
            {
                AttributeRouteModel = metadata.Template == null
                                        ? null
                                        : new AttributeRouteModel(
                    new RouteAttribute(metadata.Template)
                {
                    Name = metadata.ActionName
                })
            };

            foreach (var constraint in metadata.ActionConstraints)
            {
                model.ActionConstraints.Add(constraint(provider));
            }

            foreach (var filter in metadata.Filters)
            {
                controller.Filters.Add(filter(provider));
            }

            var conventions = controller.Selectors.Where(s => s.AttributeRouteModel == null).ToList();

            foreach (var convention in conventions)
            {
                controller.Selectors.Remove(convention);
            }

            controller.Selectors.Insert(0, model);
        }
Пример #13
0
        private void AddVersion(ApplicationModel application, string version, IReadOnlyDictionary <string, TypeInfo> controllers, Dictionary <string, ControllerModel> versionedModels)
        {
            foreach (KeyValuePair <string, TypeInfo> controller in controllers)
            {
                string controllerTypeName = controller.Value.AssemblyQualifiedName;
                var    controllerModel    = new ControllerModel(versionedModels[controllerTypeName])
                {
                    ControllerName = $"{controller.Key}/{version}",
                    RouteValues    =
                    {
                        ["version"] = version,
                    },
                };
                if (controllerModel.Selectors.Count > 1)
                {
                    throw new InvalidOperationException("Versioned Controllers cannot have more than one route.");
                }

                RemoveApiRemovedActions(controllerModel);

                SelectorModel selector = controllerModel.Selectors.Count == 1
                    ? controllerModel.Selectors[0]
                    : GetDefaultControllerSelector(controller);
                if (selector.AttributeRouteModel.IsAbsoluteTemplate)
                {
                    throw new InvalidOperationException(
                              "versioned api controllers are not allowed to have absolute routes.");
                }

                controllerModel.Selectors.Clear();
                Options.VersioningScheme.Apply(selector, version);
                controllerModel.Selectors.Add(selector);

                application.Controllers.Add(controllerModel);
                controllerModel.Application = application;
            }
        }
        public void Apply(ControllerModel controller)
        {
            var newSelectors = new List <SelectorModel>();

            //Controller has Attribute Route
            var matchedSelectors = controller.Selectors.Where(x => x.AttributeRouteModel != null).ToList();

            if (matchedSelectors.Any())
            {
                foreach (var selectorModel in matchedSelectors)
                {
                    var routeModel = AttributeRouteModel.CombineAttributeRouteModel(_culturePrefix, selectorModel.AttributeRouteModel);

                    if (_optional)
                    {
                        var newSelector = new SelectorModel();
                        newSelector.AttributeRouteModel       = routeModel;
                        newSelector.AttributeRouteModel.Order = -1;
                        newSelectors.Add(newSelector);
                    }
                    else
                    {
                        selectorModel.AttributeRouteModel = routeModel;
                    }
                }
            }

            foreach (var action in controller.Actions)
            {
                Apply(action);
            }

            foreach (var newSelector in newSelectors)
            {
                controller.Selectors.Insert(0, newSelector);
            }
        }
Пример #15
0
        public void Apply(PageRouteModel model)
        {
            var path          = model.ViewEnginePath;
            var lastSeparator = path.LastIndexOf('/');

            Debug.Assert(lastSeparator != -1);
            var lastDot = path.LastIndexOf('.', path.Length - 1, path.Length - lastSeparator);

            // /SomeFolder/MyPage.fr-FR -> fr-FR
            if (lastDot != -1)
            {
                var cultureName = path.Substring(lastDot + 1);
                var constraint  = new CultureConstraint(new CultureInfo(cultureName));
                for (var i = model.Selectors.Count - 1; i >= 0; i--)
                {
                    var selector = model.Selectors[i];

                    selector.ActionConstraints.Add(constraint);
                    var template = selector.AttributeRouteModel.Template;
                    template = template.Substring(0, lastDot - 1);

                    selector.AttributeRouteModel.Template = template;
                    var fileName = template.Substring(lastSeparator);

                    if (fileName == "Index")
                    {
                        selector.AttributeRouteModel.SuppressLinkGeneration = true;

                        var indexSelector = new SelectorModel(selector);

                        template = selector.AttributeRouteModel.Template.Substring(0, lastSeparator);
                        indexSelector.AttributeRouteModel.Template = template;
                        model.Selectors.Add(indexSelector);
                    }
                }
            }
        }
        public void AppliesToActionForSingletonWorksAsExpected(string actionName, string expectedTemplate)
        {
            // Arrange
            ControllerModel controller = ControllerModelHelpers.BuildControllerModel <SingletonTestControllerWithPrefix>(actionName);
            ActionModel     action     = controller.Actions.First();

            ODataControllerActionContext context = new ODataControllerActionContext(string.Empty, _edmModel, controller);

            context.Action  = action;
            context.Options = _options;
            AttributeRoutingConvention attributeConvention = CreateConvention();

            // Act
            bool ok = _attributeConvention.AppliesToAction(context);

            Assert.False(ok);

            // Assert
            SelectorModel selector = Assert.Single(action.Selectors);

            Assert.NotNull(selector.AttributeRouteModel);
            Assert.Equal(expectedTemplate, selector.AttributeRouteModel.Template);
            Assert.Contains(selector.EndpointMetadata, a => a is ODataRoutingMetadata);
        }
        private void Apply(ActionModel action)
        {
            var attribute = action.Attributes.OfType <WebHookAttribute>().FirstOrDefault();

            if (attribute == null)
            {
                // Not a WebHook handler.
                return;
            }

            var template  = ChooseTemplate();
            var selectors = action.Selectors;

            if (selectors.Count == 0)
            {
                var selector = new SelectorModel();
                selectors.Add(selector);

                AddTemplate(attribute, template, selector);
            }
            else
            {
                for (var i = 0; i < selectors.Count; i++)
                {
                    var selector = selectors[i];
                    AddTemplate(attribute, template, selector);
                }
            }

            var properties = action.Properties;

            AddEventMapperConstraint(properties, selectors);
            AddEventNamesConstraint(properties, selectors);
            AddIdConstraint(attribute, selectors);
            AddReceiverExistsConstraint(properties, selectors);
        }
Пример #18
0
        public static SelectorModel CreateSelectorModel(IRouteTemplateProvider route, IList <object> attributes)
        {
            var selectorModel = new SelectorModel();

            if (route != null)
            {
                selectorModel.AttributeRouteModel = new AttributeRouteModel(route);
            }

            AddRange(selectorModel.ActionConstraints, attributes.OfType <IActionConstraintMetadata>());

            var httpMethods = attributes
                              .OfType <IActionHttpMethodProvider>()
                              .SelectMany(a => a.HttpMethods)
                              .Distinct(StringComparer.OrdinalIgnoreCase)
                              .ToArray();

            if (httpMethods.Length > 0)
            {
                selectorModel.ActionConstraints.Add(new HttpMethodActionConstraint(httpMethods));
            }

            return(selectorModel);
        }
Пример #19
0
 public static HudSelector FromModel(SelectorModel model, TextStyle textStyle) => model == null ? null : new HudSelector(model, textStyle);
Пример #20
0
 private HudSelector(SelectorModel model, TextStyle textStyle) : this(model.Label, model.Tooltip, textStyle, model.Color, model.OnClick, model.OnHover)
 {
 }
 private static bool IsEmptySelector(SelectorModel selector)
 {
     return(selector.AttributeRouteModel == null && selector.ActionConstraints.IsNullOrEmpty());
 }
Пример #22
0
        public void Apply(ApplicationModel application)
        {
            var controller =
                application.Controllers.FirstOrDefault(
                    x => x.ControllerType == typeof(CompositeResourceController).GetTypeInfo());

            // composites/v{compositeVersion}/{school year if year specific}/{organizationCode}/{compositeCategoryName (regex constraint}/{compositeName}/{id?}
            // the composite category is constrained by a regex expression
            // the id is optional
            // the attribute on the controller is composites
            if (controller != null)
            {
                var defaultRouteSuffix = new AttributeRouteModel {
                    Template = CreateRouteTemplate() + "{compositeName}/{id?}"
                };

                // the composite controller has only one selector and if more are added this should break

                var selector = controller.Selectors.SingleOrDefault();

                if (selector.AttributeRouteModel != null)
                {
                    // composites have children routes that need to be added to the controller.
                    var routeMetadataGroupedByCompositeCategory = _compositesMetadataProvider.GetAllRoutes();

                    foreach (var routeGrouping in routeMetadataGroupedByCompositeCategory)
                    {
                        foreach (var routeElt in routeGrouping.Value)
                        {
                            string relativeRouteTemplate = routeElt.AttributeValue("relativeRouteTemplate")
                                                           .TrimStart('/');

                            var routeSuffix = new AttributeRouteModel {
                                Template = CreateRouteTemplate() + relativeRouteTemplate
                            };

                            var childSelector = new SelectorModel
                            {
                                AttributeRouteModel = AttributeRouteModel.CombineAttributeRouteModel(
                                    selector.AttributeRouteModel,
                                    routeSuffix)
                            };

                            controller.Selectors.Add(childSelector);
                        }
                    }

                    // set the base selector with the correct route
                    selector.AttributeRouteModel = AttributeRouteModel.CombineAttributeRouteModel(
                        selector.AttributeRouteModel,
                        defaultRouteSuffix);
                }
            }

            string CreateRouteTemplate()
            {
                string template = $"v{ApiVersionConstants.Composite}/";

                if (_apiSettings.GetApiMode() == ApiMode.YearSpecific)
                {
                    template += RouteConstants.SchoolYearFromRoute;
                }

                if (_apiSettings.GetApiMode() == ApiMode.InstanceYearSpecific)
                {
                    template += RouteConstants.InstanceIdFromRoute;
                    template += RouteConstants.SchoolYearFromRoute;
                }

                var compositeCategoryNames = _compositesMetadataProvider
                                             .GetAllCategories()
                                             .Select(x => x.Name)
                                             .ToList <string>();

                string allCompositeCategoriesConstraintExpression = $@"^(?i)({string.Join("|", compositeCategoryNames)})$";

                string categoryName = "{organizationCode}/{compositeCategory}/";

                template += categoryName;

                return(template);
            }
        }
Пример #23
0
        public void Apply(SelectorModel model, string version)
        {
            AttributeRouteModel attributeRouteModel = model.AttributeRouteModel;

            attributeRouteModel.Template = $"api/{version}/{attributeRouteModel.Template}";
        }
Пример #24
0
        public void Apply(ActionModel action)
        {
            var attributeRoutes = action.Selectors.Where(x => x.AttributeRouteModel != null).ToList();
            var newSelectors    = new List <SelectorModel>();
            //check if it's within an area
            var areaAttribute = action.Controller.Attributes.FirstOrDefault(x => x.GetType() == typeof(AreaAttribute));
            var area          = "";

            if (areaAttribute != null)
            {
                area = "/" + ((AreaAttribute)areaAttribute).RouteValue;
            }
            foreach (var ar in attributeRoutes)
            {
                if (!action.Properties.ContainsKey("RouteName"))
                {
                    action.Properties.Add("RouteName", ar.AttributeRouteModel.Name);
                }
                if (ar.AttributeRouteModel.Attribute is IDualRouteAttribute)
                {
                    var dualRouteAttribute = (IDualRouteAttribute)ar.AttributeRouteModel.Attribute;
                    if (dualRouteAttribute.OnlyApi)
                    {
                        var currentTemplate = ar.AttributeRouteModel.Template;
                        if (currentTemplate.StartsWith("~/"))
                        {
                            ar.AttributeRouteModel.Template =
                                area + "/" + ApplicationConfig.ApiEndpointName + "/" + currentTemplate.Replace("~/", "");
                        }
                        else
                        {
                            ar.AttributeRouteModel.Template =
                                area + "/" + ApplicationConfig.ApiEndpointName + "/[controller]/" + currentTemplate;
                        }
                        ar.AttributeRouteModel.Name = $"{ApplicationConfig.ApiEndpointName}_" +
                                                      ar.AttributeRouteModel.Name;
                        continue; //skip adding anything else
                    }
                    //add another route for api
                    var selectorModel = new SelectorModel(ar);
                    var newAm         = selectorModel.AttributeRouteModel;
                    if (newAm.Template.StartsWith("~/"))
                    {
                        newAm.Template = area + "/" + ApplicationConfig.ApiEndpointName + "/" + newAm.Template.Replace("~/", "");
                    }
                    else
                    {
                        newAm.Template = area + "/" + ApplicationConfig.ApiEndpointName + "/[controller]/" + newAm.Template;
                    }
                    if (newAm.Name != null)
                    {
                        newAm.Name = $"{ApplicationConfig.ApiEndpointName}_" + newAm.Name;
                    }

                    newSelectors.Add(selectorModel);
                }
                else if (ar.AttributeRouteModel.Attribute is DynamicRouteAttribute)
                {
#if DEBUGWS
                    continue;
#endif
                    var dynamicRoute = (DynamicRouteAttribute)ar.AttributeRouteModel.Attribute;
                    var template     = dynamicRoute.DynamicTemplate;
                    if (template.IsNullEmptyOrWhiteSpace())
                    {
                        var settingService = DependencyResolver.Resolve <ISettingService>();
                        var settingName    = dynamicRoute.SettingName;
                        var setting        =
                            settingService.FirstOrDefault(x => x.GroupName == nameof(UrlSettings) && x.Key == settingName);
                        if (setting == null)
                        {
                            continue;
                        }
                        template = dynamicRoute.TemplatePrefix + setting.Value + dynamicRoute.TemplateSuffix;
                    }

                    var dynamicRouteProvider = DependencyResolver.Resolve <IDynamicRouteProvider>();
                    dynamicRouteProvider.RegisterDynamicRoute(new RouteData()
                    {
                        Template       = template,
                        ActionName     = action.ActionName,
                        ControllerName = action.Controller.ControllerName,
                        RouteName      = dynamicRoute.Name,
                        Order          = dynamicRoute.Order,
                        SeoEntityName  = dynamicRoute.SeoEntityName,
                        ParameterName  = dynamicRoute.ParameterName
                    });
                }
            }

            foreach (var ns in newSelectors)
            {
                action.Selectors.Add(ns);
            }
        }
Пример #25
0
    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);
            }
        }
    }
Пример #26
0
 protected virtual bool IsEmptySelector(SelectorModel selector)
 {
     return(selector.AttributeRouteModel == null && selector.ActionConstraints.IsNullOrEmpty());
 }
        public void Apply(ActionModel action)
        {
            var newSelectors = new List <SelectorModel>();

            //Action has Attribute Route
            var matchedSelectors = action.Selectors.Where(x => x.AttributeRouteModel != null).ToList();

            if (matchedSelectors.Any())
            {
                foreach (var selectorModel in matchedSelectors)
                {
                    //https://andrewlock.net/applying-the-routedatarequest-cultureprovider-globally-with-middleware-as-filters/
                    if (selectorModel.AttributeRouteModel.Template != null && selectorModel.AttributeRouteModel.Template.StartsWith("~/"))
                    {
                        var path       = selectorModel.AttributeRouteModel.Template.Length > 2 ? $"/{selectorModel.AttributeRouteModel.Template.Substring(2)}" : "";
                        var routeModel = new AttributeRouteModel(new RouteAttribute($"~/{_culturePrefix.Template}{path}"));

                        if (_optional)
                        {
                            var newSelector = new SelectorModel();
                            newSelector.AttributeRouteModel       = routeModel;
                            newSelector.AttributeRouteModel.Order = -1;
                            newSelectors.Add(newSelector);
                        }
                        else
                        {
                            selectorModel.AttributeRouteModel = routeModel;
                        }
                    }
                    //https://andrewlock.net/applying-the-routedatarequest-cultureprovider-globally-with-middleware-as-filters/
                    else if (selectorModel.AttributeRouteModel.Template != null && selectorModel.AttributeRouteModel.Template.StartsWith("/"))
                    {
                        var path       = selectorModel.AttributeRouteModel.Template.Length > 1 ? $"/{selectorModel.AttributeRouteModel.Template.Substring(1)}" : "";
                        var routeModel = new AttributeRouteModel(new RouteAttribute($"/{_culturePrefix.Template}{path}"));

                        if (_optional)
                        {
                            var newSelector = new SelectorModel();
                            newSelector.AttributeRouteModel       = routeModel;
                            newSelector.AttributeRouteModel.Order = -1;
                            newSelectors.Add(newSelector);
                        }
                        else
                        {
                            selectorModel.AttributeRouteModel = routeModel;
                        }
                    }
                    //Controller doesn't have Attribute Route
                    else if (action.Controller.Selectors.Where(x => x.AttributeRouteModel == null).ToList().Any())
                    {
                        var routeModel = AttributeRouteModel.CombineAttributeRouteModel(_culturePrefix, selectorModel.AttributeRouteModel);

                        if (_optional)
                        {
                            var newSelector = new SelectorModel();
                            newSelector.AttributeRouteModel       = routeModel;
                            newSelector.AttributeRouteModel.Order = -1;
                            newSelectors.Add(newSelector);
                        }
                        else
                        {
                            selectorModel.AttributeRouteModel = routeModel;
                        }
                    }
                }
            }

            foreach (var newSelector in newSelectors)
            {
                action.Selectors.Insert(0, newSelector);
            }
        }
Пример #28
0
 private void AddRoutePrefixToExistingRoute(SelectorModel selector)
 {
     selector.AttributeRouteModel = AttributeRouteModel.CombineAttributeRouteModel(_routePrefix, selector.AttributeRouteModel);
 }
        /// <summary>
        ///
        /// </summary>
        /// <param name="application"></param>
        public void Apply(ApplicationModel application)
        {
            var controllerRegister = Env.Instance.ApplicationServices.GetService <IServiceRegister>();

            if (controllerRegister == null)
            {
                return;
            }
            var controllers = controllerRegister.GetAll();

            foreach (var controller in controllers)
            {
                var controllName = controller.Name;
                if (controllName.EndsWith("Controller"))
                {
                    controllName = controllName.Substring(0, controllName.Length - "Controller".Length);
                }
                var controllAttrs = controller.GetCustomAttributes().ToList();
                var routeAttr     = (RouteAttribute)controllAttrs.Find(x => typeof(RouteAttribute).IsAssignableFrom(x.GetType()));
                var model         = new ControllerModel(controller.GetTypeInfo(), controllAttrs);
                model.ControllerName = controllName;
                //model.ControllerName = controllName;
                string template = $"{controllName}";
                if (routeAttr != null)
                {
                    template = routeAttr.Template;
                }
                model.Selectors.Add(new SelectorModel()
                {
                    AttributeRouteModel = new AttributeRouteModel()
                    {
                        Template = template
                    }
                });

                var methods = controller.GetMethods(BindingFlags.Public | BindingFlags.DeclaredOnly | BindingFlags.Instance);
                foreach (var method in methods)
                {
                    var    methodAttrs    = method.GetCustomAttributes().ToList();
                    var    httpAttr       = (HttpMethodAttribute)methodAttrs.Find(x => typeof(HttpMethodAttribute).IsAssignableFrom(x.GetType()));
                    string actionTemplate = method.Name;
                    if (httpAttr != null && !string.IsNullOrWhiteSpace(httpAttr.Template))
                    {
                        actionTemplate = httpAttr.Template;
                    }
                    //methodAttrs.Add(new SwaggerOperationAttribute(method.Name));
                    var actionModel = new ActionModel(method, methodAttrs);
                    actionModel.ActionName = method.Name;
                    actionModel.Controller = model;
                    //actionModel.Selectors.Add(new SelectorModel());
                    var selectModel = new SelectorModel()
                    {
                        AttributeRouteModel = new AttributeRouteModel()
                        {
                            Template = actionTemplate
                        }
                    };
                    if (httpAttr != null)
                    {
                        selectModel.ActionConstraints.Add(new HttpMethodActionConstraint(httpAttr.HttpMethods)
                        {
                        });
                    }
                    actionModel.Selectors.Add(selectModel);
                    var paras = method.GetParameters();
                    foreach (var p in paras)
                    {
                        var            paraAttrs = p.GetCustomAttributes().ToList();
                        ParameterModel pm        = new ParameterModel(p, paraAttrs);
                        pm.Action        = actionModel;
                        pm.ParameterName = p.Name;

                        var fromBodyAttr     = p.GetCustomAttribute <FromBodyAttribute>();
                        var fromFormAttr     = p.GetCustomAttribute <FromFormAttribute>();
                        var fromQueryAttr    = p.GetCustomAttribute <FromQueryAttribute>();
                        var fromHeaderAttr   = p.GetCustomAttribute <FromHeaderAttribute>();
                        var fromRouteAttr    = p.GetCustomAttribute <FromRouteAttribute>();
                        var fromServicesAttr = p.GetCustomAttribute <FromServicesAttribute>();
                        if (fromBodyAttr != null)
                        {
                            pm.BindingInfo = new Microsoft.AspNetCore.Mvc.ModelBinding.BindingInfo();
                            pm.BindingInfo.BindingSource = new Microsoft.AspNetCore.Mvc.ModelBinding.BindingSource("Body", "Body", true, true);
                        }
                        else if (fromFormAttr != null)
                        {
                            pm.BindingInfo = new Microsoft.AspNetCore.Mvc.ModelBinding.BindingInfo();
                            pm.BindingInfo.BindingSource = new Microsoft.AspNetCore.Mvc.ModelBinding.BindingSource("Form", "Form", true, true);
                        }
                        else if (fromQueryAttr != null)
                        {
                            pm.BindingInfo = new Microsoft.AspNetCore.Mvc.ModelBinding.BindingInfo();
                            pm.BindingInfo.BindingSource = new Microsoft.AspNetCore.Mvc.ModelBinding.BindingSource("Query", "Query", true, true);
                        }
                        else if (fromHeaderAttr != null)
                        {
                            pm.BindingInfo = new Microsoft.AspNetCore.Mvc.ModelBinding.BindingInfo();
                            pm.BindingInfo.BindingSource = new Microsoft.AspNetCore.Mvc.ModelBinding.BindingSource("Header", "Header", true, true);
                        }
                        else if (fromRouteAttr != null)
                        {
                            pm.BindingInfo = new Microsoft.AspNetCore.Mvc.ModelBinding.BindingInfo();
                            pm.BindingInfo.BindingSource = new Microsoft.AspNetCore.Mvc.ModelBinding.BindingSource("Route", "Route", true, true);
                        }
                        else if (fromServicesAttr != null)
                        {
                            pm.BindingInfo = new Microsoft.AspNetCore.Mvc.ModelBinding.BindingInfo();
                            pm.BindingInfo.BindingSource = new Microsoft.AspNetCore.Mvc.ModelBinding.BindingSource("Services", "Services", true, true);
                        }
                        actionModel.Parameters.Add(pm);
                    }

                    model.Actions.Add(actionModel);
                }
                application.Controllers.Add(model);
            }
        }
Пример #30
0
        /// <summary>
        /// Adds the OData selector model to the action.
        /// </summary>
        /// <param name="action">The given action model.</param>
        /// <param name="httpMethods">The supported http methods, if multiple, using ',' to separate.</param>
        /// <param name="prefix">The prefix.</param>
        /// <param name="model">The Edm model.</param>
        /// <param name="path">The OData path template.</param>
        /// <param name="options">The route build options.</param>
        public static void AddSelector(this ActionModel action, string httpMethods, string prefix, IEdmModel model, ODataPathTemplate path, ODataRouteOptions options = null)
        {
            if (action == null)
            {
                throw Error.ArgumentNull(nameof(action));
            }

            if (string.IsNullOrEmpty(httpMethods))
            {
                throw Error.ArgumentNullOrEmpty(nameof(httpMethods));
            }

            if (model == null)
            {
                throw Error.ArgumentNull(nameof(model));
            }

            if (path == null)
            {
                throw Error.ArgumentNull(nameof(path));
            }

            // if the controller has attribute route decorated, for example:
            // [Route("api/[controller]")]
            // public class CustomersController : Controller
            // {}
            // let's always create new selector model for action.
            // Since the new created selector model is absolute attribute route, the controller attribute route doesn't apply to this selector model.
            bool hasAttributeRouteOnController = action.Controller.Selectors.Any(s => s.AttributeRouteModel != null);

            // If the methods have different case sensitive, for example, "get", "Get", in the ASP.NET Core 3.1,
            // It will throw "An item with the same key has already been added. Key: GET", in
            // HttpMethodMatcherPolicy.BuildJumpTable(Int32 exitDestination, IReadOnlyList`1 edges)
            // Another root cause is that in attribute routing, we reuse the HttpMethodMetadata, the method name is always "upper" case.
            // Therefore, we upper the http method name always.
            string[] methods = httpMethods.ToUpperInvariant().Split(',');
            foreach (string template in path.GetTemplates(options))
            {
                // Be noted: https://github.com/dotnet/aspnetcore/blob/main/src/Mvc/Mvc.Core/src/ApplicationModels/ActionAttributeRouteModel.cs#L74-L75
                // No matter whether the action selector model is absolute route template, the controller's attribute will apply automatically
                // So, let's only create/update the action selector model
                SelectorModel selectorModel = action.Selectors.FirstOrDefault(s => s.AttributeRouteModel == null);
                if (hasAttributeRouteOnController || selectorModel == null)
                {
                    // Create a new selector model.
                    selectorModel = CreateSelectorModel(action, methods);
                    action.Selectors.Add(selectorModel);
                }
                else
                {
                    // Update the existing non attribute routing selector model.
                    selectorModel = UpdateSelectorModel(selectorModel, methods);
                }

                ODataRoutingMetadata odataMetadata = new ODataRoutingMetadata(prefix, model, path);
                selectorModel.EndpointMetadata.Add(odataMetadata);

                string templateStr = string.IsNullOrEmpty(prefix) ? template : $"{prefix}/{template}";

                selectorModel.AttributeRouteModel = new AttributeRouteModel
                {
                    // OData convention route template doesn't get combined with the route template applied to the controller.
                    // Route templates applied to an action that begin with / or ~/ don't get combined with route templates applied to the controller.
                    Template = $"/{templateStr}",
                    Name     = templateStr // do we need this?
                };

                // Check with .NET Team whether the "Endpoint name metadata" needed?
                selectorModel.EndpointMetadata.Add(new EndpointNameMetadata(Guid.NewGuid().ToString())); // Do we need this?
            }
        }