/// <inheritdoc /> public virtual bool AppliesToAction(ODataControllerActionContext context) { if (context == null) { throw Error.ArgumentNull(nameof(context)); } if (context.EntitySet == null && context.Singleton == null) { return(false); } IEdmNavigationSource navigationSource = context.EntitySet == null ? (IEdmNavigationSource)context.Singleton : (IEdmNavigationSource)context.EntitySet; ActionModel action = context.Action; string actionName = action.ActionMethod.Name; string method = SplitActionName(actionName, out string property, out string cast, out string declared); if (method == null || string.IsNullOrEmpty(property)) { return(false); } // filter by action parameter IEdmEntityType entityType = navigationSource.EntityType(); bool hasKeyParameter = action.HasODataKeyParameter(entityType); if (!(context.Singleton != null ^ hasKeyParameter)) { // Singleton, doesn't allow to query property with key // entityset, doesn't allow for non-key to query property return(false); } // Find the declaring type of the property if we have the declaring type name in the action name. // eitherwise, it means the property is defined on the entity type of the navigation source. IEdmEntityType declaringEntityType = entityType; if (declared != null) { declaringEntityType = entityType.FindTypeInInheritance(context.Model, declared) as IEdmEntityType; if (declaringEntityType == null) { return(false); } } IEdmProperty edmProperty = declaringEntityType.FindProperty(property); if (edmProperty == null || edmProperty.PropertyKind != EdmPropertyKind.Structural) { return(false); } if (!CanApply(edmProperty, method)) { return(false); } IEdmComplexType castType = null; if (cast != null) { IEdmType propertyElementType = edmProperty.Type.Definition.AsElementType(); if (propertyElementType.TypeKind == EdmTypeKind.Complex) { IEdmComplexType complexType = (IEdmComplexType)propertyElementType; castType = complexType.FindTypeInInheritance(context.Model, cast) as IEdmComplexType; if (castType == null) { return(false); } } else { // only support complex type cast, (TODO: maybe consider to support Edm.PrimitiveType cast) return(false); } } // only process structural property IEdmStructuredType castComplexType = null; if (cast != null) { IEdmTypeReference propertyType = edmProperty.Type; if (propertyType.IsCollection()) { propertyType = propertyType.AsCollection().ElementType(); } if (!propertyType.IsComplex()) { return(false); } castComplexType = propertyType.ToStructuredType().FindTypeInInheritance(context.Model, cast); if (castComplexType == null) { return(false); } } AddSelector(method, context, action, navigationSource, (IEdmStructuralProperty)edmProperty, castComplexType, declaringEntityType, false, false); if (CanApplyDollarCount(edmProperty, method)) { AddSelector(method, context, action, navigationSource, (IEdmStructuralProperty)edmProperty, castComplexType, declaringEntityType, false, true); } if (CanApplyDollarValue(edmProperty, method)) { AddSelector(method, context, action, navigationSource, (IEdmStructuralProperty)edmProperty, castComplexType, declaringEntityType, true, false); } return(true); }
/// <inheritdoc /> public virtual bool AppliesToAction(ODataControllerActionContext context) { if (context == null) { throw Error.ArgumentNull(nameof(context)); } IEdmNavigationSource navigationSource = context.NavigationSource; if (navigationSource == null) { return(false); } ActionModel action = context.Action; string actionName = action.ActionName; string method = SplitActionName(actionName, out string property, out string cast, out string declared); if (method == null || string.IsNullOrEmpty(property)) { return(false); } // filter by action parameter IEdmEntityType entityType = navigationSource.EntityType(); bool hasKeyParameter = action.HasODataKeyParameter(entityType, context.Options?.RouteOptions?.EnablePropertyNameCaseInsensitive ?? false); if (!(context.Singleton != null ^ hasKeyParameter)) { // Singleton, doesn't allow to query property with key // entityset, doesn't allow for non-key to query property return(false); } // Find the declaring type of the property if we have the declaring type name in the action name. // otherwise, it means the property is defined on the entity type of the navigation source. IEdmEntityType declaringEntityType = entityType; if (declared != null) { if (declared.Length == 0) { // Early return for the following cases: // - Get|PostTo|PutTo|PatchTo|DeleteTo{PropertyName}From // - Get|PostTo|PutTo|PatchTo|DeleteTo{PropertyName}Of{Cast}From return(false); } declaringEntityType = entityType.FindTypeInInheritance(context.Model, declared) as IEdmEntityType; if (declaringEntityType == null) { return(false); } } bool enablePropertyNameCaseInsensitive = context?.Options?.RouteOptions.EnablePropertyNameCaseInsensitive ?? false; IEdmProperty edmProperty = declaringEntityType.FindProperty(property, enablePropertyNameCaseInsensitive); if (edmProperty == null || edmProperty.PropertyKind != EdmPropertyKind.Structural) { return(false); } if (!CanApply(edmProperty, method)) { return(false); } IEdmComplexType castType; // Only process structural property IEdmStructuredType castComplexType = null; if (cast != null) { if (cast.Length == 0) { // Avoid unnecessary call to FindTypeInheritance // Cases handled: Get|PostTo|PutTo|PatchTo|DeleteTo{PropertyName}Of return(false); } IEdmType propertyElementType = edmProperty.Type.Definition.AsElementType(); if (propertyElementType.TypeKind == EdmTypeKind.Complex) { IEdmComplexType complexType = (IEdmComplexType)propertyElementType; castType = complexType.FindTypeInInheritance(context.Model, cast) as IEdmComplexType; if (castType == null) { return(false); } } else { // only support complex type cast, (TODO: maybe consider to support Edm.PrimitiveType cast) return(false); } IEdmTypeReference propertyType = edmProperty.Type; if (propertyType.IsCollection()) { propertyType = propertyType.AsCollection().ElementType(); } if (!propertyType.IsComplex()) { return(false); } castComplexType = propertyType.ToStructuredType().FindTypeInInheritance(context.Model, cast); if (castComplexType == null) { return(false); } } AddSelector(method, context, action, navigationSource, (IEdmStructuralProperty)edmProperty, castComplexType, declaringEntityType, false, false); if (CanApplyDollarCount(edmProperty, method)) { AddSelector(method, context, action, navigationSource, (IEdmStructuralProperty)edmProperty, castComplexType, declaringEntityType, false, true); } if (CanApplyDollarValue(edmProperty, method)) { AddSelector(method, context, action, navigationSource, (IEdmStructuralProperty)edmProperty, castComplexType, declaringEntityType, true, false); } return(true); }