@@ -100,7 +100,13 @@ internal ODataRouteActionType GetActionType( ControllerActionDescriptor action )
100100 }
101101 else if ( Operation == null )
102102 {
103- if ( IsActionOrFunction ( EntitySet , Singleton , action . ActionName , GetHttpMethods ( action ) ) )
103+ var httpMethods = GetHttpMethods ( action ) ;
104+
105+ if ( IsCast ( EdmModel , EntitySet , action . ActionName , httpMethods ) )
106+ {
107+ return ODataRouteActionType . EntitySet ;
108+ }
109+ else if ( IsActionOrFunction ( EntitySet , Singleton , action . ActionName , httpMethods ) )
104110 {
105111 return ODataRouteActionType . Unknown ;
106112 }
@@ -122,6 +128,52 @@ internal ODataRouteActionType GetActionType( ControllerActionDescriptor action )
122128 return ODataRouteActionType . UnboundOperation ;
123129 }
124130
131+ static bool IsCast ( IEdmModel model , IEdmEntitySet ? entitySet , string actionName , IEnumerable < string > methods )
132+ {
133+ using var iterator = methods . GetEnumerator ( ) ;
134+
135+ if ( ! iterator . MoveNext ( ) )
136+ {
137+ return false ;
138+ }
139+
140+ var method = iterator . Current ;
141+
142+ if ( iterator . MoveNext ( ) )
143+ {
144+ return false ;
145+ }
146+
147+ if ( entitySet == null )
148+ {
149+ return false ;
150+ }
151+
152+ var entity = entitySet . EntityType ( ) ;
153+
154+ const string ActionMethod = "Post" ;
155+ const string FunctionMethod = "Get" ;
156+
157+ if ( ( FunctionMethod . Equals ( method , OrdinalIgnoreCase ) ||
158+ ActionMethod . Equals ( method , OrdinalIgnoreCase ) ) &&
159+ actionName != ActionMethod )
160+ {
161+ foreach ( var derivedType in model . FindAllDerivedTypes ( entity ) . OfType < EdmEntityType > ( ) )
162+ {
163+ var fromTypeName = "From" + derivedType . Name ;
164+
165+ if ( actionName . StartsWith ( method + fromTypeName , OrdinalIgnoreCase ) ||
166+ actionName . StartsWith ( method + entitySet . Name + fromTypeName , OrdinalIgnoreCase ) ||
167+ actionName . StartsWith ( method + derivedType . Name , OrdinalIgnoreCase ) )
168+ {
169+ return true ;
170+ }
171+ }
172+ }
173+
174+ return false ;
175+ }
176+
125177 // Slash became the default 4/18/2018
126178 // REF: https://github.com/OData/WebApi/pull/1393
127179 static ODataUrlKeyDelimiter UrlKeyDelimiterOrDefault ( ODataUrlKeyDelimiter ? urlKeyDelimiter ) => urlKeyDelimiter ?? Slash ;
0 commit comments