/// <summary> /// Converts a <see cref="UriOperationParameter"/> value to an escaped string for use in a Uri. Wraps the call to ODL's ConvertToUriLiteral and escapes the results. /// </summary> /// <param name="paramName">The name of the <see cref="UriOperationParameter"/>. Used for error reporting.</param> /// <param name="value">The value of the <see cref="UriOperationParameter"/>.</param> /// <param name="useEntityReference">If true, use entity reference, instead of entity to serialize the parameter.</param> /// <returns>A string representation of <paramref name="value"/> for use in a Url.</returns> private string ConvertToEscapedUriValue(string paramName, object value, bool useEntityReference = false) { Debug.Assert(!string.IsNullOrEmpty(paramName), "!string.IsNullOrEmpty(paramName)"); // Literal values with single quotes need special escaping due to System.Uri changes in behavior between .NET 4.0 and 4.5. // We need to ensure that our escaped values do not change between those versions, so we need to escape values differently when they could contain single quotes. bool needsSpecialEscaping = false; object valueInODataFormat = ConvertToODataValue(paramName, value, ref needsSpecialEscaping, useEntityReference); // When calling Execute() to invoke an Action, the client doesn't support parsing the target url // to determine which IEdmOperationImport to pass to the ODL writer. So the ODL writer is // serializing the parameter payload without metadata. Setting the model to null so ODL doesn't // do unnecessary validations when writing without metadata. bool isIeee754Compatible = this.requestInfo.IsIeee754Compatible; string literal = ODataUriUtils.ConvertToUriLiteral(valueInODataFormat, CommonUtil.ConvertToODataVersion(this.requestInfo.MaxProtocolVersionAsVersion), null /* edmModel */, isIeee754Compatible); // The value from ConvertToUriValue will not be escaped, but will already contain literal delimiters like single quotes, so we // need to use our own escape method that will preserve those characters instead of directly calling Uri.EscapeDataString that may escape them. // This is only necessary for primitives and nulls because the other structures are serialized using the JSON format and it uses double quotes // which have always been escaped. if (needsSpecialEscaping) { return(DataStringEscapeBuilder.EscapeDataString(literal)); } return(Uri.EscapeDataString(literal)); }
public void ShouldEscapeString() { Assert.AreEqual("'a%2520bc' eq%20'a%20bc'", DataStringEscapeBuilder.EscapeDataString("'a%20bc' eq%20'a bc'")); Assert.AreEqual("\"a%2520bc\" eq%20\"a%20bc\"", DataStringEscapeBuilder.EscapeDataString("\"a%20bc\" eq%20\"a bc\"")); }
public void ShouldNotEscapeNonString() { Assert.AreEqual("'abc' eq%20'abc'", DataStringEscapeBuilder.EscapeDataString("'abc' eq%20'abc'")); }
public void AlwaysEscapePlus() { // '+' should always be escaped, regardless of inside or outside of string Assert.AreEqual("'%2B' %2B", DataStringEscapeBuilder.EscapeDataString("'+' +")); }
public void DoubleSingleMix() { Assert.AreEqual("\"f'o'o\"", DataStringEscapeBuilder.EscapeDataString("\"f'o'o\"")); Assert.AreEqual("'f%22o%22o'", DataStringEscapeBuilder.EscapeDataString("'f\"o\"o'")); Assert.AreEqual("'f%22o'\"o'\"", DataStringEscapeBuilder.EscapeDataString("'f\"o'\"o'\"")); }