PageRenderTime 63ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 0ms

/test/System.Net.Http.Formatting.Test.Integration/FormUrlEncodedFromUriQueryTests.cs

https://bitbucket.org/mdavid/aspnetwebstack
C# | 503 lines | 451 code | 27 blank | 25 comment | 1 complexity | e515f14fbfec150e9101ee12ce298918 MD5 | raw file
  1. using System.Collections.Generic;
  2. using System.Json;
  3. using System.Net.Http.Internal;
  4. using System.Text;
  5. using Newtonsoft.Json.Linq;
  6. using Xunit;
  7. using Xunit.Extensions;
  8. namespace System.Net.Http.Formatting
  9. {
  10. public class FormUrlEncodedJsonFromUriQueryTests
  11. {
  12. #region Tests
  13. [Theory,
  14. InlineData("abc", "{\"abc\":\"\"}"),
  15. InlineData("%2eabc%2e", "{\".abc.\":\"\"}"),
  16. InlineData("", "{}"),
  17. InlineData("a=1", "{\"a\":\"1\"}")]
  18. public void SimpleStringsTest(string encoded, string expectedResult)
  19. {
  20. ValidateFormUrlEncoded(encoded, expectedResult);
  21. }
  22. [Theory,
  23. InlineData("a=2", "{\"a\":\"2\"}"),
  24. InlineData("b=true", "{\"b\":\"true\"}"),
  25. InlineData("c=hello", "{\"c\":\"hello\"}"),
  26. InlineData("d=", "{\"d\":\"\"}"),
  27. InlineData("e=null", "{\"e\":\"null\"}")]
  28. public void SimpleObjectsTest(string encoded, string expectedResult)
  29. {
  30. ValidateFormUrlEncoded(encoded, expectedResult);
  31. }
  32. [Fact]
  33. public void LegacyArraysTest()
  34. {
  35. ValidateFormUrlEncoded("a=1&a=hello&a=333", "{\"a\":[\"1\",\"hello\",\"333\"]}");
  36. // Only valid in shallow serialization
  37. ParseInvalidFormUrlEncoded("a[z]=2&a[z]=3");
  38. }
  39. [Theory,
  40. InlineData("a[]=1&a[]=hello&a[]=333", "{\"a\":[\"1\",\"hello\",\"333\"]}"),
  41. InlineData("a[b][]=1&a[b][]=hello&a[b][]=333", "{\"a\":{\"b\":[\"1\",\"hello\",\"333\"]}}"),
  42. InlineData("a[]=", "{\"a\":[\"\"]}"),
  43. InlineData("a%5B%5D=2", @"{""a"":[""2""]}"),
  44. InlineData("a[x][0]=1&a[x][]=2", @"{""a"":{""x"":[""1"",""2""]}}")]
  45. public void ArraysTest(string encoded, string expectedResult)
  46. {
  47. ValidateFormUrlEncoded(encoded, expectedResult);
  48. }
  49. [Theory,
  50. InlineData("a[0][]=1&a[0][]=hello&a[1][]=333", "{\"a\":[[\"1\",\"hello\"],[\"333\"]]}"),
  51. InlineData("a[b][0][]=1&a[b][1][]=hello&a[b][1][]=333", "{\"a\":{\"b\":[[\"1\"],[\"hello\",\"333\"]]}}"),
  52. InlineData("a[0][0][0][]=1", "{\"a\":[[[[\"1\"]]]]}")]
  53. public void MultidimensionalArraysTest(string encoded, string expectedResult)
  54. {
  55. ValidateFormUrlEncoded(encoded, expectedResult);
  56. }
  57. [Theory,
  58. InlineData("a[0][]=hello&a[2][]=333", "{\"a\":{\"0\":[\"hello\"],\"2\":[\"333\"]}}"),
  59. InlineData("a[0]=hello", "{\"a\":[\"hello\"]}"),
  60. InlineData("a[1][]=hello", "{\"a\":{\"1\":[\"hello\"]}}"),
  61. InlineData("a[1][0]=hello", "{\"a\":{\"1\":[\"hello\"]}}")]
  62. public void SparseArraysTest(string encoded, string expectedResult)
  63. {
  64. ValidateFormUrlEncoded(encoded, expectedResult);
  65. }
  66. [Theory,
  67. InlineData("b[]=2&b[1][c]=d", "{\"b\":[\"2\",{\"c\":\"d\"}]}")]
  68. public void ArraysWithMixedMembers(string encoded, string expectedResult)
  69. {
  70. ValidateFormUrlEncoded(encoded, expectedResult);
  71. }
  72. [Theory,
  73. InlineData("=3", "{\"\":\"3\"}"),
  74. InlineData("a=1&=3", "{\"a\":\"1\",\"\":\"3\"}"),
  75. InlineData("=3&b=2", "{\"\":\"3\",\"b\":\"2\"}")]
  76. public void EmptyKeyTest(string encoded, string expectedResult)
  77. {
  78. ValidateFormUrlEncoded(encoded, expectedResult);
  79. }
  80. [Theory,
  81. InlineData("a[b]=1&a=2"),
  82. InlineData("a[b]=1&a[b][]=2"),
  83. InlineData("a[x][]=1&a[x][0]=2"),
  84. InlineData("a=2&a[b]=1"),
  85. InlineData("[]=1"),
  86. InlineData("a[][]=0"),
  87. InlineData("a[][x]=0"),
  88. InlineData("a&a[b]=1")]
  89. public void InvalidObjectGraphsTest(string encoded)
  90. {
  91. ParseInvalidFormUrlEncoded(encoded);
  92. }
  93. [Theory,
  94. InlineData("a[b=2"),
  95. InlineData("a[[b]=2"),
  96. InlineData("a[b]]=2")]
  97. public void InvalidFormUrlEncodingTest(string encoded)
  98. {
  99. ParseInvalidFormUrlEncoded(encoded);
  100. }
  101. /// <summary>
  102. /// Tests for parsing form-urlencoded data originated from JS primitives.
  103. /// </summary>
  104. [Theory,
  105. InlineData("abc", @"{""abc"":""""}"),
  106. InlineData("123", @"{""123"":""""}"),
  107. InlineData("true", @"{""true"":""""}"),
  108. InlineData("", "{}"),
  109. InlineData("%2fabc%2f", @"{""/abc/"":""""}")]
  110. public void TestJValue(string encoded, string expectedResult)
  111. {
  112. ValidateFormUrlEncoded(encoded, expectedResult);
  113. }
  114. /// <summary>
  115. /// Negative tests for parsing form-urlencoded data originated from JS primitives.
  116. /// </summary>
  117. [Theory,
  118. InlineData("a[b]=1&a=2"),
  119. InlineData("a=2&a[b]=1"),
  120. InlineData("[]=1")]
  121. public void TestJValueNegative(string encoded)
  122. {
  123. ParseInvalidFormUrlEncoded(encoded);
  124. }
  125. /// <summary>
  126. /// Tests for parsing form-urlencoded data originated from JS objects.
  127. /// </summary>
  128. [Theory,
  129. InlineData("a=NaN", @"{""a"":""NaN""}"),
  130. InlineData("a=false", @"{""a"":""false""}"),
  131. InlineData("a=foo", @"{""a"":""foo""}"),
  132. InlineData("1=1", "{\"1\":\"1\"}")]
  133. public void TestObjects(string encoded, string expectedResult)
  134. {
  135. ValidateFormUrlEncoded(encoded, expectedResult);
  136. }
  137. /// <summary>
  138. /// Tests for parsing form-urlencoded data originated from JS arrays.
  139. /// </summary>
  140. [Theory,
  141. InlineData("a[]=2", @"{""a"":[""2""]}"),
  142. InlineData("a[]=", @"{""a"":[""""]}"),
  143. InlineData("a[0][0][]=1", @"{""a"":[[[""1""]]]}"),
  144. InlineData("z[]=9&z[]=true&z[]=undefined&z[]=", @"{""z"":[""9"",""true"",""undefined"",""""]}"),
  145. InlineData("z[]=9&z[]=true&z[]=undefined&z[]=null", @"{""z"":[""9"",""true"",""undefined"",""null""]}"),
  146. InlineData("z[0][]=9&z[0][]=true&z[1][]=undefined&z[1][]=null", @"{""z"":[[""9"",""true""],[""undefined"",""null""]]}"),
  147. InlineData("a[0][x]=2", @"{""a"":[{""x"":""2""}]}"),
  148. InlineData("a%5B%5D=2", @"{""a"":[""2""]}"),
  149. InlineData("a%5B%5D=", @"{""a"":[""""]}"),
  150. InlineData("z%5B%5D=9&z%5B%5D=true&z%5B%5D=undefined&z%5B%5D=", @"{""z"":[""9"",""true"",""undefined"",""""]}"),
  151. InlineData("z%5B%5D=9&z%5B%5D=true&z%5B%5D=undefined&z%5B%5D=null", @"{""z"":[""9"",""true"",""undefined"",""null""]}"),
  152. InlineData("z%5B0%5D%5B%5D=9&z%5B0%5D%5B%5D=true&z%5B1%5D%5B%5D=undefined&z%5B1%5D%5B%5D=null", @"{""z"":[[""9"",""true""],[""undefined"",""null""]]}")]
  153. public void TestArray(string encoded, string expectedResult)
  154. {
  155. ValidateFormUrlEncoded(encoded, expectedResult);
  156. }
  157. /// <summary>
  158. /// Tests for parsing form-urlencoded data originated from JS arrays, using the jQuery 1.3 format (no []'s).
  159. /// </summary>
  160. [Theory,
  161. InlineData("z=9&z=true&z=undefined&z=", @"{""z"":[""9"",""true"",""undefined"",""""]}"),
  162. InlineData("z=9&z=true&z=undefined&z=null", @"{""z"":[""9"",""true"",""undefined"",""null""]}"),
  163. InlineData("z=9&z=true&z=undefined&z=null&a=hello", @"{""z"":[""9"",""true"",""undefined"",""null""],""a"":""hello""}")]
  164. public void TestArrayCompat(string encoded, string expectedResult)
  165. {
  166. ValidateFormUrlEncoded(encoded, expectedResult);
  167. }
  168. /// <summary>
  169. /// Negative tests for parsing form-urlencoded data originated from JS arrays.
  170. /// </summary>
  171. [Theory,
  172. InlineData("a[z]=2&a[z]=3")]
  173. public void TestArrayCompatNegative(string encoded)
  174. {
  175. ParseInvalidFormUrlEncoded(encoded);
  176. }
  177. /// <summary>
  178. /// Tests for form-urlencoded data originated from sparse JS arrays.
  179. /// </summary>
  180. [Theory,
  181. InlineData("a[2]=hello", @"{""a"":{""2"":""hello""}}"),
  182. InlineData("a[x][0]=2", @"{""a"":{""x"":[""2""]}}"),
  183. InlineData("a[x][1]=2", @"{""a"":{""x"":{""1"":""2""}}}"),
  184. InlineData("a[x][0]=0&a[x][1]=1", @"{""a"":{""x"":[""0"",""1""]}}"),
  185. InlineData("a[0][0][0]=hello&a[1][0][0][0][]=hello", @"{""a"":[[[""hello""]],[[[[""hello""]]]]]}"),
  186. InlineData("a[0][0][0]=hello&a[1][0][0][0]=hello", @"{""a"":[[[""hello""]],[[[""hello""]]]]}"),
  187. InlineData("a[1][0][]=1", @"{""a"":{""1"":[[""1""]]}}"),
  188. InlineData("a[1][1][]=1", @"{""a"":{""1"":{""1"":[""1""]}}}"),
  189. InlineData("a[1][1][0]=1", @"{""a"":{""1"":{""1"":[""1""]}}}"),
  190. InlineData("a[0][]=2&a[0][]=3&a[2][]=1", "{\"a\":{\"0\":[\"2\",\"3\"],\"2\":[\"1\"]}}"),
  191. InlineData("a[x][]=1&a[x][1]=2", @"{""a"":{""x"":[""1"",""2""]}}"),
  192. InlineData("a[x][0]=1&a[x][]=2", @"{""a"":{""x"":[""1"",""2""]}}")]
  193. public void TestArraySparse(string encoded, string expectedResult)
  194. {
  195. ValidateFormUrlEncoded(encoded, expectedResult);
  196. }
  197. /// <summary>
  198. /// Negative tests for parsing form-urlencoded arrays.
  199. /// </summary>
  200. [Theory,
  201. InlineData("a[x]=2&a[x][]=3"),
  202. InlineData("a[]=1&a[0][]=2"),
  203. InlineData("a[]=1&a[0][0][]=2"),
  204. InlineData("a[x][]=1&a[x][0]=2"),
  205. InlineData("a[][]=0"),
  206. InlineData("a[][x]=0")]
  207. public void TestArrayIndexNegative(string encoded)
  208. {
  209. ParseInvalidFormUrlEncoded(encoded);
  210. }
  211. public static IEnumerable<object[]> TestObjectPropertyData
  212. {
  213. get
  214. {
  215. string encoded = "a[]=4&a[]=5&b[x][]=7&b[y]=8&b[z][]=9&b[z][]=true&b[z][]=undefined&b[z][]=&c=1&f=";
  216. string resultStr = @"{""a"":[""4"",""5""],""b"":{""x"":[""7""],""y"":""8"",""z"":[""9"",""true"",""undefined"",""""]},""c"":""1"",""f"":""""}";
  217. yield return new[] { encoded, resultStr };
  218. encoded = "customer[Name]=Pete&customer[Address]=Redmond&customer[Age][0][]=23&customer[Age][0][]=24&customer[Age][1][]=25&" +
  219. "customer[Age][1][]=26&customer[Phones][]=425+888+1111&customer[Phones][]=425+345+7777&customer[Phones][]=425+888+4564&" +
  220. "customer[EnrolmentDate]=%22%5C%2FDate(1276562539537)%5C%2F%22&role=NewRole&changeDate=3&count=15";
  221. resultStr = @"{""customer"":{""Name"":""Pete"",""Address"":""Redmond"",""Age"":[[""23"",""24""],[""25"",""26""]]," +
  222. @"""Phones"":[""425 888 1111"",""425 345 7777"",""425 888 4564""],""EnrolmentDate"":""\""\\/Date(1276562539537)\\/\""""},""role"":""NewRole"",""changeDate"":""3"",""count"":""15""}";
  223. yield return new[] { encoded, resultStr };
  224. encoded = "customers[0][Name]=Pete2&customers[0][Address]=Redmond2&customers[0][Age][0][]=23&customers[0][Age][0][]=24&" +
  225. "customers[0][Age][1][]=25&customers[0][Age][1][]=26&customers[0][Phones][]=425+888+1111&customers[0][Phones][]=425+345+7777&" +
  226. "customers[0][Phones][]=425+888+4564&customers[0][EnrolmentDate]=%22%5C%2FDate(1276634840700)%5C%2F%22&customers[1][Name]=Pete3&" +
  227. "customers[1][Address]=Redmond3&customers[1][Age][0][]=23&customers[1][Age][0][]=24&customers[1][Age][1][]=25&customers[1][Age][1][]=26&" +
  228. "customers[1][Phones][]=425+888+1111&customers[1][Phones][]=425+345+7777&customers[1][Phones][]=425+888+4564&customers[1][EnrolmentDate]=%22%5C%2FDate(1276634840700)%5C%2F%22";
  229. resultStr = @"{""customers"":[{""Name"":""Pete2"",""Address"":""Redmond2"",""Age"":[[""23"",""24""],[""25"",""26""]]," +
  230. @"""Phones"":[""425 888 1111"",""425 345 7777"",""425 888 4564""],""EnrolmentDate"":""\""\\/Date(1276634840700)\\/\""""}," +
  231. @"{""Name"":""Pete3"",""Address"":""Redmond3"",""Age"":[[""23"",""24""],[""25"",""26""]],""Phones"":[""425 888 1111"",""425 345 7777"",""425 888 4564""],""EnrolmentDate"":""\""\\/Date(1276634840700)\\/\""""}]}";
  232. yield return new[] { encoded, resultStr };
  233. encoded = "ab%5B%5D=hello";
  234. resultStr = @"{""ab"":[""hello""]}";
  235. yield return new[] { encoded, resultStr };
  236. encoded = "123=hello";
  237. resultStr = @"{""123"":""hello""}";
  238. yield return new[] { encoded, resultStr };
  239. encoded = "a%5B%5D=1&a";
  240. resultStr = @"{""a"":[""1"",""""]}";
  241. yield return new[] { encoded, resultStr };
  242. encoded = "a=1&a";
  243. resultStr = @"{""a"":[""1"",""""]}";
  244. yield return new[] { encoded, resultStr };
  245. }
  246. }
  247. /// <summary>
  248. /// Tests for parsing complex object graphs form-urlencoded.
  249. /// </summary>
  250. [Theory]
  251. [PropertyData("TestObjectPropertyData")]
  252. public void TestObject(string encoded, string expectedResult)
  253. {
  254. ValidateFormUrlEncoded(encoded, expectedResult);
  255. }
  256. public static IEnumerable<object[]> TestEncodedNameTestData
  257. {
  258. get
  259. {
  260. string encoded = "some+thing=10";
  261. string resultStr = @"{""some thing"":""10""}";
  262. yield return new[] { encoded, resultStr };
  263. encoded = "%E5%B8%A6%E4%B8%89%E4%B8%AA%E8%A1%A8=bar";
  264. resultStr = @"{""带三个表"":""bar""}";
  265. yield return new[] { encoded, resultStr };
  266. encoded = "some+thing=10&%E5%B8%A6%E4%B8%89%E4%B8%AA%E8%A1%A8=bar";
  267. resultStr = @"{""some thing"":""10"",""带三个表"":""bar""}";
  268. yield return new[] { encoded, resultStr };
  269. encoded = "a[0\r\n][b]=1";
  270. resultStr = "{\"a\":{\"0\\r\\n\":{\"b\":\"1\"}}}";
  271. yield return new[] { encoded, resultStr };
  272. yield return new[] { encoded.Replace("\r", "%0D").Replace("\n", "%0A"), resultStr };
  273. yield return new[] { "a[0\0]=1", "{\"a\":{\"0\\u0000\":\"1\"}}" };
  274. yield return new[] { "a[0%00]=1", "{\"a\":{\"0\\u0000\":\"1\"}}" };
  275. yield return new[] { "a[\00]=1", "{\"a\":{\"\\u00000\":\"1\"}}" };
  276. yield return new[] { "a[%000]=1", "{\"a\":{\"\\u00000\":\"1\"}}" };
  277. }
  278. }
  279. /// <summary>
  280. /// Tests for parsing form-urlencoded data with encoded names.
  281. /// </summary>
  282. [Theory]
  283. [PropertyData("TestEncodedNameTestData")]
  284. public void TestEncodedName(string encoded, string expectedResult)
  285. {
  286. ValidateFormUrlEncoded(encoded, expectedResult);
  287. }
  288. /// <summary>
  289. /// Tests for malformed form-urlencoded data.
  290. /// </summary>
  291. [Theory,
  292. InlineData("a[b=2"),
  293. InlineData("a[[b]=2"),
  294. InlineData("a[b]]=2")]
  295. public void TestNegative(string encoded)
  296. {
  297. ParseInvalidFormUrlEncoded(encoded);
  298. }
  299. /// <summary>
  300. /// Tests for parsing generated form-urlencoded data.
  301. /// </summary>
  302. [Fact]
  303. public void GeneratedJTokenTest()
  304. {
  305. Random rndGen = new Random(1);
  306. int oldMaxArray = CreatorSettings.MaxArrayLength;
  307. int oldMaxList = CreatorSettings.MaxListLength;
  308. int oldMaxStr = CreatorSettings.MaxStringLength;
  309. double oldNullProbability = CreatorSettings.NullValueProbability;
  310. bool oldCreateAscii = CreatorSettings.CreateOnlyAsciiChars;
  311. CreatorSettings.MaxArrayLength = 5;
  312. CreatorSettings.MaxListLength = 3;
  313. CreatorSettings.MaxStringLength = 3;
  314. CreatorSettings.NullValueProbability = 0;
  315. CreatorSettings.CreateOnlyAsciiChars = true;
  316. JTokenCreatorSurrogate jsonValueCreator = new JTokenCreatorSurrogate();
  317. try
  318. {
  319. for (int i = 0; i < 1000; i++)
  320. {
  321. JToken jv = (JToken)jsonValueCreator.CreateInstanceOf(typeof(JToken), rndGen);
  322. if (jv.Type == JTokenType.Array || jv.Type == JTokenType.Object)
  323. {
  324. string jaStr = FormUrlEncoding(jv);
  325. JToken deserJv = ParseFormUrlEncoded(jaStr);
  326. bool compare = true;
  327. if (deserJv is JObject && ((IDictionary<string, JToken>)deserJv).ContainsKey("JV"))
  328. {
  329. compare = JTokenRoundTripComparer.Compare(jv, deserJv["JV"]);
  330. }
  331. else
  332. {
  333. compare = JTokenRoundTripComparer.Compare(jv, deserJv);
  334. }
  335. Assert.True(compare, "Comparison failed for test instance " + i);
  336. }
  337. }
  338. }
  339. finally
  340. {
  341. CreatorSettings.MaxArrayLength = oldMaxArray;
  342. CreatorSettings.MaxListLength = oldMaxList;
  343. CreatorSettings.MaxStringLength = oldMaxStr;
  344. CreatorSettings.NullValueProbability = oldNullProbability;
  345. CreatorSettings.CreateOnlyAsciiChars = oldCreateAscii;
  346. }
  347. }
  348. #endregion
  349. #region Helpers
  350. private static string FormUrlEncoding(JToken jsonValue)
  351. {
  352. List<string> results = new List<string>();
  353. if (jsonValue is JValue)
  354. {
  355. return UriQueryUtility.UrlEncode(((JValue)jsonValue).Value.ToString());
  356. }
  357. BuildParams("JV", jsonValue, results);
  358. StringBuilder strResult = new StringBuilder();
  359. foreach (var result in results)
  360. {
  361. strResult.Append("&" + result);
  362. }
  363. if (strResult.Length > 0)
  364. {
  365. return strResult.Remove(0, 1).ToString();
  366. }
  367. return strResult.ToString();
  368. }
  369. private static void BuildParams(string prefix, JToken jsonValue, List<string> results)
  370. {
  371. if (jsonValue is JValue)
  372. {
  373. JValue jsonPrimitive = jsonValue as JValue;
  374. if (jsonPrimitive != null)
  375. {
  376. if (jsonPrimitive.Type == JTokenType.String && String.IsNullOrEmpty(jsonPrimitive.Value.ToString()))
  377. {
  378. results.Add(prefix + "=" + String.Empty);
  379. }
  380. else
  381. {
  382. if (jsonPrimitive.Value is DateTime || jsonPrimitive.Value is DateTimeOffset)
  383. {
  384. string dateStr = jsonPrimitive.ToString();
  385. if (!String.IsNullOrEmpty(dateStr) && dateStr.StartsWith("\""))
  386. {
  387. dateStr = dateStr.Substring(1, dateStr.Length - 2);
  388. }
  389. results.Add(prefix + "=" + UriQueryUtility.UrlEncode(dateStr));
  390. }
  391. else
  392. {
  393. results.Add(prefix + "=" + UriQueryUtility.UrlEncode(jsonPrimitive.Value.ToString()));
  394. }
  395. }
  396. }
  397. else
  398. {
  399. results.Add(prefix + "=" + String.Empty);
  400. }
  401. }
  402. else if (jsonValue is JArray)
  403. {
  404. for (int i = 0; i < ((JArray)jsonValue).Count; i++)
  405. {
  406. if (jsonValue[i] is JArray || jsonValue[i] is JObject)
  407. {
  408. BuildParams(prefix + "[" + i + "]", jsonValue[i], results);
  409. }
  410. else
  411. {
  412. BuildParams(prefix + "[]", jsonValue[i], results);
  413. }
  414. }
  415. }
  416. else //jsonValue is JObject
  417. {
  418. foreach (KeyValuePair<string, JToken> item in (JObject)jsonValue)
  419. {
  420. BuildParams(prefix + "[" + item.Key + "]", item.Value, results);
  421. }
  422. }
  423. }
  424. private static Uri GetQueryUri(string query)
  425. {
  426. UriBuilder uriBuilder = new UriBuilder("http://some.host");
  427. uriBuilder.Query = query;
  428. return uriBuilder.Uri;
  429. }
  430. private static JToken ParseFormUrlEncoded(string encoded)
  431. {
  432. Uri address = GetQueryUri(encoded);
  433. JObject result;
  434. Assert.True(address.TryReadQueryAsJson(out result), "Expected parsing to return true");
  435. return result;
  436. }
  437. private static void ParseInvalidFormUrlEncoded(string encoded)
  438. {
  439. Uri address = GetQueryUri(encoded);
  440. JObject result;
  441. Assert.False(address.TryReadQueryAsJson(out result), "Expected parsing to return false");
  442. Assert.Null(result);
  443. }
  444. private static void ValidateFormUrlEncoded(string encoded, string expectedResult)
  445. {
  446. Uri address = GetQueryUri(encoded);
  447. JObject result;
  448. Assert.True(address.TryReadQueryAsJson(out result), "Expected parsing to return true");
  449. Assert.NotNull(result);
  450. Assert.Equal(expectedResult, result.ToString(Newtonsoft.Json.Formatting.None));
  451. }
  452. #endregion
  453. }
  454. }