1 // Copyright (c) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information. 2 3 using System.Collections.Generic; 4 using System.Globalization; 5 using System.IO; 6 using System.Web.WebPages.Resources; 7 using Moq; 8 using Xunit; 9 using Assert = Microsoft.TestCommon.AssertEx; 10 11 namespace System.Web.WebPages.Test 12 { 13 public class RenderPageTest 14 { 15 [Fact] RenderBasicTest()16 public void RenderBasicTest() 17 { 18 // A simple page that does the following: 19 // @{ PageData["Title"] = "MyPage"; } 20 // @PageData["Title"] 21 // hello world 22 // 23 // Expected rendered result is "MyPagehello world" 24 25 var content = "hello world"; 26 var title = "MyPage"; 27 var result = Utils.RenderWebPage( 28 p => 29 { 30 p.PageData["Title"] = title; 31 p.Write(p.PageData["Title"]); 32 p.Write(content); 33 }); 34 35 Assert.Equal(title + content, result); 36 } 37 38 [Fact] RenderDynamicDictionaryBasicTest()39 public void RenderDynamicDictionaryBasicTest() 40 { 41 // A simple page that does the following: 42 // @{ Page.Title = "MyPage"; } 43 // @Page.Title 44 // hello world 45 // 46 // Expected rendered result is "MyPagehello world" 47 48 var content = "hello world"; 49 var title = "MyPage"; 50 var result = Utils.RenderWebPage( 51 p => 52 { 53 p.Page.Title = title; 54 p.Write(p.Page.Title); 55 p.Write(content); 56 }); 57 58 Assert.Equal(title + content, result); 59 } 60 61 [Fact] RenderPageBasicTest()62 public void RenderPageBasicTest() 63 { 64 // ~/index.cshtml does the following: 65 // hello 66 // @RenderPage("subpage.cshtml") 67 // 68 // ~/subpage.cshtml does the following: 69 // world 70 // 71 // Expected output is "helloworld" 72 73 var result = Utils.RenderWebPageWithSubPage( 74 p => 75 { 76 p.Write("hello"); 77 p.Write(p.RenderPage("subpage.cshtml")); 78 }, 79 p => { p.Write("world"); }); 80 Assert.Equal("helloworld", result); 81 } 82 83 [Fact] RenderPageAnonymousTypeTest()84 public void RenderPageAnonymousTypeTest() 85 { 86 // Test for passing an anonymous type object as an argument to RenderPage 87 // 88 // ~/index.cshtml does the following: 89 // @RenderPage("subpage.cshtml", new { HelloKey = "hellovalue", MyKey = "myvalue" }) 90 // 91 // ~/subpage.cshtml does the following: 92 // @PageData["HelloKey"] @PageData["MyKey"] @Model.HelloKey @Model.MyKey 93 // 94 // Expected result: hellovalue myvalue hellovalue myvalue 95 var result = Utils.RenderWebPageWithSubPage( 96 p => { p.Write(p.RenderPage("subpage.cshtml", new { HelloKey = "hellovalue", MyKey = "myvalue" })); }, 97 p => 98 { 99 p.Write(p.PageData["HelloKey"]); 100 p.Write(" "); 101 p.Write(p.PageData["MyKey"]); 102 p.Write(" "); 103 p.Write(p.Model.HelloKey); 104 p.Write(" "); 105 p.Write(p.Model.MyKey); 106 }); 107 Assert.Equal("hellovalue myvalue hellovalue myvalue", result); 108 } 109 110 [Fact] RenderPageDynamicDictionaryAnonymousTypeTest()111 public void RenderPageDynamicDictionaryAnonymousTypeTest() 112 { 113 // Test for passing an anonymous type object as an argument to RenderPage 114 // 115 // ~/index.cshtml does the following: 116 // @RenderPage("subpage.cshtml", new { HelloKey = "hellovalue", MyKey = "myvalue" }) 117 // 118 // ~/subpage.cshtml does the following: 119 // @Page.HelloKey @Page.MyKey @Model.HelloKey @Model.MyKey 120 // 121 // Expected result: hellovalue myvalue hellovalue myvalue 122 var result = Utils.RenderWebPageWithSubPage( 123 p => { p.Write(p.RenderPage("subpage.cshtml", new { HelloKey = "hellovalue", MyKey = "myvalue" })); }, 124 p => 125 { 126 p.Write(p.Page.HelloKey); 127 p.Write(" "); 128 p.Write(p.Page.MyKey); 129 p.Write(" "); 130 p.Write(p.Model.HelloKey); 131 p.Write(" "); 132 p.Write(p.Model.MyKey); 133 }); 134 Assert.Equal("hellovalue myvalue hellovalue myvalue", result); 135 } 136 137 [Fact] RenderPageDictionaryTest()138 public void RenderPageDictionaryTest() 139 { 140 // Test for passing a dictionary instance as an argument to RenderPage 141 // 142 // ~/index.cshtml does the following: 143 // @RenderPage("subpage.cshtml", new Dictionary<string, object>(){ { "foo", 1 }, { "bar", "hello"} }) 144 // 145 // ~/subpage.cshtml does the following: 146 // @PageData["foo"] @PageData["bar"] @PageData[0] 147 // 148 // Expected result: 1 hello System.Collections.Generic.Dictionary`2[System.String,System.Object] 149 150 var result = Utils.RenderWebPageWithSubPage( 151 p => { p.Write(p.RenderPage("subpage.cshtml", new Dictionary<string, object>() { { "foo", 1 }, { "bar", "hello" } })); }, 152 p => 153 { 154 p.Write(p.PageData["foo"]); 155 p.Write(" "); 156 p.Write(p.PageData["bar"]); 157 p.Write(" "); 158 p.Write(p.PageData[0]); 159 }); 160 Assert.Equal("1 hello System.Collections.Generic.Dictionary`2[System.String,System.Object]", result); 161 } 162 163 [Fact] RenderPageDynamicDictionaryTest()164 public void RenderPageDynamicDictionaryTest() 165 { 166 // Test for passing a dictionary instance as an argument to RenderPage 167 // 168 // ~/index.cshtml does the following: 169 // @RenderPage("subpage.cshtml", new Dictionary<string, object>(){ { "foo", 1 }, { "bar", "hello"} }) 170 // 171 // ~/subpage.cshtml does the following: 172 // @Page.foo @Page.bar @Page[0] 173 // 174 // Expected result: 1 hello System.Collections.Generic.Dictionary`2[System.String,System.Object] 175 176 var result = Utils.RenderWebPageWithSubPage( 177 p => { p.Write(p.RenderPage("subpage.cshtml", new Dictionary<string, object>() { { "foo", 1 }, { "bar", "hello" } })); }, 178 p => 179 { 180 p.Write(p.Page.foo); 181 p.Write(" "); 182 p.Write(p.Page.bar); 183 p.Write(" "); 184 p.Write(p.Page[0]); 185 }); 186 Assert.Equal("1 hello System.Collections.Generic.Dictionary`2[System.String,System.Object]", result); 187 } 188 189 [Fact] RenderPageListTest()190 public void RenderPageListTest() 191 { 192 // Test for passing a list of arguments to RenderPage 193 // 194 // ~/index.cshtml does the following: 195 // @RenderPage("subpage.cshtml", "hello", "world", 1, 2, 3) 196 // 197 // ~/subpage.cshtml does the following: 198 // @PageData[0] @PageData[1] @PageData[2] @PageData[3] @PageData[4] 199 // 200 // Expected result: hello world 1 2 3 201 202 var result = Utils.RenderWebPageWithSubPage( 203 p => { p.Write(p.RenderPage("subpage.cshtml", "hello", "world", 1, 2, 3)); }, 204 p => 205 { 206 p.Write(p.PageData[0]); 207 p.Write(" "); 208 p.Write(p.PageData[1]); 209 p.Write(" "); 210 p.Write(p.PageData[2]); 211 p.Write(" "); 212 p.Write(p.PageData[3]); 213 p.Write(" "); 214 p.Write(p.PageData[4]); 215 }); 216 Assert.Equal("hello world 1 2 3", result); 217 } 218 219 [Fact] RenderPageDynamicDictionaryListTest()220 public void RenderPageDynamicDictionaryListTest() 221 { 222 // Test for passing a list of arguments to RenderPage 223 // 224 // ~/index.cshtml does the following: 225 // @RenderPage("subpage.cshtml", "hello", "world", 1, 2, 3) 226 // 227 // ~/subpage.cshtml does the following: 228 // @Page[0] @Page[1] @Page[2] @Page[3] @Page[4] 229 // 230 // Expected result: hello world 1 2 3 231 232 var result = Utils.RenderWebPageWithSubPage( 233 p => { p.Write(p.RenderPage("subpage.cshtml", "hello", "world", 1, 2, 3)); }, 234 p => 235 { 236 p.Write(p.Page[0]); 237 p.Write(" "); 238 p.Write(p.Page[1]); 239 p.Write(" "); 240 p.Write(p.Page[2]); 241 p.Write(" "); 242 p.Write(p.Page[3]); 243 p.Write(" "); 244 p.Write(p.Page[4]); 245 }); 246 Assert.Equal("hello world 1 2 3", result); 247 } 248 249 private class Person 250 { 251 public string FirstName { get; set; } 252 } 253 254 [Fact] RenderPageDynamicValueTest()255 public void RenderPageDynamicValueTest() 256 { 257 // Test that PageData[key] returns a dynamic value. 258 // ~/index.cshtml does the following: 259 // @RenderPage("subpage.cshtml", new Person(){ FirstName="MyFirstName" }) 260 // 261 // ~/subpage.cshtml does the following: 262 // @PageData[0].FirstName 263 // 264 // Expected result: MyFirstName 265 var result = Utils.RenderWebPageWithSubPage( 266 p => { p.Write(p.RenderPage("subpage.cshtml", new Person() { FirstName = "MyFirstName" })); }, 267 p => { p.Write(p.PageData[0].FirstName); }); 268 Assert.Equal("MyFirstName", result); 269 } 270 271 [Fact] RenderPageDynamicDictionaryDynamicValueTest()272 public void RenderPageDynamicDictionaryDynamicValueTest() 273 { 274 // Test that PageData[key] returns a dynamic value. 275 // ~/index.cshtml does the following: 276 // @RenderPage("subpage.cshtml", new Person(){ FirstName="MyFirstName" }) 277 // 278 // ~/subpage.cshtml does the following: 279 // @Page[0].FirstName 280 // 281 // Expected result: MyFirstName 282 var result = Utils.RenderWebPageWithSubPage( 283 p => { p.Write(p.RenderPage("subpage.cshtml", new Person() { FirstName = "MyFirstName" })); }, 284 p => { p.Write(p.Page[0].FirstName); }); 285 Assert.Equal("MyFirstName", result); 286 } 287 288 [Fact] PageDataSetByParentTest()289 public void PageDataSetByParentTest() 290 { 291 // Items set in the PageData should be accessible by the subpage 292 var result = Utils.RenderWebPageWithSubPage( 293 p => 294 { 295 p.PageData["test"] = "hello"; 296 p.Write(p.RenderPage("subpage.cshtml")); 297 }, 298 p => { p.Write(p.PageData["test"]); }); 299 Assert.Equal("hello", result); 300 } 301 302 [Fact] DynamicDictionarySetByParentTest()303 public void DynamicDictionarySetByParentTest() 304 { 305 // Items set in the PageData should be accessible by the subpage 306 var result = Utils.RenderWebPageWithSubPage( 307 p => 308 { 309 p.Page.test = "hello"; 310 p.Write(p.RenderPage("subpage.cshtml")); 311 }, 312 p => { p.Write(p.Page.test); }); 313 Assert.Equal("hello", result); 314 } 315 316 [Fact] OverridePageDataSetByParentTest()317 public void OverridePageDataSetByParentTest() 318 { 319 // Items set in the PageData should be accessible by the subpage unless 320 // overriden by parameters passed into RenderPage, in which case the 321 // specified value should be used. 322 var result = Utils.RenderWebPageWithSubPage( 323 p => 324 { 325 p.PageData["test"] = "hello"; 326 p.Write(p.RenderPage("subpage.cshtml", new { Test = "world" })); 327 }, 328 p => 329 { 330 p.Write(p.PageData["test"]); 331 p.Write(p.PageData[0].Test); 332 }); 333 Assert.Equal("worldworld", result); 334 } 335 336 [Fact] OverrideDynamicDictionarySetByParentTest()337 public void OverrideDynamicDictionarySetByParentTest() 338 { 339 // Items set in the PageData should be accessible by the subpage unless 340 // overriden by parameters passed into RenderPage, in which case the 341 // specified value should be used. 342 var result = Utils.RenderWebPageWithSubPage( 343 p => 344 { 345 p.PageData["test"] = "hello"; 346 p.Write(p.RenderPage("subpage.cshtml", new { Test = "world" })); 347 }, 348 p => 349 { 350 p.Write(p.Page.test); 351 p.Write(p.Page[0].Test); 352 }); 353 Assert.Equal("worldworld", result); 354 } 355 356 [Fact] RenderPageMissingKeyTest()357 public void RenderPageMissingKeyTest() 358 { 359 // Test that using PageData with a missing key returns null 360 // 361 // ~/index.cshtml does the following: 362 // @RenderPage("subpage.cshtml", new Dictionary<string, object>(){ { "foo", 1 }, { "bar", "hello"} }) 363 // @RenderPage("subpage.cshtml", "x", "y", "z") 364 // 365 // ~/subpage.cshtml does the following: 366 // @(PageData[1] ?? "null") 367 // @(PageData["bar"] ?? "null") 368 // 369 // Expected result: null hello y null 370 371 var result = Utils.RenderWebPageWithSubPage( 372 p => 373 { 374 p.Write(p.RenderPage("subpage.cshtml", new Dictionary<string, object>() { { "foo", 1 }, { "bar", "hello" } })); 375 p.Write(p.RenderPage("subpage.cshtml", "x", "y", "z")); 376 }, 377 p => 378 { 379 p.Write(p.PageData[1] ?? "null1"); 380 p.Write(" "); 381 p.Write(p.PageData["bar"] ?? "null2"); 382 p.Write(" "); 383 }); 384 Assert.Equal("null1 hello y null2 ", result); 385 } 386 387 [Fact] RenderPageDynamicDictionaryMissingKeyTest()388 public void RenderPageDynamicDictionaryMissingKeyTest() 389 { 390 // Test that using PageData with a missing key returns null 391 // 392 // ~/index.cshtml does the following: 393 // @RenderPage("subpage.cshtml", new Dictionary<string, object>(){ { "foo", 1 }, { "bar", "hello"} }) 394 // @RenderPage("subpage.cshtml", "x", "y", "z") 395 // 396 // ~/subpage.cshtml does the following: 397 // @(Page[1] ?? "null") 398 // @(Page.bar ?? "null") 399 // 400 // Expected result: null hello y null 401 402 Action<WebPage> subPage = p => 403 { 404 p.Write(p.Page[1] ?? "null1"); 405 p.Write(" "); 406 p.Write(p.Page.bar ?? "null2"); 407 p.Write(" "); 408 }; 409 var result = Utils.RenderWebPageWithSubPage( 410 p => { p.Write(p.RenderPage("subpage.cshtml", new Dictionary<string, object>() { { "foo", 1 }, { "bar", "hello" } })); }, subPage); 411 Assert.Equal("null1 hello ", result); 412 result = Utils.RenderWebPageWithSubPage( 413 p => { p.Write(p.RenderPage("subpage.cshtml", "x", "y", "z")); }, subPage); 414 Assert.Equal("y null2 ", result); 415 } 416 417 [Fact] RenderPageNoArgumentsTest()418 public void RenderPageNoArgumentsTest() 419 { 420 // Test that using PageData within the calling page, and also 421 // within the subppage when the calling page doesn't provide any arguments 422 // 423 // ~/index.cshtml does the following: 424 // @(PageData["foo"] ?? "null1") 425 // @RenderPage("subpage.cshtml") 426 // 427 // ~/subpage.cshtml does the following: 428 // @(PageData[1] ?? "null2") 429 // @(PageData["bar"] ?? "null3") 430 // 431 // Expected result: null1 null2 null3 432 433 var result = Utils.RenderWebPageWithSubPage( 434 p => 435 { 436 p.Write(p.PageData["foo"] ?? "null1 "); 437 p.Write(p.RenderPage("subpage.cshtml")); 438 }, 439 p => 440 { 441 p.Write(p.PageData[1] ?? "null2"); 442 p.Write(" "); 443 p.Write(p.PageData["bar"] ?? "null3"); 444 }); 445 Assert.Equal("null1 null2 null3", result); 446 } 447 448 [Fact] RenderPageDynamicDictionaryNoArgumentsTest()449 public void RenderPageDynamicDictionaryNoArgumentsTest() 450 { 451 // Test that using PageData within the calling page, and also 452 // within the subppage when the calling page doesn't provide any arguments 453 // 454 // ~/index.cshtml does the following: 455 // @(Page.foo ?? "null1") 456 // @RenderPage("subpage.cshtml") 457 // 458 // ~/subpage.cshtml does the following: 459 // @(Page[1] ?? "null2") 460 // @(Page.bar ?? "null3") 461 // 462 // Expected result: null1 null2 null3 463 464 var result = Utils.RenderWebPageWithSubPage( 465 p => 466 { 467 p.Write(p.Page.foo ?? "null1 "); 468 p.Write(p.RenderPage("subpage.cshtml")); 469 }, 470 p => 471 { 472 p.Write(p.Page[1] ?? "null2"); 473 p.Write(" "); 474 p.Write(p.Page.bar ?? "null3"); 475 }); 476 Assert.Equal("null1 null2 null3", result); 477 } 478 479 [Fact] RenderPageNestedSubPageListTest()480 public void RenderPageNestedSubPageListTest() 481 { 482 // Test that PageData for each level of nesting returns the values as specified in the 483 // previous calling page. 484 // 485 // ~/index.cshtml does the following: 486 // @(PageData["foo"] ?? "null") 487 // @RenderPage("subpage1.cshtml", "a", "b", "c") 488 // 489 // ~/subpage1.cshtml does the following: 490 // @(PageData[0] ?? "sub1null0") 491 // @(PageData[1] ?? "sub1null1") 492 // @(PageData[2] ?? "sub1null2") 493 // @(PageData[3] ?? "sub1null3") 494 // @RenderPage("subpage2.cshtml", "x", "y", "z") 495 // 496 // ~/subpage2.cshtml does the following: 497 // @(PageData[0] ?? "sub2null0") 498 // @(PageData[1] ?? "sub2null1") 499 // @(PageData[2] ?? "sub2null2") 500 // @(PageData[3] ?? "sub2null3") 501 // 502 // Expected result: null a b c sub1null3 x y z sub2null3 503 var page = Utils.CreatePage( 504 p => 505 { 506 p.Write(p.PageData["foo"] ?? "null "); 507 p.Write(p.RenderPage("subpage1.cshtml", "a", "b", "c")); 508 }); 509 var subpage1Path = "~/subpage1.cshtml"; 510 var subpage1 = Utils.CreatePage( 511 p => 512 { 513 p.Write(p.PageData[0] ?? "sub1null0"); 514 p.Write(" "); 515 p.Write(p.PageData[1] ?? "sub1null1"); 516 p.Write(" "); 517 p.Write(p.PageData[2] ?? "sub1null2"); 518 p.Write(" "); 519 p.Write(p.PageData[3] ?? "sub1null3"); 520 p.Write(" "); 521 p.Write(p.RenderPage("subpage2.cshtml", "x", "y", "z")); 522 }, subpage1Path); 523 var subpage2Path = "~/subpage2.cshtml"; 524 var subpage2 = Utils.CreatePage( 525 p => 526 { 527 p.Write(p.PageData[0] ?? "sub2null0"); 528 p.Write(" "); 529 p.Write(p.PageData[1] ?? "sub2null1"); 530 p.Write(" "); 531 p.Write(p.PageData[2] ?? "sub2null2"); 532 p.Write(" "); 533 p.Write(p.PageData[3] ?? "sub2null3"); 534 }, subpage2Path); 535 536 Utils.AssignObjectFactoriesAndDisplayModeProvider(page, subpage1, subpage2); 537 538 var result = Utils.RenderWebPage(page); 539 Assert.Equal("null a b c sub1null3 x y z sub2null3", result); 540 } 541 542 [Fact] RenderPageNestedSubPageAnonymousTypeTest()543 public void RenderPageNestedSubPageAnonymousTypeTest() 544 { 545 // Test that PageData for each level of nesting returns the values as specified in the 546 // previous calling page. 547 // 548 // ~/index.cshtml does the following: 549 // @(PageData["foo"] ?? "null") 550 // @RenderPage("subpage.cshtml", new { foo = 1 , bar = "hello" }) 551 // 552 // ~/subpage1.cshtml does the following: 553 // @(PageData["foo"] ?? "sub1nullfoo") 554 // @(PageData["bar"] ?? "sub1nullbar") 555 // @(PageData["x"] ?? "sub1nullx") 556 // @(PageData["y"] ?? "sub1nully") 557 // @RenderPage("subpage2.cshtml", new { bar = "world", x = "good", y = "bye"}) 558 // 559 // ~/subpage2.cshtml does the following: 560 // @(PageData["foo"] ?? "sub2nullfoo") 561 // @(PageData["bar"] ?? "sub2nullbar") 562 // @(PageData["x"] ?? "sub2nullx") 563 // @(PageData["y"] ?? "sub2nully") 564 // 565 // Expected result: null 1 hello sub1nullx sub1nully sub2nullfoo world good bye 566 var page = Utils.CreatePage( 567 p => 568 { 569 p.Write(p.PageData["foo"] ?? "null "); 570 p.Write(p.RenderPage("subpage1.cshtml", new { foo = 1, bar = "hello" })); 571 }); 572 var subpage1Path = "~/subpage1.cshtml"; 573 var subpage1 = Utils.CreatePage( 574 p => 575 { 576 p.Write(p.PageData["foo"] ?? "sub1nullfoo"); 577 p.Write(" "); 578 p.Write(p.PageData["bar"] ?? "sub1nullbar"); 579 p.Write(" "); 580 p.Write(p.PageData["x"] ?? "sub1nullx"); 581 p.Write(" "); 582 p.Write(p.PageData["y"] ?? "sub1nully"); 583 p.Write(" "); 584 p.Write(p.RenderPage("subpage2.cshtml", new { bar = "world", x = "good", y = "bye" })); 585 }, subpage1Path); 586 var subpage2Path = "~/subpage2.cshtml"; 587 var subpage2 = Utils.CreatePage( 588 p => 589 { 590 p.Write(p.PageData["foo"] ?? "sub2nullfoo"); 591 p.Write(" "); 592 p.Write(p.PageData["bar"] ?? "sub2nullbar"); 593 p.Write(" "); 594 p.Write(p.PageData["x"] ?? "sub2nullx"); 595 p.Write(" "); 596 p.Write(p.PageData["y"] ?? "sub2nully"); 597 }, subpage2Path); 598 599 Utils.AssignObjectFactoriesAndDisplayModeProvider(subpage1, subpage2, page); 600 601 var result = Utils.RenderWebPage(page); 602 Assert.Equal("null 1 hello sub1nullx sub1nully sub2nullfoo world good bye", result); 603 } 604 605 [Fact] RenderPageNestedSubPageDictionaryTest()606 public void RenderPageNestedSubPageDictionaryTest() 607 { 608 // Test that PageData for each level of nesting returns the values as specified in the 609 // previous calling page. 610 // 611 // ~/index.cshtml does the following: 612 // @(PageData["foo"] ?? "null") 613 // @RenderPage("subpage.cshtml", new Dictionary<string, object>(){ { "foo", 1 }, { "bar", "hello"} }) 614 // 615 // ~/subpage1.cshtml does the following: 616 // @(PageData["foo"] ?? "sub1nullfoo") 617 // @(PageData["bar"] ?? "sub1nullbar") 618 // @(PageData["x"] ?? "sub1nullx") 619 // @(PageData["y"] ?? "sub1nully") 620 // @RenderPage("subpage2.cshtml", new Dictionary<string, object>(){ { { "bar", "world"}, {"x", "good"}, {"y", "bye"} }) 621 // 622 // ~/subpage2.cshtml does the following: 623 // @(PageData["foo"] ?? "sub2nullfoo") 624 // @(PageData["bar"] ?? "sub2nullbar") 625 // @(PageData["x"] ?? "sub2nullx") 626 // @(PageData["y"] ?? "sub2nully") 627 // 628 // Expected result: null 1 hello sub1nullx sub1nully sub2nullfoo world good bye 629 var page = Utils.CreatePage( 630 p => 631 { 632 p.Write(p.PageData["foo"] ?? "null "); 633 p.Write(p.RenderPage("subpage1.cshtml", new Dictionary<string, object>() { { "foo", 1 }, { "bar", "hello" } })); 634 }); 635 var subpage1Path = "~/subpage1.cshtml"; 636 var subpage1 = Utils.CreatePage( 637 p => 638 { 639 p.Write(p.PageData["foo"] ?? "sub1nullfoo"); 640 p.Write(" "); 641 p.Write(p.PageData["bar"] ?? "sub1nullbar"); 642 p.Write(" "); 643 p.Write(p.PageData["x"] ?? "sub1nullx"); 644 p.Write(" "); 645 p.Write(p.PageData["y"] ?? "sub1nully"); 646 p.Write(" "); 647 p.Write(p.RenderPage("subpage2.cshtml", new Dictionary<string, object>() { { "bar", "world" }, { "x", "good" }, { "y", "bye" } })); 648 }, subpage1Path); 649 var subpage2Path = "~/subpage2.cshtml"; 650 var subpage2 = Utils.CreatePage( 651 p => 652 { 653 p.Write(p.PageData["foo"] ?? "sub2nullfoo"); 654 p.Write(" "); 655 p.Write(p.PageData["bar"] ?? "sub2nullbar"); 656 p.Write(" "); 657 p.Write(p.PageData["x"] ?? "sub2nullx"); 658 p.Write(" "); 659 p.Write(p.PageData["y"] ?? "sub2nully"); 660 }, subpage2Path); 661 662 Utils.AssignObjectFactoriesAndDisplayModeProvider(page, subpage1, subpage2); 663 664 var result = Utils.RenderWebPage(page); 665 Assert.Equal("null 1 hello sub1nullx sub1nully sub2nullfoo world good bye", result); 666 } 667 668 [Fact] RenderPageNestedParentPageDataTest()669 public void RenderPageNestedParentPageDataTest() 670 { 671 // PageData should return values set by parent pages. 672 var page = Utils.CreatePage( 673 p => 674 { 675 p.PageData["key1"] = "value1"; 676 p.Write(p.RenderPage("subpage1.cshtml")); 677 }); 678 var subpage1Path = "~/subpage1.cshtml"; 679 var subpage1 = Utils.CreatePage( 680 p => 681 { 682 p.WriteLiteral("<subpage1>"); 683 p.Write(p.PageData["key1"]); 684 p.Write(p.RenderPage("subpage2.cshtml")); 685 p.Write(p.PageData["key1"]); 686 p.PageData["key1"] = "value2"; 687 p.Write(p.RenderPage("subpage2.cshtml")); 688 p.WriteLiteral("</subpage1>"); 689 }, subpage1Path); 690 var subpage2Path = "~/subpage2.cshtml"; 691 var subpage2 = Utils.CreatePage( 692 p => 693 { 694 p.WriteLiteral("<subpage2>"); 695 p.Write(p.PageData["key1"]); 696 // Setting the value in the child page should 697 // not affect the parent page 698 p.PageData["key1"] = "value3"; 699 p.Write(p.RenderPage("subpage3.cshtml", new { Key1 = "value4" })); 700 p.WriteLiteral("</subpage2>"); 701 }, subpage2Path); 702 var subpage3Path = "~/subpage3.cshtml"; 703 var subpage3 = Utils.CreatePage( 704 p => 705 { 706 p.WriteLiteral("<subpage3>"); 707 p.Write(p.PageData["key1"]); 708 p.WriteLiteral("</subpage3>"); 709 }, subpage3Path); 710 711 Utils.AssignObjectFactoriesAndDisplayModeProvider(subpage1, subpage2, subpage3, page); 712 713 var result = Utils.RenderWebPage(page); 714 Assert.Equal("<subpage1>value1<subpage2>value1<subpage3>value4</subpage3></subpage2>value1<subpage2>value2<subpage3>value4</subpage3></subpage2></subpage1>", result); 715 } 716 717 [Fact] WriteNullTest()718 public void WriteNullTest() 719 { 720 // Test for @null 721 var result = Utils.RenderWebPage( 722 p => 723 { 724 p.Write(null); 725 p.Write((object)null); 726 p.Write((HelperResult)null); 727 }); 728 729 Assert.Equal("", result); 730 } 731 732 [Fact] WriteTest()733 public void WriteTest() 734 { 735 // Test for calling WebPage.Write on text and HtmlHelper 736 var text = "Hello"; 737 var wrote = false; 738 Action<TextWriter> action = tw => 739 { 740 tw.Write(text); 741 wrote = true; 742 }; 743 var helper = new HelperResult(action); 744 var result = Utils.RenderWebPage( 745 p => { p.Write(helper); }); 746 Assert.Equal(text, result); 747 Assert.True(wrote); 748 } 749 750 [Fact] WriteLiteralTest()751 public void WriteLiteralTest() 752 { 753 // Test for calling WebPage.WriteLiteral on text and HtmlHelper 754 var text = "Hello"; 755 var wrote = false; 756 Action<TextWriter> action = tw => 757 { 758 tw.Write(text); 759 wrote = true; 760 }; 761 var helper = new HelperResult(action); 762 var result = Utils.RenderWebPage( 763 p => { p.WriteLiteral(helper); }); 764 Assert.Equal(text, result); 765 Assert.True(wrote); 766 } 767 768 [Fact] ExtensionNotSupportedTest()769 public void ExtensionNotSupportedTest() 770 { 771 // Tests that calling RenderPage on an unsupported extension returns a new simpler error message 772 // instead of the full error about build providers in system.web.dll. 773 var vpath = "~/hello/world.txt"; 774 var ext = ".txt"; 775 var compilationUtilThrowingBuildManager = new CompilationUtil(); 776 var otherExceptionBuildManager = new Mock<IVirtualPathFactory>(); 777 var msg = "The file \"~/hello/world.txt\" could not be rendered, because it does not exist or is not a valid page."; 778 otherExceptionBuildManager.Setup(c => c.CreateInstance(It.IsAny<string>())).Throws(new HttpException(msg)); 779 780 Assert.Throws<HttpException>(() => 781 WebPage.CreateInstanceFromVirtualPath(vpath, new VirtualPathFactoryManager(compilationUtilThrowingBuildManager)), 782 String.Format(CultureInfo.CurrentCulture, WebPageResources.WebPage_FileNotSupported, ext, vpath)); 783 784 // Test that other error messages are thrown unmodified. 785 Assert.Throws<HttpException>(() => WebPage.CreateInstanceFromVirtualPath(vpath, otherExceptionBuildManager.Object), msg); 786 } 787 788 [Fact] RenderBodyCalledInChildPageTest()789 public void RenderBodyCalledInChildPageTest() 790 { 791 // A Page that is called by RenderPage should not be able to call RenderBody(). 792 793 Assert.Throws<HttpException>(() => 794 Utils.RenderWebPageWithSubPage( 795 p => 796 { 797 p.Write("hello"); 798 p.Write(p.RenderPage("subpage.cshtml")); 799 }, 800 p => 801 { 802 p.Write("world"); 803 p.RenderBody(); 804 }), 805 String.Format(CultureInfo.CurrentCulture, WebPageResources.WebPage_CannotRequestDirectly, "~/subpage.cshtml", "RenderBody")); 806 } 807 808 [Fact] RenderPageInvalidPageType()809 public void RenderPageInvalidPageType() 810 { 811 var pagePath = "~/foo.js"; 812 var page = Utils.CreatePage(p => { p.Write(p.RenderPage(pagePath)); }); 813 814 var objectFactory = new Mock<IVirtualPathFactory>(); 815 objectFactory.Setup(c => c.Exists(It.IsAny<string>())).Returns<string>(p => pagePath.Equals(p, StringComparison.OrdinalIgnoreCase)); 816 objectFactory.Setup(c => c.CreateInstance(It.IsAny<string>())).Returns<string>(_ => null); 817 page.VirtualPathFactory = objectFactory.Object; 818 819 Assert.Throws<HttpException>(() => 820 { 821 page.VirtualPathFactory = objectFactory.Object; 822 page.DisplayModeProvider = new DisplayModeProvider(); 823 Utils.RenderWebPage(page); 824 }, 825 String.Format(CultureInfo.CurrentCulture, WebPageResources.WebPage_InvalidPageType, pagePath)); 826 } 827 828 [Fact] RenderPageValidPageType()829 public void RenderPageValidPageType() 830 { 831 var pagePath = "~/foo.js"; 832 var page = Utils.CreatePage(p => { p.Write(p.RenderPage(pagePath)); }); 833 834 var contents = "hello world"; 835 var subPage = Utils.CreatePage(p => p.Write(contents), pagePath); 836 837 Utils.AssignObjectFactoriesAndDisplayModeProvider(page, subPage); 838 839 Assert.Equal(contents, Utils.RenderWebPage(page)); 840 } 841 842 [Fact] RenderPageNull()843 public void RenderPageNull() 844 { 845 Assert.ThrowsArgumentNullOrEmptyString(() => Utils.RenderWebPage(p => p.RenderPage(null)), "path"); 846 } 847 848 [Fact] RenderPageEmptyString()849 public void RenderPageEmptyString() 850 { 851 Assert.ThrowsArgumentNullOrEmptyString(() => Utils.RenderWebPage(p => p.RenderPage("")), "path"); 852 } 853 854 [Fact] SamePageCaseInsensitiveTest()855 public void SamePageCaseInsensitiveTest() 856 { 857 var result = Utils.RenderWebPage( 858 p => 859 { 860 p.PageData["xyz"] = "value"; 861 p.PageData["XYZ"] = "VALUE"; 862 p.Write(p.PageData["xYz"]); 863 }); 864 865 Assert.Equal("VALUE", result); 866 } 867 } 868 } 869