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