From 408d4056b1063461ae1b27a7524985fd2dbac9a6 Mon Sep 17 00:00:00 2001 From: Ryan Nowak Date: Wed, 9 Apr 2014 11:54:58 -0700 Subject: [PATCH] Rearrange ViewContext --- samples/MvcSample.Web/MvcSample.Web.kproj | 3 ++ src/Common/Common.kproj | 3 ++ .../ActionContext.cs | 6 +++ .../ActionResults/ViewResult.cs | 15 +----- .../Rendering/Html/HtmlHelper.cs | 17 +++---- .../Rendering/Html/TemplateRenderer.cs | 14 +++--- .../ViewComponents/ViewViewComponentResult.cs | 18 ++++--- src/Microsoft.AspNet.Mvc.Core/ViewContext.cs | 48 +++++++++++-------- src/Microsoft.AspNet.Mvc.Razor/RazorView.cs | 6 +-- .../RazorViewOfT.cs | 4 +- .../Microsoft.AspNet.Mvc.kproj | 3 ++ .../Microsoft.AspNet.Mvc.Core.Test.kproj | 3 ++ .../Rendering/ViewContextTests.cs | 2 +- ...crosoft.AspNet.Mvc.ModelBinding.Test.kproj | 3 ++ .../Microsoft.AspNet.Mvc.Razor.Test.kproj | 3 ++ .../RazorViewTest.cs | 15 ++++-- .../project.json | 1 + 17 files changed, 96 insertions(+), 68 deletions(-) diff --git a/samples/MvcSample.Web/MvcSample.Web.kproj b/samples/MvcSample.Web/MvcSample.Web.kproj index 1d5d97fbeb..2956d976f2 100644 --- a/samples/MvcSample.Web/MvcSample.Web.kproj +++ b/samples/MvcSample.Web/MvcSample.Web.kproj @@ -60,5 +60,8 @@ + + + \ No newline at end of file diff --git a/src/Common/Common.kproj b/src/Common/Common.kproj index a848b015d3..eabc129a05 100644 --- a/src/Common/Common.kproj +++ b/src/Common/Common.kproj @@ -23,5 +23,8 @@ + + + \ No newline at end of file diff --git a/src/Microsoft.AspNet.Mvc.Core/ActionContext.cs b/src/Microsoft.AspNet.Mvc.Core/ActionContext.cs index cce52f4e81..a626b5b875 100644 --- a/src/Microsoft.AspNet.Mvc.Core/ActionContext.cs +++ b/src/Microsoft.AspNet.Mvc.Core/ActionContext.cs @@ -7,6 +7,12 @@ namespace Microsoft.AspNet.Mvc { public class ActionContext { + public ActionContext([NotNull] ActionContext actionContext) + : this(actionContext.HttpContext, actionContext.Router, actionContext.RouteValues, actionContext.ActionDescriptor) + { + ModelState = actionContext.ModelState; + } + public ActionContext(HttpContext httpContext, IRouter router, IDictionary routeValues, ActionDescriptor actionDescriptor) { HttpContext = httpContext; diff --git a/src/Microsoft.AspNet.Mvc.Core/ActionResults/ViewResult.cs b/src/Microsoft.AspNet.Mvc.Core/ActionResults/ViewResult.cs index f7efaee70f..e4acdb1da0 100644 --- a/src/Microsoft.AspNet.Mvc.Core/ActionResults/ViewResult.cs +++ b/src/Microsoft.AspNet.Mvc.Core/ActionResults/ViewResult.cs @@ -33,7 +33,7 @@ namespace Microsoft.AspNet.Mvc context.HttpContext.Response.ContentType = "text/html"; using (var writer = new StreamWriter(context.HttpContext.Response.Body, Encoding.UTF8, 1024, leaveOpen: true)) { - var viewContext = CreateViewContext(context, writer); + var viewContext = new ViewContext(context, view, ViewData, writer); await view.RenderAsync(viewContext); } } @@ -44,18 +44,5 @@ namespace Microsoft.AspNet.Mvc var result = _viewEngine.FindView(context, viewName); return result.View; } - - private ViewContext CreateViewContext([NotNull] ActionContext actionContext, [NotNull] TextWriter writer) - { - var urlHelper = _serviceProvider.GetService(); - - var viewContext = new ViewContext(_serviceProvider, actionContext.HttpContext, actionContext.RouteValues) - { - ViewData = ViewData, - Writer = writer, - }; - - return viewContext; - } } } diff --git a/src/Microsoft.AspNet.Mvc.Core/Rendering/Html/HtmlHelper.cs b/src/Microsoft.AspNet.Mvc.Core/Rendering/Html/HtmlHelper.cs index b2f996417b..6b8781ef33 100644 --- a/src/Microsoft.AspNet.Mvc.Core/Rendering/Html/HtmlHelper.cs +++ b/src/Microsoft.AspNet.Mvc.Core/Rendering/Html/HtmlHelper.cs @@ -281,15 +281,16 @@ namespace Microsoft.AspNet.Mvc.Rendering var newViewData = new ViewDataDictionary(baseViewData, model); - var newViewContext = new ViewContext(ViewContext) + + + var viewEngineResult = _viewEngine.FindPartialView(ViewContext.RouteValues, partialViewName); + var view = viewEngineResult.View; + + using (view as IDisposable) { - ViewData = newViewData, - Writer = writer - }; - - var viewEngineResult = _viewEngine.FindPartialView(newViewContext.ViewEngineContext, partialViewName); - - await viewEngineResult.View.RenderAsync(newViewContext); + var viewContext = new ViewContext(ViewContext, view, newViewData, writer); + await viewEngineResult.View.RenderAsync(viewContext); + } } public HtmlString Password(string name, object value, object htmlAttributes) diff --git a/src/Microsoft.AspNet.Mvc.Core/Rendering/Html/TemplateRenderer.cs b/src/Microsoft.AspNet.Mvc.Core/Rendering/Html/TemplateRenderer.cs index 69cf1e5219..6091dbc860 100644 --- a/src/Microsoft.AspNet.Mvc.Core/Rendering/Html/TemplateRenderer.cs +++ b/src/Microsoft.AspNet.Mvc.Core/Rendering/Html/TemplateRenderer.cs @@ -44,20 +44,20 @@ namespace Microsoft.AspNet.Mvc.Rendering var fullViewName = modeViewPath + "/" + viewName; // Forcing synchronous behavior so users don't have to await templates. - var viewEngineResult = _viewEngine.FindPartialView(_viewContext.ViewEngineContext, fullViewName); + var viewEngineResult = _viewEngine.FindPartialView(_viewContext.RouteValues, fullViewName); if (viewEngineResult.Success) { using (var writer = new StringWriter(CultureInfo.InvariantCulture)) { // Forcing synchronous behavior so users don't have to await templates. // TODO: Pass through TempData once implemented. - viewEngineResult.View.RenderAsync(new ViewContext(_viewContext) + var view = viewEngineResult.View; + using (view as IDisposable) { - ViewData = _viewData, - Writer = writer, - }).Wait(); - - return writer.ToString(); + var viewContext = new ViewContext(_viewContext, viewEngineResult.View, _viewData, writer); + viewEngineResult.View.RenderAsync(viewContext).Wait(); + return writer.ToString(); + } } } diff --git a/src/Microsoft.AspNet.Mvc.Core/ViewComponents/ViewViewComponentResult.cs b/src/Microsoft.AspNet.Mvc.Core/ViewComponents/ViewViewComponentResult.cs index c5f91d961c..945c655dbf 100644 --- a/src/Microsoft.AspNet.Mvc.Core/ViewComponents/ViewViewComponentResult.cs +++ b/src/Microsoft.AspNet.Mvc.Core/ViewComponents/ViewViewComponentResult.cs @@ -31,15 +31,6 @@ namespace Microsoft.AspNet.Mvc public async Task ExecuteAsync([NotNull] ViewComponentContext context) { - var childViewContext = new ViewContext( - context.ViewContext.ServiceProvider, - context.ViewContext.HttpContext, - context.ViewContext.ViewEngineContext) - { - ViewData = _viewData ?? context.ViewContext.ViewData, - Writer = context.Writer, - }; - string qualifiedViewName; if (_viewName.Length > 0 && _viewName[0] == '/') { @@ -66,7 +57,14 @@ namespace Microsoft.AspNet.Mvc _viewName); } - var view = FindView(context.ViewContext.ViewEngineContext, qualifiedViewName); + var view = FindView(context.ViewContext.RouteValues, qualifiedViewName); + + var childViewContext = new ViewContext( + context.ViewContext, + view, + _viewData ?? context.ViewContext.ViewData, + context.Writer); + using (view as IDisposable) { await view.RenderAsync(childViewContext); diff --git a/src/Microsoft.AspNet.Mvc.Core/ViewContext.cs b/src/Microsoft.AspNet.Mvc.Core/ViewContext.cs index 5dd54696f6..5c49b84f2b 100644 --- a/src/Microsoft.AspNet.Mvc.Core/ViewContext.cs +++ b/src/Microsoft.AspNet.Mvc.Core/ViewContext.cs @@ -6,7 +6,7 @@ using Microsoft.AspNet.Mvc.Rendering; namespace Microsoft.AspNet.Mvc { - public class ViewContext + public class ViewContext : ActionContext { private DynamicViewData _viewBag; @@ -14,25 +14,39 @@ namespace Microsoft.AspNet.Mvc private readonly FormContext _defaultFormContext = new FormContext(); private FormContext _formContext; - - public ViewContext([NotNull] ViewContext viewContext) - : this(viewContext.ServiceProvider, viewContext.HttpContext, viewContext.ViewEngineContext) - { - UnobtrusiveJavaScriptEnabled = viewContext.UnobtrusiveJavaScriptEnabled; - ClientValidationEnabled = viewContext.ClientValidationEnabled; - } - public ViewContext(IServiceProvider serviceProvider, HttpContext httpContext, - IDictionary viewEngineContext) + public ViewContext( + [NotNull] ActionContext actionContext, + [NotNull] IView view, + [NotNull] ViewDataDictionary viewData, + [NotNull] TextWriter writer) + : base(actionContext) { - ServiceProvider = serviceProvider; - HttpContext = httpContext; - ViewEngineContext = viewEngineContext; + View = view; + ViewData = viewData; + Writer = writer; + _formContext = _defaultFormContext; UnobtrusiveJavaScriptEnabled = true; ClientValidationEnabled = true; } + public ViewContext( + [NotNull] ViewContext viewContext, + [NotNull] IView view, + [NotNull] ViewDataDictionary viewData, + [NotNull] TextWriter writer) + : base(viewContext) + { + _formContext = viewContext.FormContext; + UnobtrusiveJavaScriptEnabled = viewContext.UnobtrusiveJavaScriptEnabled; + ClientValidationEnabled = viewContext.ClientValidationEnabled; + + View = view; + ViewData = viewData; + Writer = writer; + } + public virtual FormContext FormContext { get @@ -46,10 +60,6 @@ namespace Microsoft.AspNet.Mvc } } - public HttpContext HttpContext { get; private set; } - - public IServiceProvider ServiceProvider { get; private set; } - public bool UnobtrusiveJavaScriptEnabled { get; set; } public bool ClientValidationEnabled { get; set; } @@ -67,9 +77,9 @@ namespace Microsoft.AspNet.Mvc } } - public ViewDataDictionary ViewData { get; set; } + public IView View { get; set; } - public IDictionary ViewEngineContext { get; private set; } + public ViewDataDictionary ViewData { get; set; } public TextWriter Writer { get; set; } } diff --git a/src/Microsoft.AspNet.Mvc.Razor/RazorView.cs b/src/Microsoft.AspNet.Mvc.Razor/RazorView.cs index b07e0a5bac..d7e00efc30 100644 --- a/src/Microsoft.AspNet.Mvc.Razor/RazorView.cs +++ b/src/Microsoft.AspNet.Mvc.Razor/RazorView.cs @@ -86,9 +86,9 @@ namespace Microsoft.AspNet.Mvc.Razor { Contract.Assert(Context != null); - Url = Context.ServiceProvider.GetService(); + Url = Context.HttpContext.RequestServices.GetService(); - Component = Context.ServiceProvider.GetService(); + Component = Context.HttpContext.RequestServices.GetService(); var contextable = Component as ICanHasViewContext; if (contextable != null) @@ -99,7 +99,7 @@ namespace Microsoft.AspNet.Mvc.Razor private async Task RenderLayoutAsync(ViewContext context, string bodyContent) { - var virtualPathFactory = context.ServiceProvider.GetService(); + var virtualPathFactory = context.HttpContext.RequestServices.GetService(); var layoutView = (RazorView)virtualPathFactory.CreateInstance(Layout); if (layoutView == null) diff --git a/src/Microsoft.AspNet.Mvc.Razor/RazorViewOfT.cs b/src/Microsoft.AspNet.Mvc.Razor/RazorViewOfT.cs index 3cc5af08fe..800e3b8295 100644 --- a/src/Microsoft.AspNet.Mvc.Razor/RazorViewOfT.cs +++ b/src/Microsoft.AspNet.Mvc.Razor/RazorViewOfT.cs @@ -31,7 +31,7 @@ namespace Microsoft.AspNet.Mvc.Razor } else { - var metadataProvider = context.ServiceProvider.GetService(); + var metadataProvider = context.HttpContext.RequestServices.GetService(); ViewData = new ViewDataDictionary(metadataProvider); } @@ -46,7 +46,7 @@ namespace Microsoft.AspNet.Mvc.Razor private void InitHelpers(ViewContext context) { - Html = context.ServiceProvider.GetService>(); + Html = context.HttpContext.RequestServices.GetService>(); var contextable = Html as ICanHasViewContext; if (contextable != null) diff --git a/src/Microsoft.AspNet.Mvc/Microsoft.AspNet.Mvc.kproj b/src/Microsoft.AspNet.Mvc/Microsoft.AspNet.Mvc.kproj index c1b586a170..4020974722 100644 --- a/src/Microsoft.AspNet.Mvc/Microsoft.AspNet.Mvc.kproj +++ b/src/Microsoft.AspNet.Mvc/Microsoft.AspNet.Mvc.kproj @@ -22,5 +22,8 @@ + + + \ No newline at end of file diff --git a/test/Microsoft.AspNet.Mvc.Core.Test/Microsoft.AspNet.Mvc.Core.Test.kproj b/test/Microsoft.AspNet.Mvc.Core.Test/Microsoft.AspNet.Mvc.Core.Test.kproj index 17d4e4dc8e..00ef2fce71 100644 --- a/test/Microsoft.AspNet.Mvc.Core.Test/Microsoft.AspNet.Mvc.Core.Test.kproj +++ b/test/Microsoft.AspNet.Mvc.Core.Test/Microsoft.AspNet.Mvc.Core.Test.kproj @@ -36,5 +36,8 @@ + + + \ No newline at end of file diff --git a/test/Microsoft.AspNet.Mvc.Core.Test/Rendering/ViewContextTests.cs b/test/Microsoft.AspNet.Mvc.Core.Test/Rendering/ViewContextTests.cs index 35fe3771ed..3fb194c97f 100644 --- a/test/Microsoft.AspNet.Mvc.Core.Test/Rendering/ViewContextTests.cs +++ b/test/Microsoft.AspNet.Mvc.Core.Test/Rendering/ViewContextTests.cs @@ -8,7 +8,7 @@ namespace Microsoft.AspNet.Mvc.Rendering public void SettingViewData_AlsoUpdatesViewBag() { // Arrange (eventually passing null to these consturctors will throw) - var context = new ViewContext(serviceProvider: null, httpContext: null, viewEngineContext: null); + var context = new ViewContext(new ActionContext(null, null, null, null), view: null, viewData: null, writer: null); var originalViewData = context.ViewData = new ViewDataDictionary(metadataProvider: null); var replacementViewData = new ViewDataDictionary(metadataProvider: null); diff --git a/test/Microsoft.AspNet.Mvc.ModelBinding.Test/Microsoft.AspNet.Mvc.ModelBinding.Test.kproj b/test/Microsoft.AspNet.Mvc.ModelBinding.Test/Microsoft.AspNet.Mvc.ModelBinding.Test.kproj index a9be9a260d..41f28e309d 100644 --- a/test/Microsoft.AspNet.Mvc.ModelBinding.Test/Microsoft.AspNet.Mvc.ModelBinding.Test.kproj +++ b/test/Microsoft.AspNet.Mvc.ModelBinding.Test/Microsoft.AspNet.Mvc.ModelBinding.Test.kproj @@ -50,5 +50,8 @@ + + + \ No newline at end of file diff --git a/test/Microsoft.AspNet.Mvc.Razor.Test/Microsoft.AspNet.Mvc.Razor.Test.kproj b/test/Microsoft.AspNet.Mvc.Razor.Test/Microsoft.AspNet.Mvc.Razor.Test.kproj index 45daf3311b..00d34abd8a 100644 --- a/test/Microsoft.AspNet.Mvc.Razor.Test/Microsoft.AspNet.Mvc.Razor.Test.kproj +++ b/test/Microsoft.AspNet.Mvc.Razor.Test/Microsoft.AspNet.Mvc.Razor.Test.kproj @@ -26,5 +26,8 @@ + + + \ No newline at end of file diff --git a/test/Microsoft.AspNet.Mvc.Razor.Test/RazorViewTest.cs b/test/Microsoft.AspNet.Mvc.Razor.Test/RazorViewTest.cs index 12952f174e..64f780ab7a 100644 --- a/test/Microsoft.AspNet.Mvc.Razor.Test/RazorViewTest.cs +++ b/test/Microsoft.AspNet.Mvc.Razor.Test/RazorViewTest.cs @@ -1,6 +1,7 @@ using System; using System.IO; using System.Threading.Tasks; +using Microsoft.AspNet.Abstractions; using Microsoft.AspNet.Mvc.Rendering; using Microsoft.AspNet.Testing; using Moq; @@ -295,10 +296,16 @@ Layout end var serviceProvider = new Mock(); serviceProvider.Setup(f => f.GetService(typeof(IVirtualPathViewFactory))) .Returns(viewFactory.Object); - return new ViewContext(serviceProvider.Object, httpContext: null, viewEngineContext: null) - { - Writer = new StringWriter() - }; + + var httpContext = new Mock(); + httpContext.SetupGet(c => c.RequestServices).Returns(serviceProvider.Object); + + var actionContext = new ActionContext(httpContext.Object, null, null, null); + return new ViewContext( + actionContext, + layoutView, + null, + new StringWriter()); } public abstract class TestableRazorView : RazorView diff --git a/test/Microsoft.AspNet.Mvc.Razor.Test/project.json b/test/Microsoft.AspNet.Mvc.Razor.Test/project.json index 9f2c3bfd85..2956d4bd27 100644 --- a/test/Microsoft.AspNet.Mvc.Razor.Test/project.json +++ b/test/Microsoft.AspNet.Mvc.Razor.Test/project.json @@ -4,6 +4,7 @@ "Microsoft.AspNet.Abstractions": "0.1-alpha-*", "Microsoft.AspNet.FileSystems": "0.1-alpha-*", "Microsoft.AspNet.Razor": "0.1-alpha-*", + "Microsoft.AspNet.Routing": "0.1-alpha-*", "Microsoft.AspNet.Mvc.Core" : "", "Microsoft.AspNet.Mvc.Razor" : "", "Microsoft.AspNet.Testing" : "0.1-alpha-*",