-
Notifications
You must be signed in to change notification settings - Fork 2.1k
Adding IView.Path and ViewContext.ExecutingPagePath #1996
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -6,6 +6,9 @@ | |
|
||
namespace Microsoft.AspNet.Mvc | ||
{ | ||
/// <summary> | ||
/// Context for view execution. | ||
/// </summary> | ||
public class ViewContext : ActionContext | ||
{ | ||
// We need a default FormContext if the user uses html <form> instead of an MvcForm | ||
|
@@ -14,6 +17,13 @@ public class ViewContext : ActionContext | |
private FormContext _formContext; | ||
private DynamicViewData _viewBag; | ||
|
||
/// <summary> | ||
/// Initializes a new instance of <see cref="ViewContext"/>. | ||
/// </summary> | ||
/// <param name="actionContext">The <see cref="ActionContext"/>.</param> | ||
/// <param name="view">The <see cref="IView"/> being rendered.</param> | ||
/// <param name="viewData">The <see cref="ViewDataDictionary"/>.</param> | ||
/// <param name="writer">The <see cref="TextWriter"/> to render output to.</param> | ||
public ViewContext( | ||
[NotNull] ActionContext actionContext, | ||
[NotNull] IView view, | ||
|
@@ -31,6 +41,13 @@ public ViewContext( | |
ValidationMessageElement = "span"; | ||
} | ||
|
||
/// <summary> | ||
/// Initializes a new instance of <see cref="ViewContext"/>. | ||
/// </summary> | ||
/// <param name="viewContext">The <see cref="ViewContext"/> to copy values from.</param> | ||
/// <param name="view">The <see cref="IView"/> being rendered.</param> | ||
/// <param name="viewData">The <see cref="ViewDataDictionary"/>.</param> | ||
/// <param name="writer">The <see cref="TextWriter"/> to render output to.</param> | ||
public ViewContext( | ||
[NotNull] ViewContext viewContext, | ||
[NotNull] IView view, | ||
|
@@ -49,6 +66,10 @@ public ViewContext( | |
Writer = writer; | ||
} | ||
|
||
/// <summary> | ||
/// Gets or sets the <see cref="Mvc.FormContext"/> for the form element being rendered. | ||
/// A default context is returned if no form is currently being rendered. | ||
/// </summary> | ||
public virtual FormContext FormContext | ||
{ | ||
get | ||
|
@@ -62,6 +83,9 @@ public virtual FormContext FormContext | |
} | ||
} | ||
|
||
/// <summary> | ||
/// Gets or sets a value that indicates whether client-side validation is enabled. | ||
/// </summary> | ||
public bool ClientValidationEnabled { get; set; } | ||
|
||
/// <summary> | ||
|
@@ -84,6 +108,9 @@ public virtual FormContext FormContext | |
/// </summary> | ||
public string ValidationMessageElement { get; set; } | ||
|
||
/// <summary> | ||
/// Gets the dynamic view bag. | ||
/// </summary> | ||
public dynamic ViewBag | ||
{ | ||
get | ||
|
@@ -97,12 +124,30 @@ public dynamic ViewBag | |
} | ||
} | ||
|
||
/// <summary> | ||
/// Gets or sets the <see cref="IView"/> currently being rendered, if any. | ||
/// </summary> | ||
public IView View { get; set; } | ||
|
||
/// <summary> | ||
/// Gets or sets the <see cref="ViewDataDictionary"/>. | ||
/// </summary> | ||
public ViewDataDictionary ViewData { get; set; } | ||
|
||
/// <summary> | ||
/// Gets or sets the <see cref="TextWriter"/> used to write the output. | ||
/// </summary> | ||
public TextWriter Writer { get; set; } | ||
|
||
/// <summary> | ||
/// Gets or sets the path of the view file currently being rendered. | ||
/// </summary> | ||
/// <remarks> | ||
/// The rendering of a view may involve one or more files (e.g. _ViewStart, Layouts etc). | ||
/// This property contains the path of the file currently being rendered. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nit: remove first "being rendered" and (perhaps) add "specific" before "file currently" |
||
/// </remarks> | ||
public string ExecutingFilePath { get; set; } | ||
|
||
public FormContext GetFormContextForClientValidation() | ||
{ | ||
return (ClientValidationEnabled) ? FormContext : null; | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -42,6 +42,9 @@ public RazorView(IRazorViewEngine viewEngine, | |
IsPartial = isPartial; | ||
} | ||
|
||
/// <inheritdoc /> | ||
public string Path => RazorPage.Path; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nit: ick; can't we limit ourselves to properties that look like properties? in this case, There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Sadly not. Plus having the auto property just creates an unnecessary field There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. you're trading off an unnecessary delegate (or two, depending on the IL generation) and its backing field against a single backing field? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The generated code looks like: public string Path
{
get { return RazorPage.Path; }
} There are no delegates \ backing field in the generated code . There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. faster w/ the testing than I 😄 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @pranavkm not sure the team's bought into using the new syntax for this. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We got an ok from the engineering team to use C# 6.0 features that aren't experimental. That said, seeing this is so contentious I'll just switch back to using a regular property declaration. |
||
|
||
/// <summary> | ||
/// Gets <see cref="IRazorPage"/> instance that the views executes on. | ||
/// </summary> | ||
|
@@ -93,7 +96,9 @@ private async Task<IBufferedTextWriter> RenderPageAsync(IRazorPage page, | |
// The writer for the body is passed through the ViewContext, allowing things like HtmlHelpers | ||
// and ViewComponents to reference it. | ||
var oldWriter = context.Writer; | ||
var oldFilePath = context.ExecutingFilePath; | ||
context.Writer = writer; | ||
context.ExecutingFilePath = page.Path; | ||
|
||
try | ||
{ | ||
|
@@ -109,6 +114,7 @@ private async Task<IBufferedTextWriter> RenderPageAsync(IRazorPage page, | |
finally | ||
{ | ||
context.Writer = oldWriter; | ||
context.ExecutingFilePath = oldFilePath; | ||
writer.Dispose(); | ||
} | ||
} | ||
|
@@ -131,12 +137,21 @@ private async Task RenderViewStartAsync(ViewContext context) | |
var viewStarts = _viewStartProvider.GetViewStartPages(RazorPage.Path); | ||
|
||
string layout = null; | ||
foreach (var viewStart in viewStarts) | ||
var oldFilePath = context.ExecutingFilePath; | ||
try | ||
{ | ||
foreach (var viewStart in viewStarts) | ||
{ | ||
context.ExecutingFilePath = viewStart.Path; | ||
// Copy the layout value from the previous view start (if any) to the current. | ||
viewStart.Layout = layout; | ||
await RenderPageCoreAsync(viewStart, context); | ||
layout = viewStart.Layout; | ||
} | ||
} | ||
finally | ||
{ | ||
// Copy the layout value from the previous view start (if any) to the current. | ||
viewStart.Layout = layout; | ||
await RenderPageCoreAsync(viewStart, context); | ||
layout = viewStart.Layout; | ||
context.ExecutingFilePath = oldFilePath; | ||
} | ||
|
||
// Copy over interesting properties from the ViewStart page to the entry page. | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
<Layout> | ||
/Views/ViewWithPaths/_Layout.cshtml | ||
/Views/ViewWithPaths/Index.cshtml | ||
</Layout> | ||
|
||
<ViewStart> | ||
Views\ViewWithPaths\_ViewStart.cshtml | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. why is this case using the Windows-specific path separator? should be consistent whatever we're rendering There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Interestingly, the VIewStart path generation is the only one that goes through There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. agree a separate issue might come of this but I wouldn't file it unless we get complaints. it's an existing problem that's just made a bit more visible here. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
IMO worth considering in a follow-up. Will be wierd if half of the system normalizes paths and the other doesn't. Also recall our discussion last week about the hidden cost of There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
/Views/ViewWithPaths/Index.cshtml | ||
</ViewStart> | ||
<Index> | ||
/Views/ViewWithPaths/Index.cshtml | ||
/Views/ViewWithPaths/Index.cshtml | ||
<component> | ||
/Views/Shared/Components/ComponentForViewWithPaths/Default.cshtml | ||
/Views/Shared/Components/ComponentForViewWithPaths/Default.cshtml | ||
</component> | ||
<Partial> | ||
/Views/ViewWithPaths/_Partial.cshtml | ||
/Views/ViewWithPaths/_Partial.cshtml | ||
</Partial> | ||
</Index> |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. | ||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. | ||
|
||
using Microsoft.AspNet.Mvc; | ||
|
||
namespace MvcSample.Web.Components | ||
{ | ||
[ViewComponent(Name = "ComponentForViewWithPaths")] | ||
public class ComponentForViewWithPaths : ViewComponent | ||
{ | ||
public IViewComponentResult Invoke() | ||
{ | ||
return View(); | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. | ||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. | ||
|
||
using Microsoft.AspNet.Mvc; | ||
|
||
namespace RazorWebSite.Controllers | ||
{ | ||
public class ViewWithPathsController : Controller | ||
{ | ||
[HttpGet("/ViewWithPaths")] | ||
public IActionResult Index() | ||
{ | ||
return View(); | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
<component> | ||
@ViewContext.ExecutingFilePath | ||
@ViewContext.View.Path | ||
</component> |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
<Index> | ||
@ViewContext.ExecutingFilePath | ||
@ViewContext.View.Path | ||
@Component.Invoke("ComponentForViewWithPaths") | ||
@Html.Partial("_Partial") | ||
</Index> |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
<Layout> | ||
@ViewContext.ExecutingFilePath | ||
@ViewContext.View.Path | ||
</Layout> | ||
@RenderBody() |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
<Partial> | ||
@ViewContext.ExecutingFilePath | ||
@ViewContext.View.Path | ||
</Partial> |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
@{ | ||
Layout = "_Layout"; | ||
} | ||
<ViewStart> | ||
@ViewContext.ExecutingFilePath | ||
@ViewContext.View.Path | ||
</ViewStart> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
doesn't this come from the view engine? there's nothing stopping you from using this outside of
ViewResult
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍