@@ -182,7 +182,13 @@ internal ODataRouteActionType GetActionType( HttpActionDescriptor action )
182182 }
183183 else if ( Operation == null )
184184 {
185- if ( IsActionOrFunction ( EntitySet , Singleton , action . ActionName , GetHttpMethods ( action ) ) )
185+ var httpMethods = GetHttpMethods ( action ) ;
186+
187+ if ( IsCast ( EdmModel , EntitySet , action . ActionName , httpMethods ) )
188+ {
189+ return ODataRouteActionType . EntitySet ;
190+ }
191+ else if ( IsActionOrFunction ( EntitySet , Singleton , action . ActionName , httpMethods ) )
186192 {
187193 return ODataRouteActionType . Unknown ;
188194 }
@@ -204,6 +210,52 @@ internal ODataRouteActionType GetActionType( HttpActionDescriptor action )
204210 return ODataRouteActionType . UnboundOperation ;
205211 }
206212
213+ private static bool IsCast ( IEdmModel model , IEdmEntitySet ? entitySet , string actionName , IEnumerable < string > methods )
214+ {
215+ using var iterator = methods . GetEnumerator ( ) ;
216+
217+ if ( ! iterator . MoveNext ( ) )
218+ {
219+ return false ;
220+ }
221+
222+ var method = iterator . Current ;
223+
224+ if ( iterator . MoveNext ( ) )
225+ {
226+ return false ;
227+ }
228+
229+ if ( entitySet == null )
230+ {
231+ return false ;
232+ }
233+
234+ var entity = entitySet . EntityType ( ) ;
235+
236+ const string ActionMethod = "Post" ;
237+ const string FunctionMethod = "Get" ;
238+
239+ if ( ( FunctionMethod . Equals ( method , OrdinalIgnoreCase ) ||
240+ ActionMethod . Equals ( method , OrdinalIgnoreCase ) ) &&
241+ actionName != ActionMethod )
242+ {
243+ foreach ( var derivedType in model . FindAllDerivedTypes ( entity ) . OfType < EdmEntityType > ( ) )
244+ {
245+ var fromTypeName = "From" + derivedType . Name ;
246+
247+ if ( actionName . StartsWith ( method + fromTypeName , OrdinalIgnoreCase ) ||
248+ actionName . StartsWith ( method + entitySet . Name + fromTypeName , OrdinalIgnoreCase ) ||
249+ actionName . StartsWith ( method + derivedType . Name , OrdinalIgnoreCase ) )
250+ {
251+ return true ;
252+ }
253+ }
254+ }
255+
256+ return false ;
257+ }
258+
207259 // Slash became the default 4/18/2018
208260 // REF: https://github.com/OData/WebApi/pull/1393
209261 private static ODataUrlKeyDelimiter UrlKeyDelimiterOrDefault ( ODataUrlKeyDelimiter ? urlKeyDelimiter ) => urlKeyDelimiter ?? Slash ;
0 commit comments