From 5f4807dc9e1f81c2820106e7705df9010180235c Mon Sep 17 00:00:00 2001 From: Pranav K Date: Mon, 20 Jan 2014 16:06:31 -0800 Subject: [PATCH] Adding support for ViewData --- .../Compilation/CscBasedCompilationService.cs | 27 +++---- Microsoft.AspNet.Mvc.Razor/RazorView.cs | 4 +- Microsoft.AspNet.Mvc.Razor/RazorViewOfT.cs | 5 +- Microsoft.AspNet.Mvc/ActionResultHelper.cs | 4 +- .../ActionResultHelperExtensions.cs | 8 +-- Microsoft.AspNet.Mvc/Controller.cs | 3 + Microsoft.AspNet.Mvc/IActionResultHelper.cs | 2 +- .../Microsoft.AspNet.Mvc.csproj | 1 + Microsoft.AspNet.Mvc/View/ViewContext.cs | 6 +- .../View/ViewDataDictionary.cs | 72 +++++++++++++++++++ Microsoft.AspNet.Mvc/View/ViewResult.cs | 4 +- MvcSample/HomeController.cs | 3 +- MvcSample/MvcSample.csproj | 2 - MvcSample/Views/Home/MyView.cshtml | 35 ++++++++- MvcSample/Views/Layout.cs | 20 ------ MvcSample/Views/MyView.cs | 20 ------ MvcSample/Views/Shared/_Layout.cshtml | 43 ++++++++--- 17 files changed, 172 insertions(+), 87 deletions(-) create mode 100644 Microsoft.AspNet.Mvc/View/ViewDataDictionary.cs delete mode 100644 MvcSample/Views/Layout.cs delete mode 100644 MvcSample/Views/MyView.cs diff --git a/Microsoft.AspNet.CoreServices/Compilation/CscBasedCompilationService.cs b/Microsoft.AspNet.CoreServices/Compilation/CscBasedCompilationService.cs index 52d5060da9..4f5e2a18ed 100644 --- a/Microsoft.AspNet.CoreServices/Compilation/CscBasedCompilationService.cs +++ b/Microsoft.AspNet.CoreServices/Compilation/CscBasedCompilationService.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; @@ -32,18 +33,18 @@ namespace Microsoft.AspNet.CoreServices } args.AppendFormat("\"{0}\"", fileInfo.PhysicalPath); var outputStream = new MemoryStream(); - var errorStream = new MemoryStream(); // common execute var process = CreateProcess(args.ToString()); - int exitCode = await Start(process, outputStream, errorStream); + int exitCode = await Start(process, outputStream); string output = GetString(outputStream); - string error = GetString(errorStream); if (exitCode != 0) { - return CompilationResult.Failed(String.Empty, error.Split(new[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries) - .Select(e => new CompilationMessage(e))); + IEnumerable messages = output.Split(new[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries) + .Skip(3) + .Select(e => new CompilationMessage(e)); + return CompilationResult.Failed(String.Empty, messages); } var type = Assembly.LoadFrom(outFile) @@ -63,7 +64,7 @@ namespace Microsoft.AspNet.CoreServices return String.Empty; } - private static async Task Start(Process process, Stream output, Stream error) + private static async Task Start(Process process, Stream output) { var tcs = new TaskCompletionSource(); process.EnableRaisingEvents = true; @@ -74,18 +75,10 @@ namespace Microsoft.AspNet.CoreServices process.Start(); - var tasks = new[] - { - process.StandardOutput.BaseStream.CopyToAsync(output), - process.StandardError.BaseStream.CopyToAsync(error) - }; + var copyTask = process.StandardOutput.BaseStream.CopyToAsync(output); + await Task.WhenAll(tcs.Task, copyTask); - int result = await tcs.Task; - - // Process has exited, draining the stdout and stderr - await Task.WhenAll(tasks); - - return result; + return process.ExitCode; } internal Process CreateProcess(string arguments) diff --git a/Microsoft.AspNet.Mvc.Razor/RazorView.cs b/Microsoft.AspNet.Mvc.Razor/RazorView.cs index 03b5437177..818cc72d38 100644 --- a/Microsoft.AspNet.Mvc.Razor/RazorView.cs +++ b/Microsoft.AspNet.Mvc.Razor/RazorView.cs @@ -89,13 +89,13 @@ namespace Microsoft.AspNet.Mvc.Razor } } - protected virtual string RenderBody() + protected virtual HtmlString RenderBody() { if (BodyContent == null) { throw new InvalidOperationException("RenderBody cannot be called at this point because you're not executing a layout"); } - return BodyContent; + return new HtmlString(BodyContent); } } } diff --git a/Microsoft.AspNet.Mvc.Razor/RazorViewOfT.cs b/Microsoft.AspNet.Mvc.Razor/RazorViewOfT.cs index 93cf3291bc..ef6b19584d 100644 --- a/Microsoft.AspNet.Mvc.Razor/RazorViewOfT.cs +++ b/Microsoft.AspNet.Mvc.Razor/RazorViewOfT.cs @@ -7,9 +7,12 @@ namespace Microsoft.AspNet.Mvc.Razor { public TModel Model { get; set; } + public dynamic ViewData { get; set; } + public override Task RenderAsync(ViewContext context, TextWriter writer) { - Model = (TModel)context.Model; + ViewData = context.ViewData; + Model = (TModel)ViewData.Model; return base.RenderAsync(context, writer); } } diff --git a/Microsoft.AspNet.Mvc/ActionResultHelper.cs b/Microsoft.AspNet.Mvc/ActionResultHelper.cs index 2935b46a4a..79677eb59b 100644 --- a/Microsoft.AspNet.Mvc/ActionResultHelper.cs +++ b/Microsoft.AspNet.Mvc/ActionResultHelper.cs @@ -36,12 +36,12 @@ namespace Microsoft.AspNet.Mvc throw new NotImplementedException(); } - public IActionResult View(string view, object model) + public IActionResult View(string view, ViewDataDictionary viewData) { return new ViewResult(_serviceProvider, _viewEngine) { ViewName = view, - Model = model + ViewData = viewData }; } } diff --git a/Microsoft.AspNet.Mvc/ActionResultHelperExtensions.cs b/Microsoft.AspNet.Mvc/ActionResultHelperExtensions.cs index d0345d9973..6c7a32d36c 100644 --- a/Microsoft.AspNet.Mvc/ActionResultHelperExtensions.cs +++ b/Microsoft.AspNet.Mvc/ActionResultHelperExtensions.cs @@ -5,17 +5,17 @@ namespace Microsoft.AspNet.Mvc { public static IActionResult View(this IActionResultHelper actionResultHelper) { - return actionResultHelper.View(view: null, model: null); + return actionResultHelper.View(view: null, viewData: null); } public static IActionResult View(this IActionResultHelper actionResultHelper, string view) { - return actionResultHelper.View(view, model: null); + return actionResultHelper.View(view, viewData: null); } - public static IActionResult View(this IActionResultHelper actionResultHelper, object model) + public static IActionResult View(this IActionResultHelper actionResultHelper, ViewDataDictionary viewData) { - return actionResultHelper.View(view: null, model: model); + return actionResultHelper.View(view: null, viewData: viewData); } } } diff --git a/Microsoft.AspNet.Mvc/Controller.cs b/Microsoft.AspNet.Mvc/Controller.cs index d79a6b657c..d6af014875 100644 --- a/Microsoft.AspNet.Mvc/Controller.cs +++ b/Microsoft.AspNet.Mvc/Controller.cs @@ -8,10 +8,13 @@ namespace Microsoft.AspNet.Mvc public void Initialize(IActionResultHelper actionResultHelper) { Result = actionResultHelper; + ViewData = new ViewDataDictionary(); } public IActionResultHelper Result { get; private set; } public IOwinContext Context { get; set; } + + public ViewDataDictionary ViewData { get; private set; } } } diff --git a/Microsoft.AspNet.Mvc/IActionResultHelper.cs b/Microsoft.AspNet.Mvc/IActionResultHelper.cs index 8bf087d11b..be8c7edbdb 100644 --- a/Microsoft.AspNet.Mvc/IActionResultHelper.cs +++ b/Microsoft.AspNet.Mvc/IActionResultHelper.cs @@ -6,6 +6,6 @@ namespace Microsoft.AspNet.Mvc IActionResult Content(string value); IActionResult Content(string value, string contentType); IActionResult Json(object value); - IActionResult View(string view, object model); + IActionResult View(string view, ViewDataDictionary viewData); } } diff --git a/Microsoft.AspNet.Mvc/Microsoft.AspNet.Mvc.csproj b/Microsoft.AspNet.Mvc/Microsoft.AspNet.Mvc.csproj index bdc28dbe39..af56f7c519 100644 --- a/Microsoft.AspNet.Mvc/Microsoft.AspNet.Mvc.csproj +++ b/Microsoft.AspNet.Mvc/Microsoft.AspNet.Mvc.csproj @@ -89,6 +89,7 @@ + diff --git a/Microsoft.AspNet.Mvc/View/ViewContext.cs b/Microsoft.AspNet.Mvc/View/ViewContext.cs index 135270f97e..f9cd20cc05 100644 --- a/Microsoft.AspNet.Mvc/View/ViewContext.cs +++ b/Microsoft.AspNet.Mvc/View/ViewContext.cs @@ -6,14 +6,14 @@ namespace Microsoft.AspNet.Mvc { public class ViewContext : RequestContext { - public ViewContext(IOwinContext context, IRouteData routeData, object model) : + public ViewContext(IOwinContext context, IRouteData routeData, ViewDataDictionary viewData) : base(context, routeData) { - Model = model; + ViewData = viewData; } public IServiceProvider ServiceProvider { get; set; } - public object Model { get; private set; } + public ViewDataDictionary ViewData { get; private set; } } } diff --git a/Microsoft.AspNet.Mvc/View/ViewDataDictionary.cs b/Microsoft.AspNet.Mvc/View/ViewDataDictionary.cs new file mode 100644 index 0000000000..11fa9a2126 --- /dev/null +++ b/Microsoft.AspNet.Mvc/View/ViewDataDictionary.cs @@ -0,0 +1,72 @@ +using System; +using System.Collections.Generic; +using System.Dynamic; + +namespace Microsoft.AspNet.Mvc +{ + public class ViewDataDictionary : DynamicObject + { + private Dictionary _data; + + public ViewDataDictionary() + { + _data = new Dictionary(); + } + + public ViewDataDictionary(ViewDataDictionary source) + { + _data = new Dictionary(source._data); + } + + public object Model { get; set; } + + public override bool TryGetMember(GetMemberBinder binder, out object result) + { + result = _data[binder.Name]; + // We return true here because ViewDataDictionary returns null if the key is not + // in the dictionary, so we simply pass on the returned value. + return true; + } + + public override bool TrySetMember(SetMemberBinder binder, object value) + { + // This cast should always succeed assuming TValue is dynamic. + dynamic v = value; + _data[binder.Name] = v; + return true; + } + + public override bool TryGetIndex(GetIndexBinder binder, object[] indexes, out object result) + { + if (indexes == null || indexes.Length != 1) + { + throw new ArgumentException("Invalid number of indexes"); + } + + object index = indexes[0]; + + if (_data.TryGetValue(index, out result)) + { + result = _data[index]; + } + else + { + result = null; + } + return true; + } + + public override bool TrySetIndex(SetIndexBinder binder, object[] indexes, object value) + { + if (indexes == null || indexes.Length != 1) + { + throw new ArgumentException("Invalid number of indexes"); + } + + object index = indexes[0]; + // This cast should always succeed assuming TValue is dynamic. + _data[index] = (dynamic)value; + return true; + } + } +} diff --git a/Microsoft.AspNet.Mvc/View/ViewResult.cs b/Microsoft.AspNet.Mvc/View/ViewResult.cs index 70655f7426..0c8ff8249e 100644 --- a/Microsoft.AspNet.Mvc/View/ViewResult.cs +++ b/Microsoft.AspNet.Mvc/View/ViewResult.cs @@ -20,7 +20,7 @@ namespace Microsoft.AspNet.Mvc public string ViewName {get; set; } - public object Model { get; set; } + public ViewDataDictionary ViewData { get; set; } public async Task ExecuteResultAsync(RequestContext context) { @@ -35,7 +35,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 = new ViewContext(context.HttpContext, context.RouteData, Model) + var viewContext = new ViewContext(context.HttpContext, context.RouteData, ViewData) { ServiceProvider = _serviceProvider }; diff --git a/MvcSample/HomeController.cs b/MvcSample/HomeController.cs index 83eb50046f..3e0ec9789e 100644 --- a/MvcSample/HomeController.cs +++ b/MvcSample/HomeController.cs @@ -50,7 +50,8 @@ namespace MvcSample public IActionResult MyView() { - return Result.View(User()); + ViewData.Model = User(); + return Result.View(ViewData); } } } \ No newline at end of file diff --git a/MvcSample/MvcSample.csproj b/MvcSample/MvcSample.csproj index 490c09b182..870c49d0b4 100644 --- a/MvcSample/MvcSample.csproj +++ b/MvcSample/MvcSample.csproj @@ -74,8 +74,6 @@ - - diff --git a/MvcSample/Views/Home/MyView.cshtml b/MvcSample/Views/Home/MyView.cshtml index eafc38014b..97fc4cc938 100644 --- a/MvcSample/Views/Home/MyView.cshtml +++ b/MvcSample/Views/Home/MyView.cshtml @@ -1,2 +1,33 @@ -@{ Layout = "~/Views/Shared/_Layout.cshtml"; } -@DateTime.UtcNow \ No newline at end of file +@{ + Layout = "~/Views/Shared/_Layout.cshtml"; + ViewData.Title = "Home Page"; +} + +
+

ASP.NET

+

ASP.NET is a free web framework for building great Web sites and Web applications using HTML, CSS and JavaScript.

+

Learn more »

+
+ +
+
+

Getting started

+

+ ASP.NET MVC gives you a powerful, patterns-based way to build dynamic websites that + enables a clean separation of concerns and gives you full control over markup + for enjoyable, agile development. +

+

Learn more »

+
+
+

Get more libraries

+

NuGet is a free Visual Studio extension that makes it easy to add, remove, and update libraries and tools in Visual Studio projects.

+

Learn more »

+
+
+

Web Hosting

+

You can easily find a web hosting company that offers the right mix of features and price for your applications.

+

Learn more »

+
+
+ diff --git a/MvcSample/Views/Layout.cs b/MvcSample/Views/Layout.cs deleted file mode 100644 index eb8975bfb2..0000000000 --- a/MvcSample/Views/Layout.cs +++ /dev/null @@ -1,20 +0,0 @@ -using System; -using Microsoft.AspNet.Mvc.Razor; - -namespace MvcSample.Views -{ - [VirtualPath("~/Views/Shared/_Layout.cshtml")] - public class Layout : RazorView - { - public override void Execute() - { - WriteLiteral(""); - WriteLiteral(""); - WriteLiteral("

Hello world

"); - WriteLiteral("
"); - WriteLiteral(""); - } - } -} \ No newline at end of file diff --git a/MvcSample/Views/MyView.cs b/MvcSample/Views/MyView.cs deleted file mode 100644 index cd620ea51e..0000000000 --- a/MvcSample/Views/MyView.cs +++ /dev/null @@ -1,20 +0,0 @@ -using System; -using Microsoft.AspNet.Mvc.Razor; - -namespace MvcSample.Views -{ - [VirtualPath("~/Views/Home/MyView.cshtml")] - public class MyView : RazorView - { - public override void Execute() - { - Layout = "~/Views/Shared/_Layout.cshtml"; - WriteLiteral("
The time is now"); - Write(new HtmlString(DateTime.UtcNow.ToString())); - WriteLiteral(""); - Write(Model.Name); - Write(""); - WriteLiteral("
"); - } - } -} \ No newline at end of file diff --git a/MvcSample/Views/Shared/_Layout.cshtml b/MvcSample/Views/Shared/_Layout.cshtml index 088578cfd2..a9ee6506c1 100644 --- a/MvcSample/Views/Shared/_Layout.cshtml +++ b/MvcSample/Views/Shared/_Layout.cshtml @@ -1,11 +1,34 @@ - - - No title - - -
-

Hello world

- @RenderBody() + + + + + + @ViewData.Title - My ASP.NET Application + + + + +
+ @RenderBody() +
+ +
+ +