public override string SelectAction(System.Web.Http.OData.Routing.ODataPath odataPath, System.Web.Http.Controllers.HttpControllerContext controllerContext, ILookup <string, System.Web.Http.Controllers.HttpActionDescriptor> actionMap)
        {
            if (odataPath == null)
            {
                throw new ArgumentNullException("odataPath");
            }

            if (controllerContext == null)
            {
                throw new ArgumentNullException("controllerContext");
            }

            if (actionMap == null)
            {
                throw new ArgumentNullException("actionMap");
            }

            HttpMethod requestMethod = controllerContext.Request.Method;

            if (odataPath.PathTemplate == "~/entityset/key/$links/navigation" && requestMethod == HttpMethod.Get)
            {
                KeyValuePathSegment keyValueSegment = odataPath.Segments[1] as KeyValuePathSegment;
                controllerContext.RouteData.Values[ODataRouteConstants.Key] = keyValueSegment.Value;
                NavigationPathSegment  navigationSegment  = odataPath.Segments[3] as NavigationPathSegment;
                IEdmNavigationProperty navigationProperty = navigationSegment.NavigationProperty;
                IEdmEntityType         declaredType       = navigationProperty.DeclaringType as IEdmEntityType;

                string action = requestMethod + "LinksFor" + navigationProperty.Name + "From" + declaredType.Name;
                return(actionMap.Contains(action) ? action : requestMethod + "LinksFor" + navigationProperty.Name);
            }
            return(base.SelectAction(odataPath, controllerContext, actionMap));
        }
Example #2
0
        private static void ValidateCount(ODataPathSegment segment, IEdmModel model)
        {
            Contract.Assert(segment != null);
            Contract.Assert(model != null);

            NavigationPathSegment navigationPathSegment = segment as NavigationPathSegment;

            if (navigationPathSegment != null)
            {
                if (EdmLibHelpers.IsNotCountable(navigationPathSegment.NavigationProperty, model))
                {
                    throw new InvalidOperationException(Error.Format(
                                                            SRResources.NotCountablePropertyUsedForCount,
                                                            navigationPathSegment.NavigationPropertyName));
                }
                return;
            }

            PropertyAccessPathSegment propertyAccessPathSegment = segment as PropertyAccessPathSegment;

            if (propertyAccessPathSegment != null)
            {
                if (EdmLibHelpers.IsNotCountable(propertyAccessPathSegment.Property, model))
                {
                    throw new InvalidOperationException(Error.Format(
                                                            SRResources.NotCountablePropertyUsedForCount,
                                                            propertyAccessPathSegment.PropertyName));
                }
            }
        }
Example #3
0
        public override string SelectAction(ODataPath odataPath, HttpControllerContext context,
                                            ILookup <string, HttpActionDescriptor> actionMap)
        {
            if (context.Request.Method == HttpMethod.Get &&
                odataPath.PathTemplate == "~/entityset/key/navigation/key")
            {
                NavigationPathSegment  navigationSegment  = odataPath.Segments[2] as NavigationPathSegment;
                IEdmNavigationProperty navigationProperty = navigationSegment.NavigationProperty.Partner;
                IEdmEntityType         declaringType      = navigationProperty.DeclaringType as IEdmEntityType;

                string actionName = "Get" + declaringType.Name;
                if (actionMap.Contains(actionName))
                {
                    // Add keys to route data, so they will bind to action parameters.
                    KeyValuePathSegment keyValueSegment = odataPath.Segments[1] as KeyValuePathSegment;
                    context.RouteData.Values[ODataRouteConstants.Key] = keyValueSegment.Value;

                    KeyValuePathSegment relatedKeySegment = odataPath.Segments[3] as KeyValuePathSegment;
                    context.RouteData.Values[ODataRouteConstants.RelatedKey] = relatedKeySegment.Value;

                    return(actionName);
                }
            }
            // Not a match.
            return(null);
        }
    public override string SelectAction(ODataPath odataPath, HttpControllerContext controllerContext, ILookup <string, HttpActionDescriptor> actionMap)
    {
        if (controllerContext.Request.Method != HttpMethod.Get || odataPath.PathTemplate != "~/entityset/key/navigation")
        {
            return(null);
        }
        NavigationPathSegment  navigationSegment  = odataPath.Segments.Last() as NavigationPathSegment;
        IEdmNavigationProperty navigationProperty = navigationSegment.NavigationProperty;
        IEdmEntityType         declaringType      = navigationProperty.DeclaringType as IEdmEntityType;

        if (declaringType == null)
        {
            return(null);
        }
        string actionName = navigationProperty.TargetMultiplicity() == EdmMultiplicity.Many
                                ? "GetRelatedEntityCollection" : "GetRelatedSingleEntity";

        if (!actionMap.Contains(actionName))
        {
            return(null);
        }
        KeyValuePathSegment keyValueSegment = odataPath.Segments[1] as KeyValuePathSegment;

        controllerContext.RouteData.Values[ODataRouteConstants.Key] = keyValueSegment.Value;
        // Add information about the specific navigation property. If you need
        // more than just the name, add additional items to RouteData.Values.
        controllerContext.RouteData.Values["navigationProperty"] = navigationProperty.Name;
        return(actionName);
    }
Example #5
0
        public override string SelectAction(ODataPath odataPath, HttpControllerContext controllerContext, ILookup <string, HttpActionDescriptor> actionMap)
        {
            HttpMethod httpMethod = controllerContext.Request.Method;

            if (httpMethod != HttpMethod.Get)
            {
                return(null);
            }

            if (odataPath.PathTemplate == "~/entityset/key/navigation/key")
            {
                KeyValuePathSegment segment = (KeyValuePathSegment)odataPath.Segments[1];
                object value = ODataUriUtils.ConvertFromUriLiteral(segment.Value, ODataVersion.V4);
                controllerContext.RouteData.Values.Add("key", value);

                segment = (KeyValuePathSegment)odataPath.Segments[3];
                value   = ODataUriUtils.ConvertFromUriLiteral(segment.Value, ODataVersion.V4);
                controllerContext.RouteData.Values.Add("relatedKey", value);

                NavigationPathSegment property = odataPath.Segments[2] as NavigationPathSegment;
                // controllerContext.RouteData.Values.Add("propertyName", property.NavigationProperty.Name);

                return("Get" + property.NavigationProperty.Name);
            }

            return(null);
        }
        private static HttpStatusCode?GetChangedStatusCodeForNavigationProperty(NavigationPathSegment navigation)
        {
            EdmMultiplicity multiplicity = navigation.NavigationProperty.TargetMultiplicity();

            return(multiplicity == EdmMultiplicity.ZeroOrOne || multiplicity == EdmMultiplicity.One ?
                   HttpStatusCode.NoContent :
                   (HttpStatusCode?)null);
        }
        private static void AddLinkInfoToRouteData(IHttpRouteData routeData, ODataPath odataPath)
        {
            KeyValuePathSegment keyValueSegment = odataPath.Segments[1] as KeyValuePathSegment;

            routeData.Values[ODataRouteConstants.Key] = keyValueSegment.Value;
            NavigationPathSegment navigationSegment = odataPath.Segments[3] as NavigationPathSegment;

            routeData.Values[ODataRouteConstants.NavigationProperty] = navigationSegment.NavigationProperty.Name;
        }
        private IQueryable DrillIntoNavigationProperty(IQueryable queryable, NavigationPathSegment navigationPath)
        {
            // make sure we found the key and entity
            if (navigationPath == null)
            {
                throw new WebAPIDataServiceException("Missing navigation key");
            }

            return ProjectionInto(queryable, navigationPath.NavigationPropertyName);
        }
        /// <summary>
        /// Selects the action.
        /// </summary>
        /// <param name="odataPath">The odata path.</param>
        /// <param name="controllerContext">The controller context.</param>
        /// <param name="actionMap">The action map.</param>
        /// <returns></returns>
        public override string SelectAction(ODataPath odataPath, HttpControllerContext controllerContext, ILookup <string, HttpActionDescriptor> actionMap)
        {
            if (odataPath == null)
            {
                throw Error.ArgumentNull("odataPath");
            }

            if (controllerContext == null)
            {
                throw Error.ArgumentNull("controllerContext");
            }

            if (actionMap == null)
            {
                throw Error.ArgumentNull("actionMap");
            }

            HttpMethod     requestMethod = controllerContext.Request.Method;
            IHttpRouteData routeData     = controllerContext.RouteData;

            if (odataPath.PathTemplate == "~/entityset/key/$links/navigation" ||
                odataPath.PathTemplate == "~/entityset/key/cast/$links/navigation")
            {
                NavigationPathSegment  navigationSegment  = odataPath.Segments.Last() as NavigationPathSegment;
                IEdmNavigationProperty navigationProperty = navigationSegment.NavigationProperty;
                IEdmEntityType         declaringType      = navigationProperty.DeclaringType as IEdmEntityType;

                string linksActionName = FindLinksActionName(actionMap, navigationProperty, declaringType, requestMethod);
                if (linksActionName != null)
                {
                    routeData.Values[ODataRouteConstants.Key] = (odataPath.Segments[1] as KeyValuePathSegment).Value;
                    routeData.Values[ODataRouteConstants.NavigationProperty] = navigationSegment.NavigationProperty.Name;
                    return(linksActionName);
                }
            }
            else if ((odataPath.PathTemplate == "~/entityset/key/$links/navigation/key" ||
                      odataPath.PathTemplate == "~/entityset/key/cast/$links/navigation/key") && requestMethod == HttpMethod.Delete)
            {
                NavigationPathSegment  navigationSegment  = odataPath.Segments[odataPath.Segments.Count - 2] as NavigationPathSegment;
                IEdmNavigationProperty navigationProperty = navigationSegment.NavigationProperty;
                IEdmEntityType         declaringType      = navigationProperty.DeclaringType as IEdmEntityType;

                string linksActionName = FindLinksActionName(actionMap, navigationProperty, declaringType, requestMethod);
                if (linksActionName != null)
                {
                    routeData.Values[ODataRouteConstants.Key] = (odataPath.Segments[1] as KeyValuePathSegment).Value;
                    routeData.Values[ODataRouteConstants.NavigationProperty] = navigationSegment.NavigationProperty.Name;
                    routeData.Values[ODataRouteConstants.RelatedKey]         = (odataPath.Segments.Last() as KeyValuePathSegment).Value;
                    return(linksActionName);
                }
            }

            return(null);
        }
Example #10
0
        /// <inheritdoc/>
        public override string SelectAction(ODataPath odataPath, HttpControllerContext controllerContext, ILookup <string, HttpActionDescriptor> actionMap)
        {
            if (odataPath == null)
            {
                throw Error.ArgumentNull("odataPath");
            }

            if (controllerContext == null)
            {
                throw Error.ArgumentNull("controllerContext");
            }

            if (actionMap == null)
            {
                throw Error.ArgumentNull("actionMap");
            }

            HttpMethod     requestMethod = controllerContext.Request.Method;
            IHttpRouteData routeData     = controllerContext.RouteData;

            if (odataPath.PathTemplate == EntitysetKeyNavigationRef ||
                odataPath.PathTemplate == EntitysetKeyCastNavigationRef)
            {
                NavigationPathSegment  navigationSegment  = (NavigationPathSegment)odataPath.Segments[odataPath.Segments.Count - 2];
                IEdmNavigationProperty navigationProperty = navigationSegment.NavigationProperty;
                IEdmEntityType         declaringType      = navigationProperty.DeclaringEntityType();

                string refActionName = FindRefActionName(actionMap, navigationProperty, declaringType, requestMethod);
                if (refActionName != null)
                {
                    routeData.Values[ODataRouteConstants.Key] = ((KeyValuePathSegment)odataPath.Segments[1]).Value;
                    routeData.Values[ODataRouteConstants.NavigationProperty] = navigationSegment.NavigationProperty.Name;
                    return(refActionName);
                }
            }
            else if ((odataPath.PathTemplate == EntitysetKeyNavigationKeyRef ||
                      odataPath.PathTemplate == EntitysetKeyCastNavigationKeyRef) && requestMethod == HttpMethod.Delete)
            {
                NavigationPathSegment  navigationSegment  = (NavigationPathSegment)odataPath.Segments[odataPath.Segments.Count - 3];
                IEdmNavigationProperty navigationProperty = navigationSegment.NavigationProperty;
                IEdmEntityType         declaringType      = navigationProperty.DeclaringEntityType();

                string refActionName = FindRefActionName(actionMap, navigationProperty, declaringType, requestMethod);
                if (refActionName != null)
                {
                    routeData.Values[ODataRouteConstants.Key] = ((KeyValuePathSegment)odataPath.Segments[1]).Value;
                    routeData.Values[ODataRouteConstants.NavigationProperty] = navigationSegment.NavigationProperty.Name;
                    routeData.Values[ODataRouteConstants.RelatedKey]         = ((KeyValuePathSegment)odataPath.Segments[odataPath.Segments.Count - 2]).Value;
                    return(refActionName);
                }
            }

            return(null);
        }
        private static IEdmNavigationProperty GetNavigationProperty(ODataPath path)
        {
            if (path == null)
            {
                throw new ArgumentNullException("path");
            }
            NavigationPathSegment navigationSegment = (NavigationPathSegment)path.Segments.FirstOrDefault(
                s => s is NavigationPathSegment);

            if (navigationSegment == null)
            {
                return(null);
            }
            return(navigationSegment.NavigationProperty);
        }
Example #12
0
        /// <summary>
        /// Selects the action.
        /// </summary>
        /// <param name="odataPath">The OData path.</param>
        /// <param name="controllerContext">The controller context.</param>
        /// <param name="actionMap">The action map.</param>
        /// <returns></returns>
        public override string SelectAction(ODataPath odataPath, HttpControllerContext controllerContext, ILookup <string, HttpActionDescriptor> actionMap)
        {
            if (odataPath == null)
            {
                throw Error.ArgumentNull("odataPath");
            }

            if (controllerContext == null)
            {
                throw Error.ArgumentNull("controllerContext");
            }

            if (actionMap == null)
            {
                throw Error.ArgumentNull("actionMap");
            }

            HttpMethod method = controllerContext.Request.Method;

            if ((method == HttpMethod.Get || method == HttpMethod.Post) &&
                (odataPath.PathTemplate == "~/entityset/key/navigation" ||
                 odataPath.PathTemplate == "~/entityset/key/cast/navigation"))
            {
                NavigationPathSegment  navigationSegment  = odataPath.Segments.Last() as NavigationPathSegment;
                IEdmNavigationProperty navigationProperty = navigationSegment.NavigationProperty;
                IEdmEntityType         declaringType      = navigationProperty.DeclaringType as IEdmEntityType;

                if (declaringType != null)
                {
                    string actionNamePrefix = (method == HttpMethod.Get) ? "Get" : "PostTo";

                    // e.g. Try GetNavigationPropertyFromDeclaringType first, then fallback on GetNavigationProperty action name
                    string actionName = actionMap.FindMatchingAction(
                        actionNamePrefix + navigationProperty.Name + "From" + declaringType.Name,
                        actionNamePrefix + navigationProperty.Name);

                    if (actionName != null)
                    {
                        KeyValuePathSegment keyValueSegment = odataPath.Segments[1] as KeyValuePathSegment;
                        controllerContext.RouteData.Values[ODataRouteConstants.Key] = keyValueSegment.Value;
                        return(actionName);
                    }
                }
            }

            return(null);
        }
Example #13
0
        public override string SelectAction(ODataPath odataPath, HttpControllerContext controllerContext, ILookup <string, HttpActionDescriptor> actionMap)
        {
            //if (controllerContext.Request.Method == System.Net.Http.HttpMethod.Put) controllerContext.Request.Content.ReadAsStreamAsync().ContinueWith((t) => A(t.Result));

            if (odataPath == null)
            {
                throw new ArgumentNullException("odataPath");
            }

            if (controllerContext == null)
            {
                throw new ArgumentNullException("controllerContext");
            }

            if (actionMap == null)
            {
                throw new ArgumentNullException("actionMap");
            }

            string prefix = GetHttpPrefix(controllerContext.Request.Method.ToString());

            if (string.IsNullOrEmpty(prefix))
            {
                return(null);
            }

            //~/entityset/key/$links/navigation
            if ((odataPath.PathTemplate == "~/entityset/key/navigation") ||
                (odataPath.PathTemplate == "~/entityset/key/cast/navigation") ||
                (odataPath.PathTemplate == "~/entityset/key/$links/navigation"))
            {
                NavigationPathSegment  segment            = odataPath.Segments.Last() as NavigationPathSegment;
                IEdmNavigationProperty navigationProperty = segment.NavigationProperty;
                IEdmEntityType         declaringType      = navigationProperty.DeclaringType as IEdmEntityType;

                if (declaringType != null)
                {
                    KeyValuePathSegment keySegment = odataPath.Segments[1] as KeyValuePathSegment;
                    controllerContext.RouteData.Values[ODataRouteConstants.Key] = keySegment.Value;
                    string actionName = prefix + navigationProperty.Name + "From" + declaringType.Name;
                    return(actionMap.Contains(actionName) ? actionName : (prefix + navigationProperty.Name));
                }
            }

            return(null);
        }
Example #14
0
        // Retrieves the IEdmEntityType from the path only in the case that we are addressing a single entity.
        // We iterate the path backwards and we return as soon as we realize we are referencing a single entity.
        // That is, as soon as we find a singleton segment, a key segment or a navigation segment with target
        // multiplicity 0..1 or 1.
        internal static IEdmEntityType GetSingleEntityEntityType(ODataPath path)
        {
            if (path == null || path.Segments.Count == 0)
            {
                return(null);
            }

            int currentSegmentIndex = path.Segments.Count - 1;

            // Skip a possible sequence of casts at the end of the path.
            while (currentSegmentIndex >= 0 &&
                   path.Segments[currentSegmentIndex].SegmentKind == ODataSegmentKinds._Cast)
            {
                currentSegmentIndex--;
            }
            if (currentSegmentIndex < 0)
            {
                return(null);
            }

            ODataPathSegment currentSegment = path.Segments[currentSegmentIndex];

            switch (currentSegment.SegmentKind)
            {
            case ODataSegmentKinds._Singleton:
            case ODataSegmentKinds._Key:
                return((IEdmEntityType)path.EdmType);

            case ODataSegmentKinds._Navigation:
                NavigationPathSegment navigation = (NavigationPathSegment)currentSegment;
                if (navigation.NavigationProperty.TargetMultiplicity() == EdmMultiplicity.ZeroOrOne ||
                    navigation.NavigationProperty.TargetMultiplicity() == EdmMultiplicity.One)
                {
                    return((IEdmEntityType)path.EdmType);
                }
                break;

            default:
                break;
            }
            return(null);
        }
Example #15
0
        private static void CheckNavigableProperty(ODataPath path, IEdmModel model)
        {
            Contract.Assert(path != null);
            Contract.Assert(model != null);

            foreach (ODataPathSegment segment in path.Segments)
            {
                NavigationPathSegment navigationPathSegment = segment as NavigationPathSegment;

                if (navigationPathSegment != null)
                {
                    if (EdmLibHelpers.IsNotNavigable(navigationPathSegment.NavigationProperty, model))
                    {
                        throw new ODataException(Error.Format(
                                                     SRResources.NotNavigablePropertyUsedInNavigation,
                                                     navigationPathSegment.NavigationProperty.Name));
                    }
                }
            }
        }
        public string SelectAction(
            ODataPath odataPath,
            HttpControllerContext controllerContext,
            ILookup <string, HttpActionDescriptor> actionMap)
        {
            if (odataPath.PathTemplate == "~/entityset/key/navigation")
            {
                if (controllerContext.Request.Method == HttpMethod.Get)
                {
                    NavigationPathSegment navigationPathSegment = (NavigationPathSegment)odataPath.Segments.Last();

                    controllerContext.RouteData.Values["navigation"] = navigationPathSegment.NavigationProperty.Name;

                    KeyValuePathSegment keyValueSegment = (KeyValuePathSegment)odataPath.Segments[1];
                    controllerContext.RouteData.Values[ODataRouteConstants.Key] = keyValueSegment.Value;

                    return("GetNavigation");
                }
            }

            return(null);
        }
Example #17
0
 public override string SelectAction(ODataPath odataPath, HttpControllerContext controllerContext, ILookup <string, HttpActionDescriptor> actionMap)
 {
     if ((odataPath.PathTemplate == "~/entityset/key/navigation") || (odataPath.PathTemplate == "~/entityset/key/cast/navigation"))
     {
         NavigationPathSegment  segment            = odataPath.Segments.Last <ODataPathSegment>() as NavigationPathSegment;
         IEdmNavigationProperty navigationProperty = segment.NavigationProperty;
         IEdmEntityType         declaringType      = navigationProperty.DeclaringType as IEdmEntityType;
         if (declaringType != null)
         {
             string prefix = ODataHelper.GetHttpPrefix(controllerContext.Request.Method.ToString());
             if (string.IsNullOrEmpty(prefix))
             {
                 return(null);
             }
             KeyValuePathSegment segment2 = odataPath.Segments[1] as KeyValuePathSegment;
             controllerContext.RouteData.Values.Add(ODataRouteConstants.Key, segment2.Value);
             string key = prefix + navigationProperty.Name + "On" + declaringType.Name;
             return(actionMap.Contains(key) ? key : (prefix + navigationProperty.Name));
         }
     }
     return(null);
 }
Example #18
0
        /// <summary>
        /// Selects the action.
        /// </summary>
        /// <param name="odataPath">The odata path.</param>
        /// <param name="controllerContext">The controller context.</param>
        /// <param name="actionMap">The action map.</param>
        /// <returns></returns>
        public override string SelectAction(ODataPath odataPath, HttpControllerContext controllerContext, ILookup <string, HttpActionDescriptor> actionMap)
        {
            if (odataPath == null)
            {
                throw Error.ArgumentNull("odataPath");
            }

            if (controllerContext == null)
            {
                throw Error.ArgumentNull("controllerContext");
            }

            if (actionMap == null)
            {
                throw Error.ArgumentNull("actionMap");
            }

            if (controllerContext.Request.Method == HttpMethod.Get &&
                (odataPath.PathTemplate == "~/entityset/key/navigation" ||
                 odataPath.PathTemplate == "~/entityset/key/cast/navigation"))
            {
                NavigationPathSegment  navigationSegment  = odataPath.Segments.Last() as NavigationPathSegment;
                IEdmNavigationProperty navigationProperty = navigationSegment.NavigationProperty;
                IEdmEntityType         declaringType      = navigationProperty.DeclaringType as IEdmEntityType;

                if (declaringType != null)
                {
                    KeyValuePathSegment keyValueSegment = odataPath.Segments[1] as KeyValuePathSegment;
                    controllerContext.RouteData.Values.Add(ODataRouteConstants.Key, keyValueSegment.Value);

                    // e.g. Try GetNavigationPropertyFromDeclaringType first, then fallback on GetNavigationProperty action name
                    string propertyFromDeclaringTypeActionName = "Get" + navigationProperty.Name + "From" + declaringType.Name;
                    return(actionMap.Contains(propertyFromDeclaringTypeActionName) ? propertyFromDeclaringTypeActionName : "Get" + navigationProperty.Name);
                }
            }

            return(null);
        }
Example #19
0
        public IHttpActionResult GetNavigation(string key, string navigation)
        {
            ODataPath path = Request.ODataProperties().Path;

            if (path.PathTemplate != "~/entityset/key/navigation")
            {
                return(BadRequest("Not the correct navigation property access request!"));
            }

            NavigationPathSegment property = path.Segments.Last() as NavigationPathSegment;

            if (property == null)
            {
                return(BadRequest("Not the correct navigation property access request!"));
            }

            IEdmEntityType entityType = property.NavigationProperty.DeclaringType as IEdmEntityType;

            EdmEntityObject entity = new EdmEntityObject(entityType);

            DataSourceProvider.Get((string)Request.Properties[Constants.ODataDataSource], key, entity);

            object value = DataSourceProvider.GetProperty((string)Request.Properties[Constants.ODataDataSource], navigation, entity);

            if (value == null)
            {
                return(NotFound());
            }

            IEdmEntityObject nav = value as IEdmEntityObject;

            if (nav == null)
            {
                return(NotFound());
            }

            return(Ok(nav));
        }
Example #20
0
        public override string SelectAction(ODataPath odataPath, HttpControllerContext context,
                                            ILookup <string, HttpActionDescriptor> actionMap)
        {
            /*
             * if (context.Request.Method == HttpMethod.Get &&
             *  odataPath.PathTemplate == "~/entityset/key")
             * {
             *  string navigationPropertyName = odataPath.NavigationSource.Name;
             *  string actionName = "Get" + navigationPropertyName;
             *
             *  KeyValuePathSegment keyValueSegment = odataPath.Segments[1] as KeyValuePathSegment;
             *
             *  System.Guid key;
             *
             *  if (System.Guid.TryParse(keyValueSegment.Value, out key))
             *  {
             *      actionName += "ById";
             *      context.RouteData.Values[ODataRouteConstants.Key] = key;
             *  }
             *  else
             *  {
             *      actionName += "ByKey";
             *      context.RouteData.Values[ODataRouteConstants.Key] = keyValueSegment.Value;
             *  }
             *
             *  if (actionMap.Contains(actionName))
             *  {
             *      return actionName;
             *  }
             * }
             */

            if (context.Request.Method == HttpMethod.Get &&
                odataPath.PathTemplate == "~/entityset/key/navigation/key")
            {
                string navigationEntityName = model.FindDeclaredEntitySet((odataPath.Segments[2] as NavigationPathSegment).NavigationPropertyName).EntityType().Name;

                //NavigationPathSegment navigationSegment = odataPath.Segments[2] as NavigationPathSegment;
                //var declaringType = model.FindDeclaredEntitySet(navigationSegment.NavigationPropertyName);

                //IEdmNavigationProperty navigationProperty = navigationSegment.NavigationProperty.Partner;
                //IEdmEntityType declaringType = navigationProperty.DeclaringType as IEdmEntityType;
                //string actionName = "Get" + declaringType.Name;

                string actionName = "Get" + navigationEntityName + "ByRelatedKey";
                if (actionMap.Contains(actionName))
                {
                    // Add keys to route data, so they will bind to action parameters.
                    KeyValuePathSegment keyValueSegment = odataPath.Segments[1] as KeyValuePathSegment;
                    context.RouteData.Values[ODataRouteConstants.Key] = keyValueSegment.Value;

                    KeyValuePathSegment relatedKeySegment = odataPath.Segments[3] as KeyValuePathSegment;
                    context.RouteData.Values[ODataRouteConstants.RelatedKey] = relatedKeySegment.Value;

                    return(actionName);
                }
            }

            /*
             * if (context.Request.Method == HttpMethod.Post &&
             *  odataPath.PathTemplate == "~/entityset/key/navigation")
             * {
             *  string entityName = ((EntitySetPathSegment)(odataPath.Segments[0])).EntitySetName;
             *  string navigationPropertyName = (odataPath.Segments[2] as NavigationPathSegment).NavigationPropertyName;
             *  //string navigationEntityName = model.FindDeclaredEntitySet((odataPath.Segments[2] as NavigationPathSegment).NavigationPropertyName).Name;
             *
             *  var navigationPropertyBinding =
             *  ((Microsoft.OData.Edm.Library.EdmNavigationPropertyBinding)
             *  (model.FindDeclaredEntitySet(entityName)
             *      .NavigationPropertyBindings
             *      .FirstOrDefault(r => r.NavigationProperty.Name == navigationPropertyName)));
             *
             *  var navigationPropertyType = navigationPropertyBinding
             *      .Target
             *      .EntityType();
             *
             *  string actionName = "Post" + navigationPropertyName + "To" + entityName;
             *  if (actionMap.Contains(actionName))
             *  {
             *      KeyValuePathSegment keyValueSegment = odataPath.Segments[1] as KeyValuePathSegment;
             *      context.RouteData.Values[ODataRouteConstants.Key] = keyValueSegment.Value;
             *
             *      var content = context.Request.Content.ReadAsStringAsync().Result;
             *      var entity = Newtonsoft.Json.JsonConvert.DeserializeObject(content, Type.GetType(navigationPropertyType.FullTypeName()));
             *      context.RouteData.Values["entity"] = entity;
             *
             *      return actionName;
             *  }
             * }
             */
            /*
             * if (context.Request.Method == HttpMethod.Put &&
             *  odataPath.PathTemplate == "~/entityset/key/navigation/key")
             * {
             *  string entityName = ((EntitySetPathSegment)(odataPath.Segments[0])).EntitySetName;
             *  string navigationEntityName = model.FindDeclaredEntitySet((odataPath.Segments[2] as NavigationPathSegment).NavigationPropertyName).EntityType().Name;
             *  string navigationPropertyName = (odataPath.Segments[2] as NavigationPathSegment).NavigationPropertyName;
             *
             *  //string entityName = model.FindDeclaredEntitySet(((EntitySetPathSegment)(odataPath.Segments[0])).EntitySetName).EntityType().Name;
             *  //NavigationPathSegment navigationSegment = odataPath.Segments[2] as NavigationPathSegment;
             *  //IEdmNavigationProperty navigationProperty = navigationSegment.NavigationProperty;
             *
             *  //var declaringType = model.FindDeclaredEntitySet(navigationSegment.NavigationPropertyName);
             *  //var entityType = declaringType.EntityType();
             *  //IEdmEntityType declaringType = navigationProperty.DeclaringType as IEdmEntityType;
             *  //string actionName = "Put" + declaringType.Name;
             *
             *  var navigationPropertyBinding =
             *  ((Microsoft.OData.Edm.Library.EdmNavigationPropertyBinding)
             *  (model.FindDeclaredEntitySet(entityName)
             *      .NavigationPropertyBindings
             *      .FirstOrDefault(r => r.NavigationProperty.Name == navigationPropertyName)));
             *
             *  var navigationPropertyType = navigationPropertyBinding
             *      .Target
             *      .EntityType();
             *
             *  string actionName = "Update" + navigationEntityName;
             *  //string actionName = "Put" + navigationEntityName + "To" + entityName;
             *
             *  if (actionMap.Contains(actionName))
             *  {
             *      // Add keys to route data, so they will bind to action parameters.
             *      KeyValuePathSegment keyValueSegment = odataPath.Segments[1] as KeyValuePathSegment;
             *      context.RouteData.Values[ODataRouteConstants.Key] = keyValueSegment.Value;
             *
             *      KeyValuePathSegment relatedKeySegment = odataPath.Segments[3] as KeyValuePathSegment;
             *      context.RouteData.Values[ODataRouteConstants.RelatedKey] = relatedKeySegment.Value;
             *
             *      var content = context.Request.Content.ReadAsStringAsync().Result;
             *      var entity = Newtonsoft.Json.JsonConvert.DeserializeObject(content, Type.GetType(navigationPropertyType.FullTypeName()));
             *      context.RouteData.Values["entity"] = entity;
             *
             *      return actionName;
             *  }
             * }
             */

            if (context.Request.Method == HttpMethod.Put &&
                odataPath.PathTemplate == "~/entityset/key/navigation/key")
            {
                string navigationPropertyName = (odataPath.Segments[2] as NavigationPathSegment).NavigationPropertyName;
                string actionName             = "Update" + navigationPropertyName;

                if (actionMap.Contains(actionName))
                {
                    // Add keys to route data, so they will bind to action parameters.
                    KeyValuePathSegment keyValueSegment = odataPath.Segments[1] as KeyValuePathSegment;
                    context.RouteData.Values[ODataRouteConstants.Key] = keyValueSegment.Value;

                    KeyValuePathSegment relatedKeySegment = odataPath.Segments[3] as KeyValuePathSegment;
                    context.RouteData.Values[ODataRouteConstants.RelatedKey] = relatedKeySegment.Value;

                    return(actionName);
                }
            }

            if (context.Request.Method == HttpMethod.Put &&
                odataPath.PathTemplate == "~/entityset/key/navigation")
            {
                string navigationPropertyName = (odataPath.Segments[2] as NavigationPathSegment).NavigationPropertyName;
                string actionName             = "Update" + navigationPropertyName;

                if (actionMap.Contains(actionName))
                {
                    // Add keys to route data, so they will bind to action parameters.
                    KeyValuePathSegment keyValueSegment = odataPath.Segments[1] as KeyValuePathSegment;
                    context.RouteData.Values[ODataRouteConstants.Key] = keyValueSegment.Value;

                    return(actionName);
                }
            }

            if (context.Request.Method == HttpMethod.Post &&
                odataPath.PathTemplate == "~/entityset/key/navigation")
            {
                NavigationPathSegment segment = (odataPath.Segments[2] as NavigationPathSegment);
                string navigationPropertyName = segment.NavigationPropertyName;
                string actionPrefix           = "Create";

                var type = segment.NavigationProperty.Type.Definition.TypeKind;
                if (type == EdmTypeKind.Collection)
                {
                    actionPrefix = "AddTo";
                }

                string actionName = actionPrefix + navigationPropertyName;

                if (actionMap.Contains(actionName))
                {
                    // Add keys to route data, so they will bind to action parameters.
                    KeyValuePathSegment keyValueSegment = odataPath.Segments[1] as KeyValuePathSegment;
                    context.RouteData.Values[ODataRouteConstants.Key] = keyValueSegment.Value;

                    return(actionName);
                }
            }

            // Not a match.
            return(null);
        }
        // Determines if a status code needs to be changed based on the path of the request and returns the new
        // status code or null if no change is required.
        internal static HttpStatusCode?GetUpdatedResponseStatusCodeOrNull(ODataPath oDataPath)
        {
            if (oDataPath == null || oDataPath.Segments == null || oDataPath.Segments.Count == 0)
            {
                return(null);
            }

            // Skip any sequence of cast segments at the end of the path.
            int currentIndex = oDataPath.Segments.Count - 1;
            ReadOnlyCollection <ODataPathSegment> segments = oDataPath.Segments;

            while (currentIndex >= 0 && segments[currentIndex].SegmentKind == ODataSegmentKinds.Cast)
            {
                currentIndex--;
            }

            // Null value properties should be treated in the same way independent of whether the user asked for the
            // raw value of the property or a specific format, so we skip the $value segment as it can only be
            // preceeded by a property access segment.
            if (currentIndex >= 0 && segments[currentIndex].SegmentKind == ODataSegmentKinds.Value)
            {
                currentIndex--;
            }

            // Protect ourselves against malformed path segments.
            if (currentIndex < 0)
            {
                return(null);
            }

            switch (segments[currentIndex].SegmentKind)
            {
            case ODataSegmentKinds._Key:
                // Look at the previous segment to decide, but skip any possible sequence of cast segments in
                // between.
                currentIndex--;
                while (currentIndex >= 0 && segments[currentIndex].SegmentKind == ODataSegmentKinds.Cast)
                {
                    currentIndex--;
                }
                if (currentIndex < 0)
                {
                    return(null);
                }

                switch (segments[currentIndex].SegmentKind)
                {
                case ODataSegmentKinds._EntitySet:
                    // Return 404 if we were trying to retrieve a specific entity from an entity set.
                    return(HttpStatusCode.NotFound);

                case ODataSegmentKinds._Navigation:
                    // Return 204 if we were trying to retrieve a related entity via a navigation property.
                    return(HttpStatusCode.NoContent);

                default:
                    break;
                }
                return(null);

            case ODataSegmentKinds._Property:
                // Return 204 only if the property is single valued (not a collection of values).
                PropertyAccessPathSegment property = (PropertyAccessPathSegment)segments[currentIndex];
                return(GetChangedStatusCodeForProperty(property));

            case ODataSegmentKinds._Navigation:
                // Return 204 only if the navigation property is a single related entity and not a collection
                // of entities.
                NavigationPathSegment navigation = (NavigationPathSegment)segments[currentIndex];
                return(GetChangedStatusCodeForNavigationProperty(navigation));

            case ODataSegmentKinds._Singleton:
                // Return 404 for a singleton with a null value.
                return(HttpStatusCode.NotFound);

            default:
                return(null);
            }
        }
Example #22
0
        /// <inheritdoc/>
        public override string SelectAction(ODataPath odataPath, HttpControllerContext controllerContext, ILookup <string, HttpActionDescriptor> actionMap)
        {
            if (odataPath == null)
            {
                throw Error.ArgumentNull("odataPath");
            }

            if (controllerContext == null)
            {
                throw Error.ArgumentNull("controllerContext");
            }

            if (actionMap == null)
            {
                throw Error.ArgumentNull("actionMap");
            }

            HttpMethod method           = controllerContext.Request.Method;
            string     actionNamePrefix = GetActionMethodPrefix(method);

            if (actionNamePrefix == null)
            {
                return(null);
            }

            if (odataPath.PathTemplate == "~/entityset/key/navigation" ||
                odataPath.PathTemplate == "~/entityset/key/navigation/$count" ||
                odataPath.PathTemplate == "~/entityset/key/cast/navigation" ||
                odataPath.PathTemplate == "~/entityset/key/cast/navigation/$count" ||
                odataPath.PathTemplate == "~/singleton/navigation" ||
                odataPath.PathTemplate == "~/singleton/navigation/$count" ||
                odataPath.PathTemplate == "~/singleton/cast/navigation" ||
                odataPath.PathTemplate == "~/singleton/cast/navigation/$count")
            {
                NavigationPathSegment navigationSegment =
                    (odataPath.Segments.Last() as NavigationPathSegment) ??
                    odataPath.Segments[odataPath.Segments.Count - 2] as NavigationPathSegment;
                IEdmNavigationProperty navigationProperty = navigationSegment.NavigationProperty;
                IEdmEntityType         declaringType      = navigationProperty.DeclaringType as IEdmEntityType;

                // It is not valid to *Post* to any non-collection valued navigation property.
                if (navigationProperty.TargetMultiplicity() != EdmMultiplicity.Many &&
                    method == HttpMethod.Post)
                {
                    return(null);
                }

                // It is not valid to *Put/Patch" to any collection-valued navigation property.
                if (navigationProperty.TargetMultiplicity() == EdmMultiplicity.Many &&
                    (method == HttpMethod.Put || "PATCH" == method.Method.ToUpperInvariant()))
                {
                    return(null);
                }

                // *Get* is the only supported method for $count request.
                if (odataPath.Segments.Last() is CountPathSegment && method != HttpMethod.Get)
                {
                    return(null);
                }

                if (declaringType != null)
                {
                    // e.g. Try GetNavigationPropertyFromDeclaringType first, then fallback on GetNavigationProperty action name
                    string actionName = actionMap.FindMatchingAction(
                        actionNamePrefix + navigationProperty.Name + "From" + declaringType.Name,
                        actionNamePrefix + navigationProperty.Name);

                    if (actionName != null)
                    {
                        if (odataPath.PathTemplate.StartsWith("~/entityset/key", StringComparison.Ordinal))
                        {
                            KeyValuePathSegment keyValueSegment = odataPath.Segments[1] as KeyValuePathSegment;
                            controllerContext.RouteData.Values[ODataRouteConstants.Key] = keyValueSegment.Value;
                        }

                        return(actionName);
                    }
                }
            }

            return(null);
        }
        /// <inheritdoc/>
        public override string SelectAction(ODataPath odataPath, HttpControllerContext controllerContext, ILookup <string, HttpActionDescriptor> actionMap)
        {
            if (odataPath == null)
            {
                throw Error.ArgumentNull("odataPath");
            }

            if (controllerContext == null)
            {
                throw Error.ArgumentNull("controllerContext");
            }

            if (actionMap == null)
            {
                throw Error.ArgumentNull("actionMap");
            }

            HttpMethod     requestMethod = controllerContext.Request.Method;
            IHttpRouteData routeData     = controllerContext.RouteData;

            if (!IsSupportedRequestMethod(requestMethod))
            {
                return(null);
            }

            if (odataPath.PathTemplate == "~/entityset/key/navigation/$ref" ||
                odataPath.PathTemplate == "~/entityset/key/cast/navigation/$ref" ||
                odataPath.PathTemplate == "~/singleton/navigation/$ref" ||
                odataPath.PathTemplate == "~/singleton/cast/navigation/$ref")
            {
                NavigationPathSegment  navigationSegment  = (NavigationPathSegment)odataPath.Segments[odataPath.Segments.Count - 2];
                IEdmNavigationProperty navigationProperty = navigationSegment.NavigationProperty;
                IEdmEntityType         declaringType      = navigationProperty.DeclaringEntityType();

                string refActionName = FindRefActionName(actionMap, navigationProperty, declaringType, requestMethod);
                if (refActionName != null)
                {
                    if (odataPath.PathTemplate.StartsWith("~/entityset/key", StringComparison.Ordinal))
                    {
                        routeData.Values[ODataRouteConstants.Key] = ((KeyValuePathSegment)odataPath.Segments[1]).Value;
                    }

                    routeData.Values[ODataRouteConstants.NavigationProperty] = navigationSegment.NavigationProperty.Name;
                    return(refActionName);
                }
            }
            else if ((requestMethod == HttpMethod.Delete) && (
                         odataPath.PathTemplate == "~/entityset/key/navigation/key/$ref" ||
                         odataPath.PathTemplate == "~/entityset/key/cast/navigation/key/$ref" ||
                         odataPath.PathTemplate == "~/singleton/navigation/key/$ref" ||
                         odataPath.PathTemplate == "~/singleton/cast/navigation/key/$ref"))
            {
                NavigationPathSegment  navigationSegment  = (NavigationPathSegment)odataPath.Segments[odataPath.Segments.Count - 3];
                IEdmNavigationProperty navigationProperty = navigationSegment.NavigationProperty;
                IEdmEntityType         declaringType      = navigationProperty.DeclaringEntityType();

                string refActionName = FindRefActionName(actionMap, navigationProperty, declaringType, requestMethod);
                if (refActionName != null)
                {
                    if (odataPath.PathTemplate.StartsWith("~/entityset/key", StringComparison.Ordinal))
                    {
                        routeData.Values[ODataRouteConstants.Key] = ((KeyValuePathSegment)odataPath.Segments[1]).Value;
                    }

                    routeData.Values[ODataRouteConstants.NavigationProperty] = navigationSegment.NavigationProperty.Name;
                    routeData.Values[ODataRouteConstants.RelatedKey]         = ((KeyValuePathSegment)odataPath.Segments[odataPath.Segments.Count - 2]).Value;
                    return(refActionName);
                }
            }

            return(null);
        }
        public override string SelectAction(ODataPath odataPath, HttpControllerContext context,
                                            ILookup <string, HttpActionDescriptor> actionMap)
        {
            if (context.Request.Method == HttpMethod.Get &&
                odataPath.PathTemplate == "~/entityset/key/navigation/key")
            {
                string navigationEntityName = model.FindDeclaredEntitySet((odataPath.Segments[2] as NavigationPathSegment).NavigationPropertyName).EntityType().Name;

                string actionName = "Get" + navigationEntityName + "ByRelatedKey";
                if (actionMap.Contains(actionName))
                {
                    // Add keys to route data, so they will bind to action parameters.
                    KeyValuePathSegment keyValueSegment = odataPath.Segments[1] as KeyValuePathSegment;
                    context.RouteData.Values[ODataRouteConstants.Key] = keyValueSegment.Value;

                    KeyValuePathSegment relatedKeySegment = odataPath.Segments[3] as KeyValuePathSegment;
                    context.RouteData.Values[ODataRouteConstants.RelatedKey] = relatedKeySegment.Value;

                    return(actionName);
                }
            }

            if (context.Request.Method == HttpMethod.Put &&
                odataPath.PathTemplate == "~/entityset/key/navigation/key")
            {
                string navigationPropertyName = (odataPath.Segments[2] as NavigationPathSegment).NavigationPropertyName;
                string actionName             = "Update" + navigationPropertyName;

                if (actionMap.Contains(actionName))
                {
                    // Add keys to route data, so they will bind to action parameters.
                    KeyValuePathSegment keyValueSegment = odataPath.Segments[1] as KeyValuePathSegment;
                    context.RouteData.Values[ODataRouteConstants.Key] = keyValueSegment.Value;

                    KeyValuePathSegment relatedKeySegment = odataPath.Segments[3] as KeyValuePathSegment;
                    context.RouteData.Values[ODataRouteConstants.RelatedKey] = relatedKeySegment.Value;

                    return(actionName);
                }
            }

            if (context.Request.Method == HttpMethod.Put &&
                odataPath.PathTemplate == "~/entityset/key/navigation")
            {
                string navigationPropertyName = (odataPath.Segments[2] as NavigationPathSegment).NavigationPropertyName;
                string actionName             = "Update" + navigationPropertyName;

                if (actionMap.Contains(actionName))
                {
                    // Add keys to route data, so they will bind to action parameters.
                    KeyValuePathSegment keyValueSegment = odataPath.Segments[1] as KeyValuePathSegment;
                    context.RouteData.Values[ODataRouteConstants.Key] = keyValueSegment.Value;

                    return(actionName);
                }
            }

            if (context.Request.Method == HttpMethod.Post &&
                odataPath.PathTemplate == "~/entityset/key/navigation")
            {
                NavigationPathSegment segment = (odataPath.Segments[2] as NavigationPathSegment);
                string navigationPropertyName = segment.NavigationPropertyName;
                string actionPrefix           = "Create";

                var type = segment.NavigationProperty.Type.Definition.TypeKind;
                if (type == EdmTypeKind.Collection)
                {
                    actionPrefix = "AddTo";
                }

                string actionName = actionPrefix + navigationPropertyName;

                if (actionMap.Contains(actionName))
                {
                    // Add keys to route data, so they will bind to action parameters.
                    KeyValuePathSegment keyValueSegment = odataPath.Segments[1] as KeyValuePathSegment;
                    context.RouteData.Values[ODataRouteConstants.Key] = keyValueSegment.Value;

                    return(actionName);
                }
            }

            // Not a match.
            return(null);
        }
        public static IEdmNavigationProperty GetNavigationProperty(ODataPath odataPath)
        {
            NavigationPathSegment segment = odataPath.Segments.OfType <NavigationPathSegment>().SingleOrDefault();

            return(segment == null ? null : segment.NavigationProperty);
        }