// Copyright (c) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information. using System.IO; using System.Web.Routing; using System.Web.TestUtil; using System.Web.UI; using Moq; using Xunit; using Assert = Microsoft.TestCommon.AssertEx; namespace System.Web.Mvc.Test { public class ViewUserControlTest { [Fact] public void ModelProperty() { // Arrange object model = new object(); ViewDataDictionary viewData = new ViewDataDictionary(model); ViewUserControl viewUserControl = new ViewUserControl(); viewUserControl.ViewData = viewData; // Act object viewPageModel = viewUserControl.Model; // Assert Assert.Equal(model, viewPageModel); Assert.Equal(model, viewUserControl.ViewData.Model); } [Fact] public void ModelPropertyStronglyTyped() { // Arrange FooModel model = new FooModel(); ViewDataDictionary viewData = new ViewDataDictionary(model); ViewUserControl viewUserControl = new ViewUserControl(); viewUserControl.ViewData = viewData; // Act object viewPageModelObject = ((ViewUserControl)viewUserControl).Model; FooModel viewPageModelPerson = viewUserControl.Model; // Assert Assert.Equal(model, viewPageModelObject); Assert.Equal(model, viewPageModelPerson); } [Fact] public void RenderViewAndRestoreContentType() { // Arrange Mock mockViewContext = new Mock(); mockViewContext.SetupProperty(c => c.HttpContext.Response.ContentType); ViewContext vc = mockViewContext.Object; Mock mockViewPage = new Mock(); mockViewPage.Setup(vp => vp.RenderView(vc)).Callback(() => vc.HttpContext.Response.ContentType = "newContentType"); // Act vc.HttpContext.Response.ContentType = "oldContentType"; ViewUserControl.RenderViewAndRestoreContentType(mockViewPage.Object, vc); string postContentType = vc.HttpContext.Response.ContentType; // Assert Assert.Equal("oldContentType", postContentType); } [Fact] public void SetViewItem() { // Arrange ViewUserControl vuc = new ViewUserControl(); object viewItem = new object(); vuc.ViewData = new ViewDataDictionary(viewItem); // Act vuc.ViewData.Model = viewItem; object newViewItem = vuc.ViewData.Model; // Assert Assert.Same(viewItem, newViewItem); } [Fact] public void SetViewItemOnBaseClassPropagatesToDerivedClass() { // Arrange ViewUserControl vucInt = new ViewUserControl(); ViewUserControl vuc = vucInt; vuc.ViewData = new ViewDataDictionary(); object o = new object(); // Act vuc.ViewData.Model = o; // Assert Assert.Equal(o, vucInt.ViewData.Model); Assert.Equal(o, vuc.ViewData.Model); } [Fact] public void SetViewItemOnDerivedClassPropagatesToBaseClass() { // Arrange ViewUserControl vucInt = new ViewUserControl(); ViewUserControl vuc = vucInt; vucInt.ViewData = new ViewDataDictionary(); object o = new object(); // Act vucInt.ViewData.Model = o; // Assert Assert.Equal(o, vucInt.ViewData.Model); Assert.Equal(o, vuc.ViewData.Model); } [Fact] public void SetViewItemToWrongTypeThrows() { // Arrange ViewUserControl vucString = new ViewUserControl(); vucString.ViewData = new ViewDataDictionary(); ViewUserControl vuc = vucString; // Act & Assert Assert.Throws( delegate { vuc.ViewData.Model = 50; }, "The model item passed into the dictionary is of type 'System.Int32', but this dictionary requires a model item of type 'System.String'."); } [Fact] public void GetViewDataWhenNoPageSetThrows() { ViewUserControl vuc = new ViewUserControl(); vuc.AppRelativeVirtualPath = "~/Foo.ascx"; Assert.Throws( delegate { var foo = vuc.ViewData["Foo"]; }, "The ViewUserControl '~/Foo.ascx' cannot find an IViewDataContainer object. The ViewUserControl must be inside a ViewPage, a ViewMasterPage, or another ViewUserControl."); } [Fact] public void GetViewDataWhenRegularPageSetThrows() { Page p = new Page(); p.Controls.Add(new Control()); ViewUserControl vuc = new ViewUserControl(); p.Controls[0].Controls.Add(vuc); vuc.AppRelativeVirtualPath = "~/Foo.ascx"; Assert.Throws( delegate { var foo = vuc.ViewData["Foo"]; }, "The ViewUserControl '~/Foo.ascx' cannot find an IViewDataContainer object. The ViewUserControl must be inside a ViewPage, a ViewMasterPage, or another ViewUserControl."); } [Fact] public void GetViewDataFromViewPage() { // Arrange ViewPage p = new ViewPage(); p.Controls.Add(new Control()); ViewUserControl vuc = new ViewUserControl(); p.Controls[0].Controls.Add(vuc); p.ViewData = new ViewDataDictionary { { "FirstName", "Joe" }, { "LastName", "Schmoe" } }; // Act object firstName = vuc.ViewData.Eval("FirstName"); object lastName = vuc.ViewData.Eval("LastName"); // Assert Assert.Equal("Joe", firstName); Assert.Equal("Schmoe", lastName); } [Fact] public void GetViewDataFromViewPageWithViewDataKeyPointingToObject() { // Arrange ViewDataDictionary vdd = new ViewDataDictionary() { { "Foo", "FooParent" }, { "Bar", "BarParent" }, { "Child", new object() } }; ViewPage p = new ViewPage(); p.Controls.Add(new Control()); ViewUserControl vuc = new ViewUserControl() { ViewDataKey = "Child" }; p.Controls[0].Controls.Add(vuc); p.ViewData = vdd; // Act object oFoo = vuc.ViewData.Eval("Foo"); object oBar = vuc.ViewData.Eval("Bar"); // Assert Assert.Equal(vdd["Child"], vuc.ViewData.Model); Assert.Equal("FooParent", oFoo); Assert.Equal("BarParent", oBar); } [Fact] public void GetViewDataFromViewPageWithViewDataKeyPointingToViewDataDictionary() { // Arrange ViewDataDictionary vdd = new ViewDataDictionary() { { "Foo", "FooParent" }, { "Bar", "BarParent" }, { "Child", new ViewDataDictionary() { { "Foo", "FooChild" }, { "Bar", "BarChild" } } } }; ViewPage p = new ViewPage(); p.Controls.Add(new Control()); ViewUserControl vuc = new ViewUserControl() { ViewDataKey = "Child" }; p.Controls[0].Controls.Add(vuc); p.ViewData = vdd; // Act object oFoo = vuc.ViewData.Eval("Foo"); object oBar = vuc.ViewData.Eval("Bar"); // Assert Assert.Equal(vdd["Child"], vuc.ViewData); Assert.Equal("FooChild", oFoo); Assert.Equal("BarChild", oBar); } [Fact] public void GetViewDataFromViewUserControl() { // Arrange ViewPage p = new ViewPage(); p.Controls.Add(new Control()); ViewUserControl outerVuc = new ViewUserControl(); p.Controls[0].Controls.Add(outerVuc); outerVuc.Controls.Add(new Control()); ViewUserControl vuc = new ViewUserControl(); outerVuc.Controls[0].Controls.Add(vuc); p.ViewData = new ViewDataDictionary { { "FirstName", "Joe" }, { "LastName", "Schmoe" } }; // Act object firstName = vuc.ViewData.Eval("FirstName"); object lastName = vuc.ViewData.Eval("LastName"); // Assert Assert.Equal("Joe", firstName); Assert.Equal("Schmoe", lastName); } [Fact] public void GetViewDataFromViewUserControlWithViewDataKeyOnInnerControl() { // Arrange ViewPage p = new ViewPage(); p.Controls.Add(new Control()); ViewUserControl outerVuc = new ViewUserControl(); p.Controls[0].Controls.Add(outerVuc); outerVuc.Controls.Add(new Control()); ViewUserControl vuc = new ViewUserControl() { ViewDataKey = "SubData" }; outerVuc.Controls[0].Controls.Add(vuc); p.ViewData = new ViewDataDictionary { { "FirstName", "Joe" }, { "LastName", "Schmoe" } }; p.ViewData["SubData"] = new ViewDataDictionary { { "FirstName", "SubJoe" }, { "LastName", "SubSchmoe" } }; // Act object firstName = vuc.ViewData.Eval("FirstName"); object lastName = vuc.ViewData.Eval("LastName"); // Assert Assert.Equal("SubJoe", firstName); Assert.Equal("SubSchmoe", lastName); } [Fact] public void GetViewDataFromViewUserControlWithViewDataKeyOnOuterControl() { // Arrange ViewPage p = new ViewPage(); p.Controls.Add(new Control()); ViewUserControl outerVuc = new ViewUserControl() { ViewDataKey = "SubData" }; p.Controls[0].Controls.Add(outerVuc); outerVuc.Controls.Add(new Control()); ViewUserControl vuc = new ViewUserControl(); outerVuc.Controls[0].Controls.Add(vuc); p.ViewData = new ViewDataDictionary { { "FirstName", "Joe" }, { "LastName", "Schmoe" } }; p.ViewData["SubData"] = new ViewDataDictionary { { "FirstName", "SubJoe" }, { "LastName", "SubSchmoe" } }; // Act object firstName = vuc.ViewData.Eval("FirstName"); object lastName = vuc.ViewData.Eval("LastName"); // Assert Assert.Equal("SubJoe", firstName); Assert.Equal("SubSchmoe", lastName); } [Fact] public void ViewDataKeyProperty() { MemberHelper.TestStringProperty(new ViewUserControl(), "ViewDataKey", String.Empty, testDefaultValueAttribute: true); } [Fact] public void GetWrongGenericViewItemTypeThrows() { // Arrange ViewPage p = new ViewPage(); p.ViewData = new ViewDataDictionary(); p.ViewData["Foo"] = new DummyViewData { MyInt = 123, MyString = "Whatever" }; MockViewUserControl vuc = new MockViewUserControl() { ViewDataKey = "FOO" }; vuc.AppRelativeVirtualPath = "~/Foo.aspx"; p.Controls.Add(new Control()); p.Controls[0].Controls.Add(vuc); // Act Assert.Throws( delegate { var foo = vuc.ViewData.Model.IntProp; }, @"The model item passed into the dictionary is of type 'System.Web.Mvc.Test.ViewUserControlTest+DummyViewData', but this dictionary requires a model item of type 'System.Web.Mvc.Test.ViewUserControlTest+MyViewData'."); } [Fact] public void GetGenericViewItemType() { // Arrange ViewPage p = new ViewPage(); p.Controls.Add(new Control()); MockViewUserControl vuc = new MockViewUserControl() { ViewDataKey = "FOO" }; p.Controls[0].Controls.Add(vuc); p.ViewData = new ViewDataDictionary(); p.ViewData["Foo"] = new MyViewData { IntProp = 123, StringProp = "miao" }; // Act int intProp = vuc.ViewData.Model.IntProp; string stringProp = vuc.ViewData.Model.StringProp; // Assert Assert.Equal(123, intProp); Assert.Equal("miao", stringProp); } [Fact] public void GetHtmlHelperFromViewPage() { // Arrange ViewUserControl vuc = new ViewUserControl(); ViewPage containerPage = new ViewPage(); containerPage.Controls.Add(vuc); ViewContext vc = new Mock().Object; vuc.ViewContext = vc; // Act HtmlHelper htmlHelper = vuc.Html; // Assert Assert.Equal(vc, htmlHelper.ViewContext); Assert.Equal(vuc, htmlHelper.ViewDataContainer); } [Fact] public void GetHtmlHelperFromRegularPage() { // Arrange ViewUserControl vuc = new ViewUserControl(); Page containerPage = new Page(); containerPage.Controls.Add(vuc); // Assert Assert.Throws( delegate { HtmlHelper foo = vuc.Html; }, "A ViewUserControl can be used only in pages that derive from ViewPage or ViewPage."); } [Fact] public void GetUrlHelperFromViewPage() { // Arrange ViewUserControl vuc = new ViewUserControl(); ViewPage containerPage = new ViewPage(); containerPage.Controls.Add(vuc); RequestContext rc = new RequestContext(new Mock().Object, new RouteData()); UrlHelper urlHelper = new UrlHelper(rc); containerPage.Url = urlHelper; // Assert Assert.Equal(vuc.Url, urlHelper); } [Fact] public void GetUrlHelperFromRegularPage() { // Arrange ViewUserControl vuc = new ViewUserControl(); Page containerPage = new Page(); containerPage.Controls.Add(vuc); // Assert Assert.Throws( delegate { UrlHelper foo = vuc.Url; }, "A ViewUserControl can be used only in pages that derive from ViewPage or ViewPage."); } [Fact] public void GetWriterFromViewPage() { // Arrange MockViewUserControl vuc = new MockViewUserControl(); MockViewUserControlContainerPage containerPage = new MockViewUserControlContainerPage(vuc); bool triggered = false; HtmlTextWriter writer = new HtmlTextWriter(TextWriter.Null); containerPage.RenderCallback = delegate() { triggered = true; Assert.Equal(writer, vuc.Writer); }; // Act & Assert Assert.Null(vuc.Writer); containerPage.RenderControl(writer); Assert.Null(vuc.Writer); Assert.True(triggered); } [Fact] public void GetWriterFromRegularPageThrows() { // Arrange MockViewUserControl vuc = new MockViewUserControl(); Page containerPage = new Page(); containerPage.Controls.Add(vuc); // Act Assert.Throws( delegate { HtmlTextWriter writer = vuc.Writer; }, "A ViewUserControl can be used only in pages that derive from ViewPage or ViewPage."); } [Fact] public void ViewBagProperty_ReflectsViewData() { // Arrange ViewPage containerPage = new ViewPage(); ViewUserControl userControl = new ViewUserControl(); containerPage.Controls.Add(userControl); userControl.ViewData["A"] = 1; // Act & Assert Assert.NotNull(userControl.ViewBag); Assert.Equal(1, userControl.ViewBag.A); } [Fact] public void ViewBagProperty_ReflectsNewViewDataInstance() { // Arrange ViewPage containerPage = new ViewPage(); ViewUserControl userControl = new ViewUserControl(); containerPage.Controls.Add(userControl); userControl.ViewData["A"] = 1; userControl.ViewData = new ViewDataDictionary() { { "A", "bar" } }; // Act & Assert Assert.Equal("bar", userControl.ViewBag.A); } [Fact] public void ViewBagProperty_PropagatesChangesToViewData() { // Arrange ViewPage containerPage = new ViewPage(); ViewUserControl userControl = new ViewUserControl(); containerPage.Controls.Add(userControl); userControl.ViewData["A"] = 1; // Act userControl.ViewBag.A = "foo"; userControl.ViewBag.B = 2; // Assert Assert.Equal("foo", userControl.ViewData["A"]); Assert.Equal(2, userControl.ViewData["B"]); } private sealed class DummyViewData { public int MyInt { get; set; } public string MyString { get; set; } } private sealed class MockViewUserControlContainerPage : ViewPage { public Action RenderCallback { get; set; } public MockViewUserControlContainerPage(ViewUserControl userControl) { Controls.Add(userControl); } protected override void RenderChildren(HtmlTextWriter writer) { if (RenderCallback != null) { RenderCallback(); } base.RenderChildren(writer); } } private sealed class MockViewUserControl : ViewUserControl { } private sealed class MockViewUserControl : ViewUserControl { } private sealed class MyViewData { public int IntProp { get; set; } public string StringProp { get; set; } } private sealed class FooModel { } } }