/// <inheritdoc />
 public override ODataPathSegment Translate(ODataTemplateTranslateContext context)
 {
     // TODO: maybe save the property name.
     // or create the PropertySegment using the information in the context.
     return(Segment);
 }
 /// <inheritdoc />
 public override ODataPathSegment Translate(ODataTemplateTranslateContext context)
 {
     return(Segment);
 }
예제 #3
0
 /// <inheritdoc />
 public override bool TryTranslate(ODataTemplateTranslateContext context)
 {
     context?.Segments.Add(Segment);
     return(true);
 }
예제 #4
0
 /// <inheritdoc />
 public override bool TryTranslate(ODataTemplateTranslateContext context)
 {
     context?.Segments.Add(MetadataSegment.Instance);
     return(true);
 }
        /// <inheritdoc />
        public override bool TryTranslate(ODataTemplateTranslateContext context)
        {
            if (context == null)
            {
                throw Error.ArgumentNull(nameof(context));
            }

            RouteValueDictionary routeValues  = context.RouteValues;
            RouteValueDictionary updateValues = context.UpdatedValues;

            IDictionary <string, object> keysValues = new Dictionary <string, object>();

            foreach (var key in KeyMappings)
            {
                string keyName      = key.Key;
                string templateName = key.Value;
                if (routeValues.TryGetValue(templateName, out object rawValue))
                {
                    IEdmProperty keyProperty = KeyProperties.FirstOrDefault(k => k.Key == keyName).Value;
                    Contract.Assert(keyProperty != null);

                    IEdmTypeReference edmType     = keyProperty.Type;
                    string            strValue    = rawValue as string;
                    string            newStrValue = context.GetParameterAliasOrSelf(strValue);
                    newStrValue = Uri.UnescapeDataString(newStrValue);
                    if (newStrValue != strValue)
                    {
                        updateValues[templateName] = newStrValue;
                        strValue = newStrValue;
                    }

                    // If it's key as segment and the key type is Edm.String, we support non-single quoted string.
                    // Since we can't identify key as segment and key in parenthesis easy so far,
                    // we use the key literal with "/" to test in the whole route template.
                    // Why we can't create two key segment templates, one reason is that in attribute routing template,
                    // we can't identify key as segment or key in parenthesis also.
                    if (edmType.IsString() && context.IsPartOfRouteTemplate($"/{_keyLiteral}"))
                    {
                        if (!strValue.StartsWith('\'') && !strValue.EndsWith('\''))
                        {
                            strValue = $"'{strValue}'"; // prefix and suffix single quote
                        }
                    }

                    object newValue;
                    try
                    {
                        newValue = ODataUriUtils.ConvertFromUriLiteral(strValue, ODataVersion.V4, context.Model, edmType);
                    }
                    catch (ODataException ex)
                    {
                        string message = Error.Format(SRResources.InvalidKeyInUriFound, strValue, edmType.FullName());
                        throw new ODataException(message, ex);
                    }

                    // for non FromODataUri, so update it, for example, remove the single quote for string value.
                    updateValues[templateName] = newValue;

                    // For FromODataUri, let's refactor it later.
                    string prefixName = ODataParameterValue.ParameterValuePrefix + templateName;
                    updateValues[prefixName] = new ODataParameterValue(newValue, edmType);

                    keysValues[keyName] = newValue;
                }
            }

            context.Segments.Add(new KeySegment(keysValues, EntityType, NavigationSource));
            return(true);
        }
 /// <summary>
 /// Translate the template into a real OData path segment <see cref="ODataPathSegment"/>
 /// </summary>
 /// <param name="context">The translate context.</param>
 /// <returns>True if translated. False if no.</returns>
 public abstract bool TryTranslate(ODataTemplateTranslateContext context);
예제 #7
0
 /// <inheritdoc />
 public override ODataPathSegment Translate(ODataTemplateTranslateContext context)
 {
     return(CountSegment.Instance);
 }
예제 #8
0
        /// <inheritdoc />
        public override ODataPathSegment Translate(ODataTemplateTranslateContext context)
        {
            if (context == null)
            {
                throw Error.ArgumentNull(nameof(context));
            }

            RouteValueDictionary routeValue = context.RouteValues;

            // TODO: process the parameter alias
            int skip = Function.IsBound ? 1 : 0;

            //if (!TestParameters(context, out IDictionary<string, string> actualParameters))
            //{
            //    return null;
            //}

            if (!IsAllParameters(routeValue))
            {
                if (!TestParameters(context, out IDictionary <string, string> actualParameters))
                {
                    return(null);
                }

                routeValue = new RouteValueDictionary();
                foreach (var item in context.RouteValues)
                {
                    routeValue.Add(item.Key, item.Value);
                }

                // Replace
                foreach (var item in actualParameters)
                {
                    routeValue[item.Key] = item.Value;
                }
            }

            IList <OperationSegmentParameter> parameters = new List <OperationSegmentParameter>();

            foreach (var parameter in Function.Parameters.Skip(skip))
            {
                if (routeValue.TryGetValue(parameter.Name, out object rawValue))
                {
                    // for resource or collection resource, this method will return "ODataResourceValue, ..." we should support it.
                    if (parameter.Type.IsResourceOrCollectionResource())
                    {
                        // For FromODataUri
                        string prefixName = ODataParameterValue.ParameterValuePrefix + parameter.Name;
                        routeValue[prefixName] = new ODataParameterValue(rawValue, parameter.Type);

                        parameters.Add(new OperationSegmentParameter(parameter.Name, rawValue));
                    }
                    else
                    {
                        string strValue = rawValue as string;
                        object newValue = ODataUriUtils.ConvertFromUriLiteral(strValue, ODataVersion.V4, context.Model, parameter.Type);

                        // for without FromODataUri, so update it, for example, remove the single quote for string value.
                        routeValue[parameter.Name] = newValue;

                        // For FromODataUri
                        string prefixName = ODataParameterValue.ParameterValuePrefix + parameter.Name;
                        routeValue[prefixName] = new ODataParameterValue(newValue, parameter.Type);

                        parameters.Add(new OperationSegmentParameter(parameter.Name, newValue));
                    }
                }
            }

            return(new OperationSegment(Function, parameters, NavigationSource as IEdmEntitySetBase));
        }
예제 #9
0
        private static DynamicPathSegment CreateDynamicSegment(ODataPathSegment previous, ODataTemplateTranslateContext context)
        {
            if (previous == null)
            {
                return(null);
            }

            IEdmStructuredType previousEdmType = previous.EdmType as IEdmStructuredType;

            if (previousEdmType == null || !previousEdmType.IsOpen)
            {
                return(null);
            }

            if (!context.RouteValues.TryGetValue("dynamicproperty", out object value))
            {
                return(null);
            }

            string       propertyName = value as string;
            IEdmProperty edmProperty  = previousEdmType.ResolveProperty(propertyName);

            if (edmProperty != null)
            {
                return(null);
            }

            return(new DynamicPathSegment(propertyName));
        }
예제 #10
0
        private static ODataPathSegment CreatePropertySegment(ODataPathSegment previous, ODataTemplateTranslateContext context)
        {
            if (previous == null)
            {
                return(null);
            }

            IEdmStructuredType previousEdmType = previous.EdmType as IEdmStructuredType;

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

            if (!context.RouteValues.TryGetValue("property", out object value))
            {
                return(null);
            }

            string                 propertyName       = value as string;
            IEdmProperty           edmProperty        = previousEdmType.ResolveProperty(propertyName);
            IEdmStructuralProperty structuralProperty = edmProperty as IEdmStructuralProperty;

            if (structuralProperty != null)
            {
                return(new PropertySegment(structuralProperty));
            }

            IEdmNavigationProperty navProperty = edmProperty as IEdmNavigationProperty;

            if (navProperty != null)
            {
                // TODO: shall we calculate the navigation source for navigation segment?
                return(new NavigationPropertySegment(navProperty, null));
            }

            return(null);
        }
        /// <summary>
        /// Match the function parameter
        /// </summary>
        /// <param name="context">The context.</param>
        /// <param name="function">The Edm function.</param>
        /// <param name="parameterMappings">The parameter mapping.</param>
        /// <returns></returns>
        public static IList <OperationSegmentParameter> Match(ODataTemplateTranslateContext context,
                                                              IEdmFunction function,
                                                              IDictionary <string, string> parameterMappings)
        {
            Contract.Assert(context != null);
            Contract.Assert(function != null);
            Contract.Assert(parameterMappings != null);

            RouteValueDictionary routeValues   = context.RouteValues;
            RouteValueDictionary updatedValues = context.UpdatedValues;

            IList <OperationSegmentParameter> parameters = new List <OperationSegmentParameter>();

            foreach (var parameter in parameterMappings)
            {
                string parameterName = parameter.Key;
                string parameterTemp = parameter.Value;

                IEdmOperationParameter edmParameter = function.Parameters.FirstOrDefault(p => p.Name == parameterName);
                Contract.Assert(edmParameter != null);

                // For a parameter mapping like: minSalary={min}
                // and a request like: ~/MyFunction(minSalary=2)
                // the routeValue includes the [min=2], so we should use the mapping name to retrieve the value.
                if (routeValues.TryGetValue(parameterTemp, out object rawValue))
                {
                    string strValue    = rawValue as string;
                    string newStrValue = context.GetParameterAliasOrSelf(strValue);
                    if (newStrValue != strValue)
                    {
                        updatedValues[parameterTemp] = newStrValue;
                        strValue = newStrValue;
                    }

                    string originalStrValue = strValue;

                    // for resource or collection resource, this method will return "ODataResourceValue, ..." we should support it.
                    if (edmParameter.Type.IsResourceOrCollectionResource())
                    {
                        // For FromODataUri
                        string prefixName = ODataParameterValue.ParameterValuePrefix + parameterTemp;
                        updatedValues[prefixName] = new ODataParameterValue(strValue, edmParameter.Type);

                        parameters.Add(new OperationSegmentParameter(parameterName, strValue));
                    }
                    else
                    {
                        if (edmParameter.Type.IsEnum() && strValue.StartsWith("'", StringComparison.Ordinal) && strValue.EndsWith("'", StringComparison.Ordinal))
                        {
                            // related implementation at: https://github.com/OData/odata.net/blob/master/src/Microsoft.OData.Core/UriParser/Resolver/StringAsEnumResolver.cs#L131
                            strValue = edmParameter.Type.FullName() + strValue;
                        }

                        object newValue;
                        try
                        {
                            newValue = ODataUriUtils.ConvertFromUriLiteral(strValue, ODataVersion.V4, context.Model, edmParameter.Type);
                        }
                        catch (ODataException ex)
                        {
                            string message = Error.Format(SRResources.InvalidParameterValueInUriFound, originalStrValue, edmParameter.Type.FullName());
                            throw new ODataException(message, ex);
                        }

                        // for without FromODataUri, so update it, for example, remove the single quote for string value.
                        updatedValues[parameterTemp] = newValue;

                        // For FromODataUri
                        string prefixName = ODataParameterValue.ParameterValuePrefix + parameterTemp;
                        updatedValues[prefixName] = new ODataParameterValue(newValue, edmParameter.Type);

                        parameters.Add(new OperationSegmentParameter(parameterName, newValue));
                    }
                }
                else
                {
                    return(null);
                }
            }

            return(parameters);
        }
 /// <summary>
 /// Translate the template into a real OData path segment, <see cref="ODataPathSegment"/>
 /// </summary>
 /// <param name="context">The translate context.</param>
 /// <returns>null or ODataPathSegment.</returns>
 public abstract ODataPathSegment Translate(ODataTemplateTranslateContext context);
예제 #13
0
        public static IList <OperationSegmentParameter> Match(ODataTemplateTranslateContext context, IEdmFunction function,
                                                              IDictionary <string, string> parameterMappings)
        {
            Contract.Assert(context != null);
            Contract.Assert(function != null);
            Contract.Assert(parameterMappings != null);

            RouteValueDictionary routeValues = context.UpdatedValues;

            IList <OperationSegmentParameter> parameters = new List <OperationSegmentParameter>();

            foreach (var parameter in parameterMappings)
            {
                string parameterName = parameter.Key;
                string parameterTemp = parameter.Value;

                IEdmOperationParameter edmParameter = function.Parameters.FirstOrDefault(p => p.Name == parameterName);
                Contract.Assert(edmParameter != null);

                // For a parameter mapping like: minSalary={min}
                // and a request like: ~/MyFunction(minSalary=2)
                // the routeValue includes the [min=2], so we should use the mapping name to retrieve the value.
                if (routeValues.TryGetValue(parameterTemp, out object rawValue))
                {
                    string strValue    = rawValue as string;
                    string newStrValue = context.GetParameterAliasOrSelf(strValue);
                    if (newStrValue != strValue)
                    {
                        routeValues[parameterTemp] = newStrValue;
                        strValue = newStrValue;
                    }

                    // for resource or collection resource, this method will return "ODataResourceValue, ..." we should support it.
                    if (edmParameter.Type.IsResourceOrCollectionResource())
                    {
                        // For FromODataUri
                        string prefixName = ODataParameterValue.ParameterValuePrefix + parameterTemp;
                        routeValues[prefixName] = new ODataParameterValue(strValue, edmParameter.Type);

                        parameters.Add(new OperationSegmentParameter(parameterName, strValue));
                    }
                    else
                    {
                        object newValue = ODataUriUtils.ConvertFromUriLiteral(strValue, ODataVersion.V4, context.Model, edmParameter.Type);

                        // for without FromODataUri, so update it, for example, remove the single quote for string value.
                        routeValues[parameterTemp] = newValue;

                        // For FromODataUri
                        string prefixName = ODataParameterValue.ParameterValuePrefix + parameterTemp;
                        routeValues[prefixName] = new ODataParameterValue(newValue, edmParameter.Type);

                        parameters.Add(new OperationSegmentParameter(parameterName, newValue));
                    }
                }
                else
                {
                    return(null);
                }
            }

            return(parameters);
        }