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);
        }
예제 #2
0
        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);
        }
예제 #4
0
        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);
        }
예제 #10
0
        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);
        }
예제 #11
0
        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());
 }