From 44048331e936de39073ca5eab97bd5b5cdb0a0f2 Mon Sep 17 00:00:00 2001 From: Ajay Bhargav Baaskaran Date: Wed, 1 Feb 2017 15:07:24 -0800 Subject: [PATCH] Make `ViewComponent.View()` overloads respect explicitly passed in model even when `null` --- .../Controller.cs | 14 +- .../ViewComponent.cs | 13 +- .../ControllerTest.cs | 159 ++++++++++++++++++ .../ViewComponentTests.cs | 58 +++++++ 4 files changed, 225 insertions(+), 19 deletions(-) diff --git a/src/Microsoft.AspNetCore.Mvc.ViewFeatures/Controller.cs b/src/Microsoft.AspNetCore.Mvc.ViewFeatures/Controller.cs index 92017c07ec..31e182b4f5 100644 --- a/src/Microsoft.AspNetCore.Mvc.ViewFeatures/Controller.cs +++ b/src/Microsoft.AspNetCore.Mvc.ViewFeatures/Controller.cs @@ -113,7 +113,7 @@ namespace Microsoft.AspNetCore.Mvc [NonAction] public virtual ViewResult View(string viewName) { - return View(viewName, model: null); + return View(viewName, model: ViewData.Model); } /// @@ -138,10 +138,7 @@ namespace Microsoft.AspNetCore.Mvc [NonAction] public virtual ViewResult View(string viewName, object model) { - if (model != null) - { - ViewData.Model = model; - } + ViewData.Model = model; return new ViewResult() { @@ -169,7 +166,7 @@ namespace Microsoft.AspNetCore.Mvc [NonAction] public virtual PartialViewResult PartialView(string viewName) { - return PartialView(viewName, model: null); + return PartialView(viewName, model: ViewData.Model); } /// @@ -194,10 +191,7 @@ namespace Microsoft.AspNetCore.Mvc [NonAction] public virtual PartialViewResult PartialView(string viewName, object model) { - if (model != null) - { - ViewData.Model = model; - } + ViewData.Model = model; return new PartialViewResult() { diff --git a/src/Microsoft.AspNetCore.Mvc.ViewFeatures/ViewComponent.cs b/src/Microsoft.AspNetCore.Mvc.ViewFeatures/ViewComponent.cs index f9352d8d25..83d71c6d7d 100644 --- a/src/Microsoft.AspNetCore.Mvc.ViewFeatures/ViewComponent.cs +++ b/src/Microsoft.AspNetCore.Mvc.ViewFeatures/ViewComponent.cs @@ -237,7 +237,7 @@ namespace Microsoft.AspNetCore.Mvc /// A . public ViewViewComponentResult View() { - return View(null, null); + return View(viewName: null); } /// @@ -247,7 +247,7 @@ namespace Microsoft.AspNetCore.Mvc /// A . public ViewViewComponentResult View(string viewName) { - return View(viewName, null); + return View(viewName, ViewData.Model); } /// @@ -257,7 +257,7 @@ namespace Microsoft.AspNetCore.Mvc /// A . public ViewViewComponentResult View(TModel model) { - return View(null, model); + return View(viewName: null, model: model); } /// @@ -268,12 +268,7 @@ namespace Microsoft.AspNetCore.Mvc /// A . public ViewViewComponentResult View(string viewName, TModel model) { - if (model != null) - { - ViewData.Model = model; - } - - var viewData = new ViewDataDictionary(ViewData); + var viewData = new ViewDataDictionary(ViewData, model); return new ViewViewComponentResult { ViewEngine = ViewEngine, diff --git a/test/Microsoft.AspNetCore.Mvc.ViewFeatures.Test/ControllerTest.cs b/test/Microsoft.AspNetCore.Mvc.ViewFeatures.Test/ControllerTest.cs index 57e31a7c5c..39874cafa0 100644 --- a/test/Microsoft.AspNetCore.Mvc.ViewFeatures.Test/ControllerTest.cs +++ b/test/Microsoft.AspNetCore.Mvc.ViewFeatures.Test/ControllerTest.cs @@ -87,6 +87,30 @@ namespace Microsoft.AspNetCore.Mvc.Test Assert.Null(actualViewResult.ViewData.Model); } + [Fact] + public void Controller_View_WithoutParameter_MaintainsModelInViewData() + { + // Arrange + var controller = new TestableController() + { + ViewData = new ViewDataDictionary(new EmptyModelMetadataProvider()), + TempData = new TempDataDictionary(new DefaultHttpContext(), Mock.Of()), + }; + + var model = new object(); + controller.ViewData.Model = model; + + // Act + var actualViewResult = controller.View(); + + // Assert + Assert.IsType(actualViewResult); + Assert.Null(actualViewResult.ViewName); + Assert.Same(controller.ViewData, actualViewResult.ViewData); + Assert.Same(controller.TempData, actualViewResult.TempData); + Assert.Same(model, actualViewResult.ViewData.Model); + } + [Fact] public void Controller_View_WithParameterViewName_SetsResultViewNameAndNullViewDataModelAndSameTempData() { @@ -152,6 +176,141 @@ namespace Microsoft.AspNetCore.Mvc.Test Assert.Same(model, actualViewResult.ViewData.Model); } + [Fact] + public void Controller_View_WithNullModelParameter_OverwritesViewDataModel() + { + // Arrange + var controller = new TestableController() + { + ViewData = new ViewDataDictionary(new EmptyModelMetadataProvider()), + TempData = new TempDataDictionary(new DefaultHttpContext(), Mock.Of()), + }; + controller.ViewData.Model = new object(); + + // Act + var actualViewResult = controller.View(model: null); + + // Assert + Assert.IsType(actualViewResult); + Assert.Null(actualViewResult.ViewName); + Assert.Same(controller.ViewData, actualViewResult.ViewData); + Assert.Same(controller.TempData, actualViewResult.TempData); + Assert.Null(actualViewResult.ViewData.Model); + } + + [Fact] + public void Controller_PartialView_WithoutParameter_MaintainsModelInViewData() + { + // Arrange + var controller = new TestableController() + { + ViewData = new ViewDataDictionary(new EmptyModelMetadataProvider()), + TempData = new TempDataDictionary(new DefaultHttpContext(), Mock.Of()), + }; + + var model = new object(); + controller.ViewData.Model = model; + + // Act + var actualViewResult = controller.PartialView(); + + // Assert + Assert.IsType(actualViewResult); + Assert.Null(actualViewResult.ViewName); + Assert.Same(controller.ViewData, actualViewResult.ViewData); + Assert.Same(controller.TempData, actualViewResult.TempData); + Assert.Same(model, actualViewResult.ViewData.Model); + } + + [Fact] + public void Controller_PartialView_WithParameterViewName_SetsResultViewNameAndMaintainsSameViewDataModelAndTempData() + { + // Arrange + var controller = new TestableController() + { + ViewData = new ViewDataDictionary(new EmptyModelMetadataProvider()), + TempData = new TempDataDictionary(new DefaultHttpContext(), Mock.Of()), + }; + var model = new object(); + controller.ViewData.Model = model; + + // Act + var actualViewResult = controller.PartialView("CustomViewName"); + + // Assert + Assert.IsType(actualViewResult); + Assert.Equal("CustomViewName", actualViewResult.ViewName); + Assert.Same(controller.ViewData, actualViewResult.ViewData); + Assert.Same(controller.TempData, actualViewResult.TempData); + Assert.Same(model, actualViewResult.ViewData.Model); + } + + [Fact] + public void Controller_PartialView_WithParameterViewModel_SetsResultNullViewNameAndViewDataModelAndSameTempData() + { + // Arrange + var controller = new TestableController() + { + ViewData = new ViewDataDictionary(new EmptyModelMetadataProvider()), + TempData = new TempDataDictionary(new DefaultHttpContext(), Mock.Of()), + }; + var model = new object(); + + // Act + var actualViewResult = controller.PartialView(model); + + // Assert + Assert.IsType(actualViewResult); + Assert.Null(actualViewResult.ViewName); + Assert.Same(controller.ViewData, actualViewResult.ViewData); + Assert.Same(controller.TempData, actualViewResult.TempData); + Assert.Same(model, actualViewResult.ViewData.Model); + } + + [Fact] + public void Controller_PartialView_WithParameterViewNameAndViewModel_SetsResultViewNameAndViewDataModelAndSameTempData() + { + // Arrange + var controller = new TestableController() + { + ViewData = new ViewDataDictionary(new EmptyModelMetadataProvider()), + TempData = new TempDataDictionary(new DefaultHttpContext(), Mock.Of()), + }; + var model = new object(); + + // Act + var actualViewResult = controller.PartialView("CustomViewName", model); + + // Assert + Assert.IsType(actualViewResult); + Assert.Equal("CustomViewName", actualViewResult.ViewName); + Assert.Same(controller.ViewData, actualViewResult.ViewData); + Assert.Same(controller.TempData, actualViewResult.TempData); + Assert.Same(model, actualViewResult.ViewData.Model); + } + + [Fact] + public void Controller_PartialView_WithNullModelParameter_OverwritesViewDataModel() + { + // Arrange + var controller = new TestableController() + { + ViewData = new ViewDataDictionary(new EmptyModelMetadataProvider()), + TempData = new TempDataDictionary(new DefaultHttpContext(), Mock.Of()), + }; + controller.ViewData.Model = new object(); + + // Act + var actualViewResult = controller.PartialView(model: null); + + // Assert + Assert.IsType(actualViewResult); + Assert.Null(actualViewResult.ViewName); + Assert.Same(controller.ViewData, actualViewResult.ViewData); + Assert.Same(controller.TempData, actualViewResult.TempData); + Assert.Null(actualViewResult.ViewData.Model); + } + [Fact] public void Controller_Json_WithParameterValue_SetsResultData() { diff --git a/test/Microsoft.AspNetCore.Mvc.ViewFeatures.Test/ViewComponentTests.cs b/test/Microsoft.AspNetCore.Mvc.ViewFeatures.Test/ViewComponentTests.cs index 92aaafbabb..40718d8a69 100644 --- a/test/Microsoft.AspNetCore.Mvc.ViewFeatures.Test/ViewComponentTests.cs +++ b/test/Microsoft.AspNetCore.Mvc.ViewFeatures.Test/ViewComponentTests.cs @@ -139,6 +139,64 @@ namespace Microsoft.AspNetCore.Mvc Assert.Null(actualResult.ViewName); } + [Fact] + public void ViewComponent_View_WithNullModelParameter_SetsResultViewWithDefaultViewNameAndNullModel() + { + // Arrange + var viewComponent = new TestViewComponent(); + viewComponent.ViewData.Model = new object(); + object model = null; + + // Act + var actualResult = viewComponent.View(model: model); + + // Assert + Assert.IsType(actualResult); + Assert.IsType>(actualResult.ViewData); + Assert.NotSame(viewComponent.ViewData, actualResult.ViewData); + Assert.Equal(new ViewDataDictionary(viewComponent.ViewData), actualResult.ViewData); + Assert.Null(actualResult.ViewData.Model); + Assert.Null(actualResult.ViewName); + } + + [Fact] + public void ViewComponent_View_WithViewNameAndNullModelParameter_SetsResultViewWithViewNameAndNullModel() + { + // Arrange + var viewComponent = new TestViewComponent(); + viewComponent.ViewData.Model = new object(); + + // Act + var actualResult = viewComponent.View("CustomViewName", model: null); + + // Assert + Assert.IsType(actualResult); + Assert.IsType>(actualResult.ViewData); + Assert.NotSame(viewComponent.ViewData, actualResult.ViewData); + Assert.Equal(new ViewDataDictionary(viewComponent.ViewData), actualResult.ViewData); + Assert.Null(actualResult.ViewData.Model); + Assert.Equal("CustomViewName", actualResult.ViewName); + } + + [Fact] + public void ViewComponent_View_WithViewNameAndNonObjectNullModelParameter_SetsResultViewWithViewNameAndNullModel() + { + // Arrange + var viewComponent = new TestViewComponent(); + viewComponent.ViewData.Model = "Hello World!"; + + // Act + var actualResult = viewComponent.View("CustomViewName", model: null); + + // Assert + Assert.IsType(actualResult); + Assert.IsType>(actualResult.ViewData); + Assert.NotSame(viewComponent.ViewData, actualResult.ViewData); + Assert.Equal(new ViewDataDictionary(viewComponent.ViewData), actualResult.ViewData); + Assert.Null(actualResult.ViewData.Model); + Assert.Equal("CustomViewName", actualResult.ViewName); + } + [Fact] public void ViewComponent_View_WithViewNameAndModelParameters_SetsResultViewWithCustomViewNameAndModel() {