internal static IReadOnlyDictionary <string, object> GetPathKeyValues(ODataPath path) { if (path.PathTemplate == "~/entityset/key" || path.PathTemplate == "~/entityset/key/cast") { KeyValuePathSegment keySegment = (KeyValuePathSegment)path.Segments[1]; return(GetPathKeyValues(keySegment, (IEdmEntityType)path.EdmType)); } else { throw new InvalidOperationException(string.Format( CultureInfo.InvariantCulture, Resources.InvalidPathTemplateInRequest, "~/entityset/key")); } }
/// <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"); } if (controllerContext.Request.Method == HttpMethod.Post) { switch (odataPath.PathTemplate) { case "~/entityset/key/cast/action": case "~/entityset/key/action": string actionName = GetAction(odataPath).SelectAction(actionMap, isCollection: false); if (actionName != null) { EntitySetPathSegment entitySetPathSegment = (EntitySetPathSegment)odataPath.Segments.First(); IEdmEntityType edmEntityType = entitySetPathSegment.EntitySetBase.EntityType(); KeyValuePathSegment keyValueSegment = (KeyValuePathSegment)odataPath.Segments[1]; controllerContext.AddKeyValueToRouteData(keyValueSegment, edmEntityType, ODataRouteConstants.Key); } return(actionName); case "~/entityset/cast/action": case "~/entityset/action": return(GetAction(odataPath).SelectAction(actionMap, isCollection: true)); case "~/singleton/action": case "~/singleton/cast/action": return(GetAction(odataPath).SelectAction(actionMap, isCollection: false)); } } return(null); }
/// <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); }
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); }
public IHttpActionResult CreateRefToCategory(int key, string navigationProperty, [FromBody] Uri reference) { Customer customer = DataSource.Customers.FirstOrDefault(e => e.CustomerId == key); if (customer == null) { return(NotFound()); } if (navigationProperty != "Category") { return(BadRequest()); } ODataRoute route = Request.GetConfiguration().Routes.First(e => e is ODataRoute) as ODataRoute; // just for test: string serviceRoot = "http://localhost:12345/odata/"; string odataPath = reference.AbsoluteUri.Substring(serviceRoot.Length); IEdmModel model = Request.ODataProperties().Model; ODataPath path = Request.ODataProperties().PathHandler.Parse(model, serviceRoot, odataPath); if (path.PathTemplate == "~/entityset/key") { KeyValuePathSegment newKey = path.Segments.Last() as KeyValuePathSegment; int categoryId = int.Parse(newKey.Value); Category category = DataSource.Categories.First(e => e.CategoryId == categoryId); if (category == null) { category = new Category { CategoryId = categoryId }; DataSource.Categories.Add(category); } customer.Category = category; return(Ok(category)); } return(BadRequest()); }
/// <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; if (odataPath.PathTemplate == "~/entityset/key/$links/navigation") { if (requestMethod == HttpMethod.Post || requestMethod == HttpMethod.Put) { AddLinkInfoToRouteData(controllerContext.RouteData, odataPath); return("CreateLink"); } else if (requestMethod == HttpMethod.Delete) { AddLinkInfoToRouteData(controllerContext.RouteData, odataPath); return("DeleteLink"); } } else if (odataPath.PathTemplate == "~/entityset/key/$links/navigation/key" && requestMethod == HttpMethod.Delete) { AddLinkInfoToRouteData(controllerContext.RouteData, odataPath); KeyValuePathSegment relatedKeySegment = odataPath.Segments[4] as KeyValuePathSegment; controllerContext.RouteData.Values.Add(ODataRouteConstants.RelatedKey, relatedKeySegment.Value); return("DeleteLink"); } 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"); } IEdmProperty property = GetProperty(odataPath, controllerContext.Request.Method); IEdmEntityType declaringType = property == null ? null : property.DeclaringType as IEdmEntityType; if (declaringType != null) { // e.g. Try GetPropertyFromDeclaringType first, then fallback on GetProperty action name string actionName = actionMap.FindMatchingAction( "Get" + property.Name + "From" + declaringType.Name, "Get" + property.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); }
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); }
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); }
public static void HasNavigationPropertyLink <TEntity, TValue>( this EntitySetConfiguration <TEntity> entitySet, NavigationPropertyConfiguration navigationProperty, Expression <Func <TEntity, TValue> > foreignKeyProperty, string targetEntitySetName) where TEntity : class { Arg.NotNull(entitySet, nameof(entitySet)); Arg.NotNull(navigationProperty, nameof(navigationProperty)); Arg.NotNull(foreignKeyProperty, nameof(foreignKeyProperty)); Arg.NotNullOrEmpty(targetEntitySetName, nameof(targetEntitySetName)); var foreignKeyPropertyName = foreignKeyProperty.GetPropertyName(); entitySet.HasNavigationPropertyLink( navigationProperty, (context, property) => { var entity = context.EdmObject; object value; if (!entity.TryGetPropertyValue(foreignKeyPropertyName, out value)) { return(null); } if (value == null) { return(null); } var entitySetPath = new EntitySetPathSegment(targetEntitySetName); var keyValuePath = new KeyValuePathSegment(ODataUriUtils.ConvertToUriLiteral(value, ODataVersion.V4)); var url = new Uri(context.Url.CreateODataLink(entitySetPath, keyValuePath)); return(url); }, false); }
/// <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); }
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/property") { KeyValuePathSegment segment = (KeyValuePathSegment)odataPath.Segments[1]; object value = ODataUriUtils.ConvertFromUriLiteral(segment.Value, ODataVersion.V4); controllerContext.RouteData.Values.Add("key", value); PropertyAccessPathSegment property = odataPath.Segments.Last() as PropertyAccessPathSegment; controllerContext.RouteData.Values.Add("propertyName", property.PropertyName); return("ReturnPropertyValue"); } return(null); }
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); }
public static void AddKeyValueToRouteData(this HttpControllerContext controllerContext, KeyValuePathSegment keySegment, IEdmEntityType entityType, string keyPrefix) { Contract.Assert(controllerContext != null); Contract.Assert(keySegment != null); IDictionary<string, object> routingConventionsStore = controllerContext.Request.ODataProperties().RoutingConventionsStore; if (entityType == null && keySegment.Segment != null) { entityType = keySegment.Segment.EdmType as IEdmEntityType; } Contract.Assert(entityType != null); int keyCount; if (keySegment.Segment != null) { keyCount = keySegment.Segment.Keys.Count(); foreach (var keyValue in keySegment.Segment.Keys) { IEdmTypeReference keyType; string newKeyName = GetKeyInfos(keyCount, keyValue.Key, entityType, keyPrefix, out keyType); ODataPathSegmentExtensions.AddKeyValues(newKeyName, keyValue.Value, keyType, controllerContext.RouteData.Values, routingConventionsStore); } } else { IEdmModel model = controllerContext.Request.ODataProperties().Model; IDictionary<string, string> keyValues = keySegment.Values; keyCount = keyValues.Count; foreach (var keyValue in keyValues) { IEdmTypeReference keyType; string newKeyName = GetKeyInfos(keyCount, keyValue.Key, entityType, keyPrefix, out keyType); object value = ODataUriUtils.ConvertFromUriLiteral(keyValue.Value, ODataVersion.V4, model, keyType); Contract.Assert(value != null); ODataPathSegmentExtensions.AddKeyValues(newKeyName, value, keyType, controllerContext.RouteData.Values, routingConventionsStore); } } }
/// <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"); } string actionName = null; DynamicPropertyPathSegment dynamicPropertSegment = null; switch (odataPath.PathTemplate) { case "~/entityset/key/dynamicproperty": case "~/entityset/key/cast/dynamicproperty": case "~/singleton/dynamicproperty": case "~/singleton/cast/dynamicproperty": dynamicPropertSegment = odataPath.Segments[odataPath.Segments.Count - 1] as DynamicPropertyPathSegment; if (dynamicPropertSegment == null) { return(null); } if (controllerContext.Request.Method == HttpMethod.Get) { string actionNamePrefix = String.Format(CultureInfo.InvariantCulture, "Get{0}", _actionName); actionName = actionMap.FindMatchingAction(actionNamePrefix); } break; case "~/entityset/key/property/dynamicproperty": case "~/entityset/key/cast/property/dynamicproperty": case "~/singleton/property/dynamicproperty": case "~/singleton/cast/property/dynamicproperty": dynamicPropertSegment = odataPath.Segments[odataPath.Segments.Count - 1] as DynamicPropertyPathSegment; if (dynamicPropertSegment == null) { return(null); } PropertyAccessPathSegment propertyAccessSegment = odataPath.Segments[odataPath.Segments.Count - 2] as PropertyAccessPathSegment; if (propertyAccessSegment == null) { return(null); } EdmComplexType complexType = propertyAccessSegment.Property.Type.Definition as EdmComplexType; if (complexType == null) { return(null); } if (controllerContext.Request.Method == HttpMethod.Get) { string actionNamePrefix = String.Format(CultureInfo.InvariantCulture, "Get{0}", _actionName); actionName = actionMap.FindMatchingAction(actionNamePrefix + "From" + complexType.Name); } break; default: break; } 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; } controllerContext.RouteData.Values[ODataRouteConstants.DynamicProperty] = dynamicPropertSegment.PropertyName; 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 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); }
/// <summary> /// Selects the action for OData requests. /// </summary> /// <param name="odataPath">The OData path.</param> /// <param name="controllerContext">The controller context.</param> /// <param name="actionMap">The action map.</param> /// <returns> /// <c>null</c> if the request isn't handled by this convention; otherwise, the name of the selected action /// </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.Post) { if (odataPath.PathTemplate == "~/entityset/key/action" || odataPath.PathTemplate == "~/entityset/key/cast/action") { ActionPathSegment actionSegment = odataPath.Segments.Last() as ActionPathSegment; IEdmFunctionImport action = actionSegment.Action; // The binding parameter is the first parameter by convention IEdmFunctionParameter bindingParameter = action.Parameters.FirstOrDefault(); if (action.IsBindable && bindingParameter != null) { IEdmEntityType bindingParameterType = bindingParameter.Type.Definition as IEdmEntityType; if (bindingParameterType != null) { KeyValuePathSegment keyValueSegment = odataPath.Segments[1] as KeyValuePathSegment; controllerContext.RouteData.Values.Add(ODataRouteConstants.Key, keyValueSegment.Value); // e.g. Try ActionOnBindingParameterType first, then fallback on Action action name string actionOnBindingTypeActionName = action.Name + "On" + bindingParameterType.Name; return(actionMap.Contains(actionOnBindingTypeActionName) ? actionOnBindingTypeActionName : action.Name); } } } else if (odataPath.PathTemplate == "~/entityset/action" || odataPath.PathTemplate == "~/entityset/cast/action") { ActionPathSegment actionSegment = odataPath.Segments.Last() as ActionPathSegment; IEdmFunctionImport action = actionSegment.Action; // The binding parameter is the first parameter by convention IEdmFunctionParameter bindingParameter = action.Parameters.FirstOrDefault(); if (action.IsBindable && bindingParameter != null) { IEdmCollectionType bindingParameterType = bindingParameter.Type.Definition as IEdmCollectionType; if (bindingParameterType != null) { // e.g. Try ActionOnBindingParameterType first, then fallback on Action action name IEdmEntityType elementType = bindingParameterType.ElementType.Definition as IEdmEntityType; string actionOnBindingTypeActionName = action.Name + "OnCollectionOf" + elementType.Name; return(actionMap.Contains(actionOnBindingTypeActionName) ? actionOnBindingTypeActionName : action.Name); } } } } 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); }
/// <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"); } if (controllerContext.Request.Method == HttpMethod.Get) { string actionName = null; BoundFunctionPathSegment function = null; switch (odataPath.PathTemplate) { case "~/entityset/key/cast/function": case "~/entityset/key/function": function = odataPath.Segments.Last() as BoundFunctionPathSegment; actionName = GetFunction(function).SelectAction(actionMap, isCollection: false); if (actionName != null) { EntitySetPathSegment entitySetPathSegment = (EntitySetPathSegment)odataPath.Segments.First(); IEdmEntityType edmEntityType = entitySetPathSegment.EntitySetBase.EntityType(); KeyValuePathSegment keyValueSegment = (KeyValuePathSegment)odataPath.Segments[1]; controllerContext.AddKeyValueToRouteData(keyValueSegment, edmEntityType, ODataRouteConstants.Key); } break; case "~/entityset/key/cast/function/$count": case "~/entityset/key/function/$count": function = odataPath.Segments[odataPath.Segments.Count - 2] as BoundFunctionPathSegment; actionName = GetFunction(function).SelectAction(actionMap, isCollection: false); if (actionName != null) { EntitySetPathSegment entitySetPathSegment = (EntitySetPathSegment)odataPath.Segments.First(); IEdmEntityType edmEntityType = entitySetPathSegment.EntitySetBase.EntityType(); KeyValuePathSegment keyValueSegment = (KeyValuePathSegment)odataPath.Segments[1]; controllerContext.AddKeyValueToRouteData(keyValueSegment, edmEntityType, ODataRouteConstants.Key); } break; case "~/entityset/cast/function": case "~/entityset/function": function = odataPath.Segments.Last() as BoundFunctionPathSegment; actionName = GetFunction(function).SelectAction(actionMap, isCollection: true); break; case "~/entityset/cast/function/$count": case "~/entityset/function/$count": function = odataPath.Segments[odataPath.Segments.Count - 2] as BoundFunctionPathSegment; actionName = GetFunction(function).SelectAction(actionMap, isCollection: true); break; case "~/singleton/function": case "~/singleton/cast/function": function = odataPath.Segments.Last() as BoundFunctionPathSegment; actionName = GetFunction(function).SelectAction(actionMap, isCollection: false); break; case "~/singleton/function/$count": case "~/singleton/cast/function/$count": function = odataPath.Segments[odataPath.Segments.Count - 2] as BoundFunctionPathSegment; actionName = GetFunction(function).SelectAction(actionMap, isCollection: false); break; } if (actionName != null) { controllerContext.AddFunctionParameterToRouteData(function); return(actionName); } } return(null); }
public override string SelectAction(ODataPath odataPath, HttpControllerContext controllerContext, ILookup <string, HttpActionDescriptor> actionMap) { if (odataPath.PathTemplate == "~/entityset/key") { KeyValuePathSegment segment = (KeyValuePathSegment)odataPath.Segments.Last(); var keyValues = segment.Value.Split(','); if (keyValues.Length <= 1) { return(null); // let other conventions to process } foreach (var item in keyValues) { var keyValue = item.Split('='); if (keyValue.Length != 2) { continue; } string key = keyValue[0].Trim(); string valueString = keyValue[1].Trim(); object value = ODataUriUtils.ConvertFromUriLiteral(valueString, ODataVersion.V4); controllerContext.RouteData.Values.Add("key" + key, value); // use a prefix } /* * IEdmModel model = controllerContext.Request.ODataProperties().Model; * * string a = controllerContext.Request.GetUrlHelper().CreateODataLink(odataPath.Segments); * //Uri b = new Uri(); * * ODataUriParser parser = new ODataUriParser(model, new Uri(a, UriKind.Absolute)); * Sematic.ODataPath path = parser.ParsePath(); * Sematic.KeySegment keySegment = path.LastSegment as Sematic.KeySegment; * foreach (var key in keySegment.Keys) * { * controllerContext.RouteData.Values.Add("key" + key.Key, key.Value); * }*/ HttpMethod httpMethod = controllerContext.Request.Method; string httpMethodName; switch (httpMethod.ToString().ToUpperInvariant()) { case "GET": httpMethodName = "Get"; break; case "PUT": httpMethodName = "Put"; break; case "PATCH": case "MERGE": httpMethodName = "Patch"; break; case "DELETE": httpMethodName = "Delete"; break; default: return(null); } IEdmEntityType entityType = odataPath.EdmType as IEdmEntityType; string actionName = FindMatchingAction(actionMap, httpMethodName + entityType.Name, httpMethodName); return(actionName); } return(null); }
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"); } string actionName = null; DynamicPropertyPathSegment dynamicPropertSegment = null; switch (odataPath.PathTemplate) { case "~/entityset/key/dynamicproperty": case "~/entityset/key/cast/dynamicproperty": case "~/singleton/dynamicproperty": case "~/singleton/cast/dynamicproperty": dynamicPropertSegment = odataPath.Segments[odataPath.Segments.Count - 1] as DynamicPropertyPathSegment; if (dynamicPropertSegment == null) { return(null); } if (controllerContext.Request.Method == HttpMethod.Get) { string actionNamePrefix = String.Format(CultureInfo.InvariantCulture, "Get{0}", _actionName); actionName = actionMap.FindMatchingAction(actionNamePrefix); } break; case "~/entityset/key/property/dynamicproperty": case "~/entityset/key/cast/property/dynamicproperty": case "~/singleton/property/dynamicproperty": case "~/singleton/cast/property/dynamicproperty": dynamicPropertSegment = odataPath.Segments[odataPath.Segments.Count - 1] as DynamicPropertyPathSegment; if (dynamicPropertSegment == null) { return(null); } PropertyAccessPathSegment propertyAccessSegment = odataPath.Segments[odataPath.Segments.Count - 2] as PropertyAccessPathSegment; if (propertyAccessSegment == null) { return(null); } EdmComplexType complexType = propertyAccessSegment.Property.Type.Definition as EdmComplexType; if (complexType == null) { return(null); } if (controllerContext.Request.Method == HttpMethod.Get) { string actionNamePrefix = String.Format(CultureInfo.InvariantCulture, "Get{0}", _actionName); actionName = actionMap.FindMatchingAction(actionNamePrefix + "From" + propertyAccessSegment.Property.Name); } break; default: break; } if (actionName != null) { if (odataPath.PathTemplate.StartsWith("~/entityset/key", StringComparison.Ordinal)) { EntitySetPathSegment entitySetPathSegment = (EntitySetPathSegment)odataPath.Segments.First(); IEdmEntityType edmEntityType = entitySetPathSegment.EntitySetBase.EntityType(); KeyValuePathSegment keyValueSegment = (KeyValuePathSegment)odataPath.Segments[1]; controllerContext.AddKeyValueToRouteData(keyValueSegment, edmEntityType, ODataRouteConstants.Key); } controllerContext.RouteData.Values[ODataRouteConstants.DynamicProperty] = dynamicPropertSegment.PropertyName; var key = ODataParameterValue.ParameterValuePrefix + ODataRouteConstants.DynamicProperty; var value = new ODataParameterValue(dynamicPropertSegment.PropertyName, EdmLibHelpers.GetEdmPrimitiveTypeReferenceOrNull(typeof(string))); controllerContext.Request.ODataProperties().RoutingConventionsStore[key] = value; return(actionName); } return(null); }
private IQueryable FilterOnKeys(IQueryable queryable, IEdmCollectionType edmCollectionType, KeyValuePathSegment segmentKey) { // need to filter down the entity var entityType = GetEdmEntityType(edmCollectionType); // make sure we found the key and entity if (entityType == null || segmentKey == null) { throw new WebAPIDataServiceException("Keys not found", new KeyNotFoundException()); } var entityKeys = entityType.DeclaredKey.Select(dk => dk.Name).ToArray(); // key can be pass in either , or name value pair var segmentKeys = segmentKey.Value.Split(','); if (segmentKeys.Length == entityKeys.Length) { //ToDo this won't handle the edge cases where a value contains an equal sign var passedInKeys = segmentKeys.Select(k => k.Split('=')) .Where(k => k.Length == 2) .Select( k => new KeyValuePair<string, string>(k[0], k[1])) .ToArray(); if (passedInKeys.Length > 0) { if (!entityKeys.OrderBy(k => k) .SequenceEqual(passedInKeys.Select(kv => kv.Key) .OrderBy(n => n))) { throw new WebAPIDataServiceException("Keys don't match entity model", new KeyNotFoundException()); } } else { // build up keyvalue pairs from entitykeys passedInKeys = segmentKeys.Zip(entityKeys, (s, k) => new KeyValuePair<string, string>(k, s)) .ToArray(); } // need to build the where clause var type = GetIEdmTypeToCLRType(entityType); var tSource = Expression.Parameter(type); var bodyList = new List<Expression>(); foreach (var keyPairs in passedInKeys) { var tProperty = Expression.Property(tSource, keyPairs.Key); var proptype = type.GetProperty(keyPairs.Key).PropertyType; var keyValue = keyPairs.Value; if (proptype == typeof (string)) { // strings usually start with ' and end with ' in OData Calls if (keyValue.StartsWith("'") && keyValue.EndsWith("'")) { keyValue = keyValue.Substring(1, keyValue.Length - 2); } } // Since using EF going to parameterize this var tupleType = typeof (Tuple<>).MakeGenericType(proptype); var tuple = Activator.CreateInstance(tupleType, Convert.ChangeType(keyValue, proptype)); bodyList.Add(Expression.Equal(tProperty, Expression.Property(Expression.Constant(tuple), "Item1"))); } // build up the body expressions adding the And method between each check check var body = bodyList[0]; for (var b = 1; b < bodyList.Count; b++) { body = Expression.And(body, bodyList[b]); } // Expression<Func<TSource, bool>> predicate var where = Expression.Lambda(typeof (Func<,>).MakeGenericType(type, typeof (bool)), body, tSource); // Call the Queryable.Where var call = Expression.Call(typeof (Queryable), "Where", new[] {type}, queryable.Expression, where); // return back the IQueryable return queryable.Provider.CreateQuery(call); } throw new WebAPIDataServiceException("Keys don't match entity model", new KeyNotFoundException()); }
/// <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"); } if (odataPath.PathTemplate == "~/entityset/key" || odataPath.PathTemplate == "~/entityset/key/cast") { HttpMethod httpMethod = controllerContext.Request.Method; string httpMethodName; switch (httpMethod.ToString().ToUpperInvariant()) { case "GET": httpMethodName = "Get"; break; case "PUT": httpMethodName = "Put"; break; case "PATCH": case "MERGE": httpMethodName = "Patch"; break; case "DELETE": httpMethodName = "Delete"; break; default: return(null); } Contract.Assert(httpMethodName != null); IEdmEntityType entityType = odataPath.EdmType as IEdmEntityType; // e.g. Try GetCustomer first, then fallback on Get action name string actionName = actionMap.FindMatchingAction( httpMethodName + entityType.Name, httpMethodName); if (actionName != null) { 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)) { EntitySetPathSegment entitySetPathSegment = (EntitySetPathSegment)odataPath.Segments.First(); IEdmEntityType edmEntityType = entitySetPathSegment.EntitySetBase.EntityType(); KeyValuePathSegment keyValueSegment = (KeyValuePathSegment)odataPath.Segments[1]; controllerContext.AddKeyValueToRouteData(keyValueSegment, edmEntityType, ODataRouteConstants.Key); } 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)) { EntitySetPathSegment entitySetPathSegment = (EntitySetPathSegment)odataPath.Segments.First(); IEdmEntityType edmEntityType = entitySetPathSegment.EntitySetBase.EntityType(); KeyValuePathSegment keyValueSegment = (KeyValuePathSegment)odataPath.Segments[1]; controllerContext.AddKeyValueToRouteData(keyValueSegment, edmEntityType, ODataRouteConstants.Key); } routeData.Values[ODataRouteConstants.NavigationProperty] = navigationSegment.NavigationProperty.Name; KeyValuePathSegment relatedKeySegment = odataPath.Segments.Last(e => e is KeyValuePathSegment) as KeyValuePathSegment; IEdmEntityType navEntityType = navigationProperty.Type.AsCollection().ElementType().AsEntity().EntityDefinition(); controllerContext.AddKeyValueToRouteData(relatedKeySegment, navEntityType, ODataRouteConstants.RelatedKey); return(refActionName); } } return(null); }