Пример #1
0
        private static IEnumerable <KeyValuePair <string, object> > ParseETagValue(IList <ResourceProperty> etagProperties, string ifMatchHeaderValue)
        {
            bool flag;

            if (ifMatchHeaderValue == "*")
            {
                return(WebUtil.EmptyKeyValuePairStringObject);
            }
            string      stringToUnescape = ifMatchHeaderValue.Substring("W/\"".Length, (ifMatchHeaderValue.Length - "W/\"".Length) - 1);
            KeyInstance instance         = null;
            Exception   innerException   = null;

            try
            {
                flag = KeyInstance.TryParseNullableTokens(Uri.UnescapeDataString(stringToUnescape), out instance);
            }
            catch (DataServiceException exception2)
            {
                flag           = false;
                innerException = exception2;
            }
            if (!flag)
            {
                throw DataServiceException.CreatePreConditionFailedError(System.Data.Services.Strings.Serializer_ETagValueDoesNotMatch, innerException);
            }
            if (instance.PositionalValues.Count != etagProperties.Count)
            {
                throw DataServiceException.CreatePreConditionFailedError(System.Data.Services.Strings.Serializer_ETagValueDoesNotMatch);
            }
            KeyValuePair <string, object>[] pairArray = new KeyValuePair <string, object> [etagProperties.Count];
            for (int i = 0; i < pairArray.Length; i++)
            {
                ResourceProperty property    = etagProperties[i];
                object           targetValue = null;
                string           text        = (string)instance.PositionalValues[i];
                if (text != "null")
                {
                    try
                    {
                        flag = WebConvert.TryKeyStringToPrimitive(text, property.Type, out targetValue);
                    }
                    catch (OverflowException exception3)
                    {
                        flag           = false;
                        innerException = exception3;
                    }
                    if (!flag)
                    {
                        throw DataServiceException.CreatePreConditionFailedError(System.Data.Services.Strings.Serializer_ETagValueDoesNotMatch, innerException);
                    }
                }
                pairArray[i] = new KeyValuePair <string, object>(etagProperties[i].Name, targetValue);
            }
            return(pairArray);
        }
Пример #2
0
 private void ApplyStandardPaging(string skipToken)
 {
     if (!string.IsNullOrEmpty(skipToken))
     {
         KeyInstance instance;
         if (!this.IsPageSizeDefined)
         {
             throw DataServiceException.CreateBadRequestError(System.Data.Services.Strings.RequestQueryProcessor_SkipTokenSupportedOnPagedSets);
         }
         WebUtil.CheckSyntaxValid(KeyInstance.TryParseNullableTokens(skipToken, out instance));
         if (this.topLevelOrderingInfo.OrderingExpressions.Count != instance.PositionalValues.Count)
         {
             throw DataServiceException.CreateBadRequestError(System.Data.Services.Strings.DataService_SDP_SkipTokenNotMatchingOrdering(instance.PositionalValues.Count, skipToken, this.topLevelOrderingInfo.OrderingExpressions.Count));
         }
         this.queryExpression = this.queryExpression.QueryableWhere(this.orderingParser.BuildSkipTokenFilter(this.topLevelOrderingInfo, instance));
         this.description.VerifyProtocolVersion(RequestDescription.Version2Dot0, this.service);
         this.description.VerifyRequestVersion(RequestDescription.Version2Dot0, this.service);
         this.description.VerifyAndRaiseResponseVersion(RequestDescription.Version2Dot0, this.service);
     }
 }
Пример #3
0
 private void ApplyCustomPaging(string skipToken)
 {
     if (!string.IsNullOrEmpty(skipToken))
     {
         KeyInstance instance;
         WebUtil.CheckSyntaxValid(KeyInstance.TryParseNullableTokens(skipToken, out instance));
         ParameterExpression parameterForIt         = Expression.Parameter(this.description.LastSegmentInfo.TargetResourceType.InstanceType, "it");
         RequestQueryParser.ExpressionParser parser = new RequestQueryParser.ExpressionParser(this.service, this.description, parameterForIt, string.Empty);
         object[] skipTokenValues = new object[instance.PositionalValues.Count];
         int      num             = 0;
         foreach (object obj2 in instance.PositionalValues)
         {
             skipTokenValues[num++] = parser.ParseSkipTokenLiteral((string)obj2);
         }
         this.CheckAndApplyCustomPaging(skipTokenValues);
         this.description.VerifyProtocolVersion(RequestDescription.Version2Dot0, this.service);
         this.description.VerifyRequestVersion(RequestDescription.Version2Dot0, this.service);
     }
     else
     {
         this.CheckAndApplyCustomPaging(null);
     }
 }
Пример #4
0
        /// <summary>Attempts to parse key values from the specified text.</summary>
        /// <param name='text'>Text to parse (not null).</param>
        /// <param name="allowNamedValues">Set to true if the parser should accept named values
        ///   so syntax like Name='value'. If this is false, the parsing will fail on such constructs.</param>
        /// <param name="allowNull">Set to true if the parser should accept null values.
        ///   If set to false, the parser will fail on null values.</param>
        /// <param name='instance'>After invocation, the parsed key instance.</param>
        /// <returns>
        /// true if the key instance was parsed; false if there was a 
        /// syntactic error.
        /// </returns>
        /// <remarks>
        /// The returned instance contains only string values. To get typed values, a call to
        /// <see cref="TryConvertValues"/> is necessary.
        /// </remarks>
        private static bool TryParseFromUri(string text, bool allowNamedValues, bool allowNull, out KeyInstance instance)
        {
            Debug.Assert(text != null, "text != null");

            Dictionary<string, object> namedValues = null;
            List<object> positionalValues = null;

            ExpressionLexer lexer = new ExpressionLexer(text);
            Token currentToken = lexer.CurrentToken;
            if (currentToken.Id == TokenId.End)
            {
                instance = Empty;
                return true;
            }

            instance = null;
            do
            {
                if (currentToken.Id == TokenId.Identifier && allowNamedValues)
                {
                    // Name-value pair.
                    if (positionalValues != null)
                    {
                        // We cannot mix named and non-named values.
                        return false;
                    }

                    string identifier = lexer.CurrentToken.GetIdentifier();
                    lexer.NextToken();
                    if (lexer.CurrentToken.Id != TokenId.Equal)
                    {
                        return false;
                    }

                    lexer.NextToken();
                    if (!lexer.CurrentToken.IsKeyValueToken)
                    {
                        return false;
                    }

                    string namedValue = lexer.CurrentToken.Text;
                    WebUtil.CreateIfNull(ref namedValues);
                    if (namedValues.ContainsKey(identifier))
                    {
                        // Duplicate name.
                        return false;
                    }

                    namedValues.Add(identifier, namedValue);
                }
                else if (currentToken.IsKeyValueToken || (allowNull && currentToken.Id == TokenId.NullLiteral))
                {
                    // Positional value.
                    if (namedValues != null)
                    {
                        // We cannot mix named and non-named values.
                        return false;
                    }

                    WebUtil.CreateIfNull(ref positionalValues);
                    positionalValues.Add(lexer.CurrentToken.Text);
                }
                else
                {
                    return false;
                }

                // Read the next token. We should be at the end, or find
                // we have a comma followed by something.
                lexer.NextToken();
                currentToken = lexer.CurrentToken;
                if (currentToken.Id == TokenId.Comma)
                {
                    lexer.NextToken();
                    currentToken = lexer.CurrentToken;
                    if (currentToken.Id == TokenId.End)
                    {
                        // Trailing comma.
                        return false;
                    }
                }
            }
            while (currentToken.Id != TokenId.End);

            instance = new KeyInstance(namedValues, positionalValues);
            return true;
        }
Пример #5
0
 /// <summary>Attempts to parse nullable values (only positional values, no name-value pairs) from the specified text.</summary>
 /// <param name='text'>Text to parse (not null).</param>
 /// <param name='instance'>After invocation, the parsed key instance.</param>
 /// <returns>
 /// true if the given values were parsed; false if there was a 
 /// syntactic error.
 /// </returns>
 /// <remarks>
 /// The returned instance contains only string values. To get typed values, a call to
 /// <see cref="TryConvertValues"/> is necessary.
 /// </remarks>
 internal static bool TryParseNullableTokens(string text, out KeyInstance instance)
 {
     return TryParseFromUri(text, false /*allowNamedValues*/, true /*allowNull*/, out instance);
 }
Пример #6
0
        /// <summary>
        /// Parse the given etag value in the If-Match request header.
        /// </summary>
        /// <param name="etagProperties">List of etag properties for the type whose etag values we are parsing.</param>
        /// <param name="ifMatchHeaderValue">value of the If-Match header as specified in the request.</param>
        /// <returns>returns the etag value as a list containing the property name and its corresponding value. If the If-Match header value is '*', then returns an empty collection.</returns>
        private static IEnumerable <KeyValuePair <string, object> > ParseETagValue(IList <ResourceProperty> etagProperties, string ifMatchHeaderValue)
        {
            Debug.Assert(etagProperties != null && etagProperties.Count != 0, "There must be atleast one etag property specified");
            Debug.Assert(!String.IsNullOrEmpty(ifMatchHeaderValue), "IfMatch header cannot be null");

            if (ifMatchHeaderValue == XmlConstants.HttpAnyETag)
            {
                // if the value is '*', then we return an empty IEnumerable.
                return(new KeyValuePair <string, object> [0]);
            }

            Debug.Assert(ifMatchHeaderValue.StartsWith(XmlConstants.HttpWeakETagPrefix, StringComparison.Ordinal), "If-Match header must be properly formatted - this check is done in DataService.CheckETagValues method");
            Debug.Assert(ifMatchHeaderValue.Length >= XmlConstants.HttpWeakETagPrefix.Length + 1, "If-Match header must be properly formatted - this check is done in DataService.CheckETagValues method");

            // Just get the etag value - we need to ignore the 'W/"' and the last '"' character from the etag
            string strippedETag = ifMatchHeaderValue.Substring(XmlConstants.HttpWeakETagPrefix.Length, ifMatchHeaderValue.Length - XmlConstants.HttpWeakETagPrefix.Length - 1);

            KeyInstance keyInstance = null;
            bool        success;
            Exception   innerException = null;

            // In V1, when we didn't have IConcurrencyProvider interface, we always used to compute the
            // latest etag from the entity instance we got from IUpdatable.GetResource and then comparing
            // it with the If-Match request header. Hence all invalid cases always used to throw
            // DataServiceException with 412, since the etags didn't match.
            // In V1.5, we have added the support for IConcurrencyProvider, which means we need to parse
            // the etag values and parse it to the provider, if it has implement this interface. To avoid
            // breaking changes, we need to catch all parsing errors and report them as 412 instead of 400
            // to avoid it from becoming a breaking change.
            try
            {
                success = KeyInstance.TryParseNullableTokens(Uri.UnescapeDataString(strippedETag), out keyInstance);
            }
            catch (DataServiceException e)
            {
                success        = false;
                innerException = e;
            }

            if (!success)
            {
                // We could have throwed BadRequest here since the etag value is not properly formattted. But since
                // we used to do throw 412 in V1, keeping it that way to avoid breaking change.
                throw DataServiceException.CreatePreConditionFailedError(Strings.Serializer_ETagValueDoesNotMatch, innerException);
            }

            if (keyInstance.PositionalValues.Count != etagProperties.Count)
            {
                // We could have throwed BadRequest here since the etag value is not properly formattted. But since
                // we used to do throw 412 in V1, keeping it that way to avoid breaking change.
                throw DataServiceException.CreatePreConditionFailedError(Strings.Serializer_ETagValueDoesNotMatch);
            }

            KeyValuePair <string, object>[] etagPropertyInfo = new KeyValuePair <string, object> [etagProperties.Count];
            for (int i = 0; i < etagPropertyInfo.Length; i++)
            {
                ResourceProperty etagProperty  = etagProperties[i];
                object           propertyValue = null;
                string           value         = (string)keyInstance.PositionalValues[i];

                if (value != XmlConstants.NullLiteralInETag)
                {
                    // The reason we need to catch the Overflow Exception here is because of the Bug #679728.
                    // In V1, when we didn't have IConcurrencyProvider interface, we always used to compute the
                    // latest etag from the entity instance we got from IUpdatable.GetResource and then comparing
                    // it with the If-Match request header. Hence all invalid cases always used to throw
                    // DataServiceException with 412, since the etags didn't match.
                    // In V1.5, we have added the support for IConcurrencyProvider, which means we need to parse
                    // the etag values and parse it to the provider, if it has implement this interface. To avoid
                    // breaking changes, we need to catch all parsing errors and report them as 412 instead of 400
                    // to avoid it from becoming a breaking change.
                    try
                    {
                        success = System.Data.Services.Parsing.WebConvert.TryKeyStringToPrimitive(value, etagProperty.Type, out propertyValue);
                    }
                    catch (OverflowException e)
                    {
                        success        = false;
                        innerException = e;
                    }

                    if (!success)
                    {
                        // We could have throwed BadRequest here since the etag value is not properly formattted. But since
                        // we used to do throw 412 in V1, keeping it that way to avoid breaking change.
                        throw DataServiceException.CreatePreConditionFailedError(Strings.Serializer_ETagValueDoesNotMatch, innerException);
                    }
                }

                etagPropertyInfo[i] = new KeyValuePair <string, object>(etagProperties[i].Name, propertyValue);
            }

            return(etagPropertyInfo);
        }
Пример #7
0
 private static Expression SelectResourceByKey(Expression queryExpression, ResourceType resourceType, KeyInstance key)
 {
     for (int i = 0; i < resourceType.KeyProperties.Count; i++)
     {
         Expression expression2;
         ResourceProperty property = resourceType.KeyProperties[i];
         object obj2 = key.AreValuesNamed ? key.NamedValues[property.Name] : key.PositionalValues[i];
         ParameterExpression expression = Expression.Parameter(queryExpression.ElementType(), "element");
         if (property.CanReflectOnInstanceTypeProperty)
         {
             expression2 = Expression.Property(expression, property.Name);
         }
         else
         {
             expression2 = Expression.Convert(Expression.Call(null, DataServiceProviderMethods.GetValueMethodInfo, expression, Expression.Constant(property)), property.Type);
         }
         LambdaExpression predicate = Expression.Lambda(Expression.Equal(expression2, Expression.Constant(obj2)), new ParameterExpression[] { expression });
         queryExpression = queryExpression.QueryableWhere(predicate);
     }
     return queryExpression;
 }
Пример #8
0
        /// <summary>Attempts to parse key values from the specified text.</summary>
        /// <param name='text'>Text to parse (not null).</param>
        /// <param name="allowNamedValues">Set to true if the parser should accept named values
        ///   so syntax like Name='value'. If this is false, the parsing will fail on such constructs.</param>
        /// <param name="allowNull">Set to true if the parser should accept null values.
        ///   If set to false, the parser will fail on null values.</param>
        /// <param name='instance'>After invocation, the parsed key instance.</param>
        /// <returns>
        /// true if the key instance was parsed; false if there was a
        /// syntactic error.
        /// </returns>
        /// <remarks>
        /// The returned instance contains only string values. To get typed values, a call to
        /// <see cref="TryConvertValues"/> is necessary.
        /// </remarks>
        private static bool TryParseFromUri(string text, bool allowNamedValues, bool allowNull, out KeyInstance instance)
        {
            Debug.Assert(text != null, "text != null");

            Dictionary <string, object> namedValues = null;
            List <object> positionalValues          = null;

            ExpressionLexer lexer        = new ExpressionLexer(text);
            Token           currentToken = lexer.CurrentToken;

            if (currentToken.Id == TokenId.End)
            {
                instance = Empty;
                return(true);
            }

            instance = null;
            do
            {
                if (currentToken.Id == TokenId.Identifier && allowNamedValues)
                {
                    // Name-value pair.
                    if (positionalValues != null)
                    {
                        // We cannot mix named and non-named values.
                        return(false);
                    }

                    string identifier = lexer.CurrentToken.GetIdentifier();
                    lexer.NextToken();
                    if (lexer.CurrentToken.Id != TokenId.Equal)
                    {
                        return(false);
                    }

                    lexer.NextToken();
                    if (!lexer.CurrentToken.IsKeyValueToken)
                    {
                        return(false);
                    }

                    string namedValue = lexer.CurrentToken.Text;
                    WebUtil.CreateIfNull(ref namedValues);
                    if (namedValues.ContainsKey(identifier))
                    {
                        // Duplicate name.
                        return(false);
                    }

                    namedValues.Add(identifier, namedValue);
                }
                else if (currentToken.IsKeyValueToken || (allowNull && currentToken.Id == TokenId.NullLiteral))
                {
                    // Positional value.
                    if (namedValues != null)
                    {
                        // We cannot mix named and non-named values.
                        return(false);
                    }

                    WebUtil.CreateIfNull(ref positionalValues);
                    positionalValues.Add(lexer.CurrentToken.Text);
                }
                else
                {
                    return(false);
                }

                // Read the next token. We should be at the end, or find
                // we have a comma followed by something.
                lexer.NextToken();
                currentToken = lexer.CurrentToken;
                if (currentToken.Id == TokenId.Comma)
                {
                    lexer.NextToken();
                    currentToken = lexer.CurrentToken;
                    if (currentToken.Id == TokenId.End)
                    {
                        // Trailing comma.
                        return(false);
                    }
                }
            }while (currentToken.Id != TokenId.End);

            instance = new KeyInstance(namedValues, positionalValues);
            return(true);
        }
Пример #9
0
 /// <summary>Attempts to parse nullable values (only positional values, no name-value pairs) from the specified text.</summary>
 /// <param name='text'>Text to parse (not null).</param>
 /// <param name='instance'>After invocation, the parsed key instance.</param>
 /// <returns>
 /// true if the given values were parsed; false if there was a
 /// syntactic error.
 /// </returns>
 /// <remarks>
 /// The returned instance contains only string values. To get typed values, a call to
 /// <see cref="TryConvertValues"/> is necessary.
 /// </remarks>
 internal static bool TryParseNullableTokens(string text, out KeyInstance instance)
 {
     return(TryParseFromUri(text, false /*allowNamedValues*/, true /*allowNull*/, out instance));
 }
Пример #10
0
        private static bool TryParseFromUri(string text, bool allowNamedValues, bool allowNull, out KeyInstance instance)
        {
            Dictionary <string, object> dictionary = null;
            List <object>   list         = null;
            ExpressionLexer lexer        = new ExpressionLexer(text);
            Token           currentToken = lexer.CurrentToken;

            if (currentToken.Id == TokenId.End)
            {
                instance = Empty;
                return(true);
            }
            instance = null;
            do
            {
                if ((currentToken.Id == TokenId.Identifier) && allowNamedValues)
                {
                    if (list != null)
                    {
                        return(false);
                    }
                    string identifier = lexer.CurrentToken.GetIdentifier();
                    lexer.NextToken();
                    if (lexer.CurrentToken.Id != TokenId.Equal)
                    {
                        return(false);
                    }
                    lexer.NextToken();
                    if (!lexer.CurrentToken.IsKeyValueToken)
                    {
                        return(false);
                    }
                    string str2 = lexer.CurrentToken.Text;
                    WebUtil.CreateIfNull <Dictionary <string, object> >(ref dictionary);
                    if (dictionary.ContainsKey(identifier))
                    {
                        return(false);
                    }
                    dictionary.Add(identifier, str2);
                }
                else
                {
                    if (!currentToken.IsKeyValueToken && (!allowNull || (currentToken.Id != TokenId.NullLiteral)))
                    {
                        return(false);
                    }
                    if (dictionary != null)
                    {
                        return(false);
                    }
                    WebUtil.CreateIfNull <List <object> >(ref list);
                    list.Add(lexer.CurrentToken.Text);
                }
                lexer.NextToken();
                currentToken = lexer.CurrentToken;
                if (currentToken.Id == TokenId.Comma)
                {
                    lexer.NextToken();
                    currentToken = lexer.CurrentToken;
                    if (currentToken.Id == TokenId.End)
                    {
                        return(false);
                    }
                }
            }while (currentToken.Id != TokenId.End);
            instance = new KeyInstance(dictionary, list);
            return(true);
        }
Пример #11
0
 internal static bool TryParseNullableTokens(string text, out KeyInstance instance)
 {
     return(TryParseFromUri(text, false, true, out instance));
 }
Пример #12
0
 internal static bool TryParseKeysFromUri(string text, out KeyInstance instance)
 {
     return(TryParseFromUri(text, true, false, out instance));
 }
Пример #13
0
 private static bool TryParseFromUri(string text, bool allowNamedValues, bool allowNull, out KeyInstance instance)
 {
     Dictionary<string, object> dictionary = null;
     List<object> list = null;
     ExpressionLexer lexer = new ExpressionLexer(text);
     Token currentToken = lexer.CurrentToken;
     if (currentToken.Id == TokenId.End)
     {
         instance = Empty;
         return true;
     }
     instance = null;
     do
     {
         if ((currentToken.Id == TokenId.Identifier) && allowNamedValues)
         {
             if (list != null)
             {
                 return false;
             }
             string identifier = lexer.CurrentToken.GetIdentifier();
             lexer.NextToken();
             if (lexer.CurrentToken.Id != TokenId.Equal)
             {
                 return false;
             }
             lexer.NextToken();
             if (!lexer.CurrentToken.IsKeyValueToken)
             {
                 return false;
             }
             string str2 = lexer.CurrentToken.Text;
             WebUtil.CreateIfNull<Dictionary<string, object>>(ref dictionary);
             if (dictionary.ContainsKey(identifier))
             {
                 return false;
             }
             dictionary.Add(identifier, str2);
         }
         else
         {
             if (!currentToken.IsKeyValueToken && (!allowNull || (currentToken.Id != TokenId.NullLiteral)))
             {
                 return false;
             }
             if (dictionary != null)
             {
                 return false;
             }
             WebUtil.CreateIfNull<List<object>>(ref list);
             list.Add(lexer.CurrentToken.Text);
         }
         lexer.NextToken();
         currentToken = lexer.CurrentToken;
         if (currentToken.Id == TokenId.Comma)
         {
             lexer.NextToken();
             currentToken = lexer.CurrentToken;
             if (currentToken.Id == TokenId.End)
             {
                 return false;
             }
         }
     }
     while (currentToken.Id != TokenId.End);
     instance = new KeyInstance(dictionary, list);
     return true;
 }
Пример #14
0
 internal static bool TryParseNullableTokens(string text, out KeyInstance instance)
 {
     return TryParseFromUri(text, false, true, out instance);
 }
Пример #15
0
 internal static bool TryParseKeysFromUri(string text, out KeyInstance instance)
 {
     return TryParseFromUri(text, true, false, out instance);
 }