public void TryMatchMediaTypeWithBinaryRawValueMatchesRequest_OnODataSingleton() { // Arrange IEdmModel model = GetBinaryModel(); PropertyAccessPathSegment propertySegment = new PropertyAccessPathSegment( (model.GetEdmType(typeof(RawValueEntity)) as IEdmEntityType).FindProperty("BinaryProperty")); ODataPath path = new ODataPath(new SingletonPathSegment("RawSingletonValue"), propertySegment, new ValuePathSegment()); ODataBinaryValueMediaTypeMapping mapping = new ODataBinaryValueMediaTypeMapping(); HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, "http://localhost/RawSingletonValue/BinaryProperty/$value"); request.ODataProperties().Model = model; request.ODataProperties().Path = path; // Act double mapResult = mapping.TryMatchMediaType(request); // Assert Assert.Equal(1.0, mapResult); }
private static string GetRootElementName(ODataPath path) { if (path != null) { ODataPathSegment lastSegment = path.Segments.LastOrDefault(); if (lastSegment != null) { BoundActionPathSegment actionSegment = lastSegment as BoundActionPathSegment; if (actionSegment != null) { return(actionSegment.Action.Name); } PropertyAccessPathSegment propertyAccessSegment = lastSegment as PropertyAccessPathSegment; if (propertyAccessSegment != null) { return(propertyAccessSegment.Property.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); }
private static IEdmProperty GetProperty(ODataPath odataPath, HttpMethod method) { PropertyAccessPathSegment segment = null; if (method == HttpMethod.Get) { if (odataPath.PathTemplate == "~/entityset/key/property" || odataPath.PathTemplate == "~/entityset/key/cast/property" || odataPath.PathTemplate == "~/singleton/property" || odataPath.PathTemplate == "~/singleton/cast/property") { segment = odataPath.Segments[odataPath.Segments.Count - 1] as PropertyAccessPathSegment; } else if (odataPath.PathTemplate == "~/entityset/key/property/$value" || odataPath.PathTemplate == "~/entityset/key/cast/property/$value" || odataPath.PathTemplate == "~/singleton/property/$value" || odataPath.PathTemplate == "~/singleton/cast/property/$value") { segment = odataPath.Segments[odataPath.Segments.Count - 2] as PropertyAccessPathSegment; } } return(segment == null ? null : segment.Property); }
/// <summary> /// This method determines if the <see cref="System.Net.Http.HttpRequestMessage"/> is an OData Raw value request. /// </summary> /// <param name="propertySegment">The <see cref="System.Web.Http.OData.Routing.PropertyAccessPathSegment"/> of the path.</param> /// <returns>True if the request is an OData raw value request.</returns> protected abstract bool IsMatch(PropertyAccessPathSegment propertySegment);
/// <inheritdoc/> protected override bool IsMatch(PropertyAccessPathSegment propertySegment) { return(propertySegment != null && propertySegment.Property.Type.IsPrimitive() && !propertySegment.Property.Type.IsBinary()); }
// 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); } }
private static HttpStatusCode?GetChangedStatusCodeForProperty(PropertyAccessPathSegment propertySegment) { IEdmTypeReference type = propertySegment.Property.Type; return(type.IsPrimitive() || type.IsComplex() ? HttpStatusCode.NoContent : (HttpStatusCode?)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"); } 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); }
private static IEdmProperty GetProperty(ODataPath odataPath, HttpMethod method, out string prefix, out ComplexCastPathSegment cast) { prefix = String.Empty; cast = null; PropertyAccessPathSegment segment = null; if (odataPath.PathTemplate == "~/entityset/key/property" || odataPath.PathTemplate == "~/entityset/key/cast/property" || odataPath.PathTemplate == "~/singleton/property" || odataPath.PathTemplate == "~/singleton/cast/property") { PropertyAccessPathSegment tempSegment = (PropertyAccessPathSegment)odataPath.Segments[odataPath.Segments.Count - 1]; switch (method.Method.ToUpperInvariant()) { case "GET": prefix = "Get"; segment = tempSegment; break; case "PUT": prefix = "PutTo"; segment = tempSegment; break; case "PATCH": // OData Spec: PATCH is not supported for collection properties. if (!tempSegment.Property.Type.IsCollection()) { prefix = "PatchTo"; segment = tempSegment; } break; case "DELETE": // OData spec: A successful DELETE request to the edit URL for a structural property, ... sets the property to null. // The request body is ignored and should be empty. // DELETE request to a non-nullable value MUST fail and the service respond with 400 Bad Request or other appropriate error. if (tempSegment.Property.Type.IsNullable) { prefix = "DeleteTo"; segment = tempSegment; } break; } } else if (odataPath.PathTemplate == "~/entityset/key/property/complexcast" || odataPath.PathTemplate == "~/entityset/key/cast/property/complexcast" || odataPath.PathTemplate == "~/singleton/property/complexcast" || odataPath.PathTemplate == "~/singleton/cast/property/complexcast") { PropertyAccessPathSegment tempSegment = (PropertyAccessPathSegment)odataPath.Segments[odataPath.Segments.Count - 2]; ComplexCastPathSegment tempCast = (ComplexCastPathSegment)odataPath.Segments.Last(); switch (method.Method.ToUpperInvariant()) { case "GET": prefix = "Get"; segment = tempSegment; cast = tempCast; break; case "PUT": prefix = "PutTo"; segment = tempSegment; cast = tempCast; break; case "PATCH": // PATCH is not supported for collection properties. if (!tempSegment.Property.Type.IsCollection()) { prefix = "PatchTo"; segment = tempSegment; cast = tempCast; } break; } } else if (odataPath.PathTemplate == "~/entityset/key/property/$value" || odataPath.PathTemplate == "~/entityset/key/cast/property/$value" || odataPath.PathTemplate == "~/singleton/property/$value" || odataPath.PathTemplate == "~/singleton/cast/property/$value" || odataPath.PathTemplate == "~/entityset/key/property/$count" || odataPath.PathTemplate == "~/entityset/key/cast/property/$count" || odataPath.PathTemplate == "~/singleton/property/$count" || odataPath.PathTemplate == "~/singleton/cast/property/$count") { PropertyAccessPathSegment tempSegment = (PropertyAccessPathSegment)odataPath.Segments[odataPath.Segments.Count - 2]; switch (method.Method.ToUpperInvariant()) { case "GET": prefix = "Get"; segment = tempSegment; break; } } return(segment == null ? null : segment.Property); }
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); }
/// <inheritdoc/> protected override bool IsMatch(PropertyAccessPathSegment propertySegment) { return(propertySegment != null && propertySegment.Property.Type.IsEnum()); }