/// <inheritdoc />
        public virtual bool AppliesToController(ODataControllerActionContext context)
        {
            if (context == null)
            {
                throw Error.ArgumentNull(nameof(context));
            }

            // It allows to use attribute routing without ODataRoutePrefixAttribute.
            // In this case, we only use the ODataRouteAttrbute to construct the route template.
            // Otherwise, we combine each route prefix with each route attribute to construct the route template.
            foreach (var pathTemplatePrefix in GetODataPathTemplatePrefixes(context.Prefix, context.Controller))
            {
                foreach (var action in context.Controller.Actions)
                {
                    var routeAttributes = action.Attributes.OfType <ODataRouteAttribute>();

                    foreach (ODataRouteAttribute routeAttribute in routeAttributes)
                    {
                        // If we have the route prefix name setting, make sure we only let the attribute with the same route prefx to pass.
                        if (routeAttribute.RoutePrefix != null &&
                            !string.Equals(routeAttribute.RoutePrefix, context.Prefix, StringComparison.OrdinalIgnoreCase))
                        {
                            continue;
                        }

                        try
                        {
                            string routeTemplate = GetODataPathTemplateString(pathTemplatePrefix, routeAttribute.PathTemplate);

                            ODataPathTemplate pathTemplate = _templateParser.Parse(context.Model, routeTemplate, context.ServiceProvider);

                            // Add the httpMethod?
                            action.AddSelector(null, context.Prefix, context.Model, pathTemplate, context.RouteOptions);
                        }
                        catch (ODataException ex)
                        {
                            // use the logger to log the wrong odata attribute template. Shall we log the others?
                            string warning = string.Format(CultureInfo.CurrentCulture, SRResources.InvalidODataRouteOnAction,
                                                           routeAttribute.PathTemplate, action.ActionMethod.Name, context.Controller.ControllerName, ex.Message);

                            _logger.LogWarning(warning);
                        }
                    }
                }
            }

            // We execute this convention on all actions in the controller level.
            // So, returns false to make sure we don't want to call the AppliesToAction for this convention.
            return(false);
        }
Пример #2
0
        private SelectorModel CreateActionSelectorModel(string prefix, IEdmModel model, IServiceProvider sp,
                                                        string routeTemplate, SelectorModel actionSelectorModel,
                                                        string originalTemplate, string actionName, string controllerName)
        {
            try
            {
                // Do the uri parser, it will throw exception if the route template is not a OData path.
                ODataPathTemplate pathTemplate = _templateParser.Parse(model, routeTemplate, sp);
                if (pathTemplate != null)
                {
                    // Create a new selector model?
                    SelectorModel newSelectorModel = new SelectorModel(actionSelectorModel);
                    // Shall we remove any certain attributes/metadata?
                    ClearMetadata(newSelectorModel);

                    // Add OData routing metadata
                    ODataRoutingMetadata odataMetadata = new ODataRoutingMetadata(prefix, model, pathTemplate);
                    newSelectorModel.EndpointMetadata.Add(odataMetadata);

                    // replace the attribute routing template using absolute routing template to avoid appending any controller route template
                    newSelectorModel.AttributeRouteModel = new AttributeRouteModel()
                    {
                        Template = $"/{originalTemplate}" // add a "/" to make sure it's absolute template, don't combine with controller
                    };

                    return(newSelectorModel);
                }

                return(null);
            }
            catch (ODataException ex)
            {
                // use the logger to log the wrong odata attribute template. Shall we log the others?
                string warning = string.Format(CultureInfo.CurrentCulture, SRResources.InvalidODataRouteOnAction,
                                               originalTemplate, actionName, controllerName, ex.Message);

                // Whether we throw exception or mark it as warning is a design pattern.
                // throw new ODataException(warning);
                _logger.LogWarning(warning);
                return(null);
            }
        }