ViewLocationExpanderContext should have a flag that indicates if the
lookup is for a full or partial view Fixes #1212
This commit is contained in:
parent
b821b706b7
commit
73f44889f2
|
|
@ -51,8 +51,10 @@ namespace Microsoft.AspNet.Mvc.Razor
|
||||||
var routeValues = context.ActionContext.RouteData.Values;
|
var routeValues = context.ActionContext.RouteData.Values;
|
||||||
var controller = routeValues.GetValueOrDefault<string>(RazorViewEngine.ControllerKey);
|
var controller = routeValues.GetValueOrDefault<string>(RazorViewEngine.ControllerKey);
|
||||||
|
|
||||||
// format is "{viewName}:{controllerName}:{areaName}:"
|
// format is "{viewName}:{isPartial}:{controllerName}:{areaName}:"
|
||||||
keyBuilder.Append(context.ViewName)
|
keyBuilder.Append(context.ViewName)
|
||||||
|
.Append(CacheKeySeparator)
|
||||||
|
.Append(context.IsPartial ? 1 : 0)
|
||||||
.Append(CacheKeySeparator)
|
.Append(CacheKeySeparator)
|
||||||
.Append(controller);
|
.Append(controller);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -104,7 +104,7 @@ namespace Microsoft.AspNet.Mvc.Razor
|
||||||
throw new ArgumentException(Resources.ArgumentCannotBeNullOrEmpty, nameof(viewName));
|
throw new ArgumentException(Resources.ArgumentCannotBeNullOrEmpty, nameof(viewName));
|
||||||
}
|
}
|
||||||
|
|
||||||
var pageResult = GetRazorPageResult(context, viewName);
|
var pageResult = GetRazorPageResult(context, viewName, isPartial: false);
|
||||||
return CreateViewEngineResult(pageResult, _viewFactory, isPartial: false);
|
return CreateViewEngineResult(pageResult, _viewFactory, isPartial: false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -117,7 +117,7 @@ namespace Microsoft.AspNet.Mvc.Razor
|
||||||
throw new ArgumentException(Resources.ArgumentCannotBeNullOrEmpty, nameof(partialViewName));
|
throw new ArgumentException(Resources.ArgumentCannotBeNullOrEmpty, nameof(partialViewName));
|
||||||
}
|
}
|
||||||
|
|
||||||
var pageResult = GetRazorPageResult(context, partialViewName);
|
var pageResult = GetRazorPageResult(context, partialViewName, isPartial: true);
|
||||||
return CreateViewEngineResult(pageResult, _viewFactory, isPartial: true);
|
return CreateViewEngineResult(pageResult, _viewFactory, isPartial: true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -130,11 +130,12 @@ namespace Microsoft.AspNet.Mvc.Razor
|
||||||
throw new ArgumentException(Resources.ArgumentCannotBeNullOrEmpty, nameof(pageName));
|
throw new ArgumentException(Resources.ArgumentCannotBeNullOrEmpty, nameof(pageName));
|
||||||
}
|
}
|
||||||
|
|
||||||
return GetRazorPageResult(context, pageName);
|
return GetRazorPageResult(context, pageName, isPartial: true);
|
||||||
}
|
}
|
||||||
|
|
||||||
private RazorPageResult GetRazorPageResult(ActionContext context,
|
private RazorPageResult GetRazorPageResult(ActionContext context,
|
||||||
string pageName)
|
string pageName,
|
||||||
|
bool isPartial)
|
||||||
{
|
{
|
||||||
if (IsApplicationRelativePath(pageName))
|
if (IsApplicationRelativePath(pageName))
|
||||||
{
|
{
|
||||||
|
|
@ -154,12 +155,13 @@ namespace Microsoft.AspNet.Mvc.Razor
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
return LocatePageFromViewLocations(context, pageName);
|
return LocatePageFromViewLocations(context, pageName, isPartial);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private RazorPageResult LocatePageFromViewLocations(ActionContext context,
|
private RazorPageResult LocatePageFromViewLocations(ActionContext context,
|
||||||
string pageName)
|
string pageName,
|
||||||
|
bool isPartial)
|
||||||
{
|
{
|
||||||
// Initialize the dictionary for the typical case of having controller and action tokens.
|
// Initialize the dictionary for the typical case of having controller and action tokens.
|
||||||
var routeValues = context.RouteData.Values;
|
var routeValues = context.RouteData.Values;
|
||||||
|
|
@ -169,7 +171,7 @@ namespace Microsoft.AspNet.Mvc.Razor
|
||||||
var viewLocations = !string.IsNullOrEmpty(areaName) ? AreaViewLocationFormats :
|
var viewLocations = !string.IsNullOrEmpty(areaName) ? AreaViewLocationFormats :
|
||||||
ViewLocationFormats;
|
ViewLocationFormats;
|
||||||
|
|
||||||
var expanderContext = new ViewLocationExpanderContext(context, pageName);
|
var expanderContext = new ViewLocationExpanderContext(context, pageName, isPartial);
|
||||||
if (_viewLocationExpanders.Count > 0)
|
if (_viewLocationExpanders.Count > 0)
|
||||||
{
|
{
|
||||||
expanderContext.Values = new Dictionary<string, string>(StringComparer.Ordinal);
|
expanderContext.Values = new Dictionary<string, string>(StringComparer.Ordinal);
|
||||||
|
|
|
||||||
|
|
@ -11,22 +11,35 @@ namespace Microsoft.AspNet.Mvc.Razor
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class ViewLocationExpanderContext
|
public class ViewLocationExpanderContext
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of <see cref="ViewLocationExpanderContext"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="actionContext">The <see cref="Mvc.ActionContext"/> for the current executing action.</param>
|
||||||
|
/// <param name="viewName">The view name.</param>
|
||||||
|
/// <param name="isPartial">Determines if the view being discovered is a partial.</param>
|
||||||
public ViewLocationExpanderContext([NotNull] ActionContext actionContext,
|
public ViewLocationExpanderContext([NotNull] ActionContext actionContext,
|
||||||
[NotNull] string viewName)
|
[NotNull] string viewName,
|
||||||
|
bool isPartial)
|
||||||
{
|
{
|
||||||
ActionContext = actionContext;
|
ActionContext = actionContext;
|
||||||
ViewName = viewName;
|
ViewName = viewName;
|
||||||
|
IsPartial = isPartial;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the <see cref="ActionContext"/> for the current executing action.
|
/// Gets the <see cref="Mvc.ActionContext"/> for the current executing action.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public ActionContext ActionContext { get; private set; }
|
public ActionContext ActionContext { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the view name
|
/// Gets the view name.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string ViewName { get; private set; }
|
public string ViewName { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets a value that determines if a partial view is being discovered.
|
||||||
|
/// </summary>
|
||||||
|
public bool IsPartial { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the <see cref="IDictionary{TKey, TValue}"/> that is populated with values as part of
|
/// Gets or sets the <see cref="IDictionary{TKey, TValue}"/> that is populated with values as part of
|
||||||
|
|
|
||||||
|
|
@ -165,6 +165,33 @@ component-content";
|
||||||
Assert.Equal(expected, body.Trim());
|
Assert.Equal(expected, body.Trim());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static TheoryData ViewLocationExpanders_PassesInIsPartialToViewLocationExpanderContextData
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return new TheoryData<string, string>
|
||||||
|
{
|
||||||
|
{ "Index", "<expander-view><shared-views>/Shared-Views/ExpanderViews/_ExpanderPartial.cshtml</shared-views></expander-view>" },
|
||||||
|
{ "Partial", "<shared-views>/Shared-Views/ExpanderViews/_ExpanderPartial.cshtml</shared-views>" }
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[MemberData(nameof(ViewLocationExpanders_PassesInIsPartialToViewLocationExpanderContextData))]
|
||||||
|
public async Task ViewLocationExpanders_PassesInIsPartialToViewLocationExpanderContext(string action, string expected)
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var server = TestServer.Create(_provider, _app);
|
||||||
|
var client = server.CreateClient();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var body = await client.GetStringAsync($"http://localhost/ExpanderViews/{action}");
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.Equal(expected, body.Trim());
|
||||||
|
}
|
||||||
|
|
||||||
public static IEnumerable<object[]> RazorViewEngine_RendersPartialViewsData
|
public static IEnumerable<object[]> RazorViewEngine_RendersPartialViewsData
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
|
|
|
||||||
|
|
@ -15,10 +15,12 @@ namespace Microsoft.AspNet.Mvc.Razor
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
yield return new[] { new ViewLocationExpanderContext(GetActionContext(), "test") };
|
yield return new[] { new ViewLocationExpanderContext(GetActionContext(), "test", isPartial: false) };
|
||||||
|
yield return new[] { new ViewLocationExpanderContext(GetActionContext(), "test", isPartial: true) };
|
||||||
|
|
||||||
var areaActionContext = GetActionContext("controller2", "myarea");
|
var areaActionContext = GetActionContext("controller2", "myarea");
|
||||||
yield return new[] { new ViewLocationExpanderContext(areaActionContext, "test2") };
|
yield return new[] { new ViewLocationExpanderContext(areaActionContext, "test2", isPartial: false) };
|
||||||
|
yield return new[] { new ViewLocationExpanderContext(areaActionContext, "test2", isPartial: true) };
|
||||||
|
|
||||||
var actionContext = GetActionContext("controller3", "area3");
|
var actionContext = GetActionContext("controller3", "area3");
|
||||||
var values = new Dictionary<string, string>(StringComparer.Ordinal)
|
var values = new Dictionary<string, string>(StringComparer.Ordinal)
|
||||||
|
|
@ -26,11 +28,16 @@ namespace Microsoft.AspNet.Mvc.Razor
|
||||||
{ "culture", "fr" },
|
{ "culture", "fr" },
|
||||||
{ "theme", "sleek" }
|
{ "theme", "sleek" }
|
||||||
};
|
};
|
||||||
var expanderContext = new ViewLocationExpanderContext(actionContext, "test3")
|
var expanderContext = new ViewLocationExpanderContext(actionContext, "test3", isPartial: false)
|
||||||
{
|
{
|
||||||
Values = values
|
Values = values
|
||||||
};
|
};
|
||||||
|
yield return new[] { expanderContext };
|
||||||
|
|
||||||
|
expanderContext = new ViewLocationExpanderContext(actionContext, "test3", isPartial: true)
|
||||||
|
{
|
||||||
|
Values = values
|
||||||
|
};
|
||||||
yield return new[] { expanderContext };
|
yield return new[] { expanderContext };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -71,15 +78,26 @@ namespace Microsoft.AspNet.Mvc.Razor
|
||||||
{
|
{
|
||||||
yield return new object[]
|
yield return new object[]
|
||||||
{
|
{
|
||||||
new ViewLocationExpanderContext(GetActionContext(), "test"),
|
new ViewLocationExpanderContext(GetActionContext(), "test", isPartial: false),
|
||||||
"test:mycontroller"
|
"test:0:mycontroller"
|
||||||
|
};
|
||||||
|
|
||||||
|
yield return new object[]
|
||||||
|
{
|
||||||
|
new ViewLocationExpanderContext(GetActionContext(), "test", isPartial: true),
|
||||||
|
"test:1:mycontroller"
|
||||||
};
|
};
|
||||||
|
|
||||||
var areaActionContext = GetActionContext("controller2", "myarea");
|
var areaActionContext = GetActionContext("controller2", "myarea");
|
||||||
yield return new object[]
|
yield return new object[]
|
||||||
{
|
{
|
||||||
new ViewLocationExpanderContext(areaActionContext, "test2"),
|
new ViewLocationExpanderContext(areaActionContext, "test2", isPartial: false),
|
||||||
"test2:controller2:myarea"
|
"test2:0:controller2:myarea"
|
||||||
|
};
|
||||||
|
yield return new object[]
|
||||||
|
{
|
||||||
|
new ViewLocationExpanderContext(areaActionContext, "test2", isPartial: true),
|
||||||
|
"test2:1:controller2:myarea"
|
||||||
};
|
};
|
||||||
|
|
||||||
var actionContext = GetActionContext("controller3", "area3");
|
var actionContext = GetActionContext("controller3", "area3");
|
||||||
|
|
@ -88,7 +106,7 @@ namespace Microsoft.AspNet.Mvc.Razor
|
||||||
{ "culture", "fr" },
|
{ "culture", "fr" },
|
||||||
{ "theme", "sleek" }
|
{ "theme", "sleek" }
|
||||||
};
|
};
|
||||||
var expanderContext = new ViewLocationExpanderContext(actionContext, "test3")
|
var expanderContext = new ViewLocationExpanderContext(actionContext, "test3", isPartial: false)
|
||||||
{
|
{
|
||||||
Values = values
|
Values = values
|
||||||
};
|
};
|
||||||
|
|
@ -96,7 +114,17 @@ namespace Microsoft.AspNet.Mvc.Razor
|
||||||
yield return new object[]
|
yield return new object[]
|
||||||
{
|
{
|
||||||
expanderContext,
|
expanderContext,
|
||||||
"test3:controller3:area3:culture:fr:theme:sleek"
|
"test3:0:controller3:area3:culture:fr:theme:sleek"
|
||||||
|
};
|
||||||
|
|
||||||
|
expanderContext = new ViewLocationExpanderContext(actionContext, "test3", isPartial: true)
|
||||||
|
{
|
||||||
|
Values = values
|
||||||
|
};
|
||||||
|
yield return new object[]
|
||||||
|
{
|
||||||
|
expanderContext,
|
||||||
|
"test3:1:controller3:area3:culture:fr:theme:sleek"
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,21 @@
|
||||||
|
// 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 ExpanderViewsController : Controller
|
||||||
|
{
|
||||||
|
// This result discovers the Index.cshtml from /View but the partial is executed from /Shared-Views
|
||||||
|
public ViewResult Index()
|
||||||
|
{
|
||||||
|
return View();
|
||||||
|
}
|
||||||
|
|
||||||
|
public PartialViewResult Partial()
|
||||||
|
{
|
||||||
|
return PartialView("_ExpanderPartial");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,35 @@
|
||||||
|
// 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 System.Collections.Generic;
|
||||||
|
using Microsoft.AspNet.Mvc.Razor;
|
||||||
|
|
||||||
|
namespace RazorWebSite
|
||||||
|
{
|
||||||
|
public class CustomPartialDirectoryViewLocationExpander : IViewLocationExpander
|
||||||
|
{
|
||||||
|
public void PopulateValues(ViewLocationExpanderContext context)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual IEnumerable<string> ExpandViewLocations(ViewLocationExpanderContext context,
|
||||||
|
IEnumerable<string> viewLocations)
|
||||||
|
{
|
||||||
|
if (context.IsPartial)
|
||||||
|
{
|
||||||
|
return ExpandViewLocationsCore(viewLocations);
|
||||||
|
}
|
||||||
|
|
||||||
|
return viewLocations;
|
||||||
|
}
|
||||||
|
|
||||||
|
private IEnumerable<string> ExpandViewLocationsCore(IEnumerable<string> viewLocations)
|
||||||
|
{
|
||||||
|
foreach (var location in viewLocations)
|
||||||
|
{
|
||||||
|
yield return "/Shared-Views/{1}/{0}.cshtml";
|
||||||
|
yield return location;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
@{
|
||||||
|
throw new Exception("This view should not be executed");
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
<shared-views>@ViewContext.View.Path</shared-views>
|
||||||
|
|
@ -27,6 +27,7 @@ namespace RazorWebSite
|
||||||
var expander = new LanguageViewLocationExpander(
|
var expander = new LanguageViewLocationExpander(
|
||||||
context => context.HttpContext.Request.Query["language-expander-value"]);
|
context => context.HttpContext.Request.Query["language-expander-value"]);
|
||||||
options.ViewLocationExpanders.Add(expander);
|
options.ViewLocationExpanders.Add(expander);
|
||||||
|
options.ViewLocationExpanders.Add(new CustomPartialDirectoryViewLocationExpander());
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
<expander-view>@Html.Partial("_ExpanderPartial")</expander-view>
|
||||||
Loading…
Reference in New Issue