/// <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); }
/// <inheritdoc /> public override bool TryTranslate(ODataTemplateTranslateContext context) { context?.Segments.Add(Segment); return(true); }
/// <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);
/// <inheritdoc /> public override ODataPathSegment Translate(ODataTemplateTranslateContext context) { return(CountSegment.Instance); }
/// <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)); }
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)); }
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);
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); }