a575963da9
Former-commit-id: da6be194a6b1221998fc28233f2503bd61dd9d14
541 lines
19 KiB
C#
541 lines
19 KiB
C#
// 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<FooModel> viewData = new ViewDataDictionary<FooModel>(model);
|
|
ViewUserControl<FooModel> viewUserControl = new ViewUserControl<FooModel>();
|
|
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<ViewContext> mockViewContext = new Mock<ViewContext>();
|
|
mockViewContext.SetupProperty(c => c.HttpContext.Response.ContentType);
|
|
ViewContext vc = mockViewContext.Object;
|
|
|
|
Mock<ViewPage> mockViewPage = new Mock<ViewPage>();
|
|
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<object> vucInt = new ViewUserControl<object>();
|
|
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<object> vucInt = new ViewUserControl<object>();
|
|
ViewUserControl vuc = vucInt;
|
|
vucInt.ViewData = new ViewDataDictionary<object>();
|
|
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<string> vucString = new ViewUserControl<string>();
|
|
vucString.ViewData = new ViewDataDictionary<string>();
|
|
ViewUserControl vuc = vucString;
|
|
|
|
// Act & Assert
|
|
Assert.Throws<InvalidOperationException>(
|
|
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<InvalidOperationException>(
|
|
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<InvalidOperationException>(
|
|
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<MyViewData> vuc = new MockViewUserControl<MyViewData>() { ViewDataKey = "FOO" };
|
|
vuc.AppRelativeVirtualPath = "~/Foo.aspx";
|
|
p.Controls.Add(new Control());
|
|
p.Controls[0].Controls.Add(vuc);
|
|
|
|
// Act
|
|
Assert.Throws<InvalidOperationException>(
|
|
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<MyViewData> vuc = new MockViewUserControl<MyViewData>() { 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<ViewContext>().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<InvalidOperationException>(
|
|
delegate { HtmlHelper foo = vuc.Html; },
|
|
"A ViewUserControl can be used only in pages that derive from ViewPage or ViewPage<TModel>.");
|
|
}
|
|
|
|
[Fact]
|
|
public void GetUrlHelperFromViewPage()
|
|
{
|
|
// Arrange
|
|
ViewUserControl vuc = new ViewUserControl();
|
|
ViewPage containerPage = new ViewPage();
|
|
containerPage.Controls.Add(vuc);
|
|
RequestContext rc = new RequestContext(new Mock<HttpContextBase>().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<InvalidOperationException>(
|
|
delegate { UrlHelper foo = vuc.Url; },
|
|
"A ViewUserControl can be used only in pages that derive from ViewPage or ViewPage<TModel>.");
|
|
}
|
|
|
|
[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<InvalidOperationException>(
|
|
delegate { HtmlTextWriter writer = vuc.Writer; },
|
|
"A ViewUserControl can be used only in pages that derive from ViewPage or ViewPage<TModel>.");
|
|
}
|
|
|
|
[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<TViewData> : ViewUserControl<TViewData>
|
|
{
|
|
}
|
|
|
|
private sealed class MyViewData
|
|
{
|
|
public int IntProp { get; set; }
|
|
public string StringProp { get; set; }
|
|
}
|
|
|
|
private sealed class FooModel
|
|
{
|
|
}
|
|
}
|
|
}
|