ViewViewComponentResult doesn't handle `~/` in view paths correctly
Fixes #2856
This commit is contained in:
parent
18c3ad25fb
commit
93d07147b2
|
|
@ -5,7 +5,6 @@ using System;
|
|||
using System.Globalization;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNet.Mvc.Rendering;
|
||||
using Microsoft.AspNet.Mvc.ViewComponents;
|
||||
using Microsoft.Framework.DependencyInjection;
|
||||
using Microsoft.Framework.Internal;
|
||||
|
||||
|
|
@ -18,6 +17,7 @@ namespace Microsoft.AspNet.Mvc
|
|||
{
|
||||
// {0} is the component name, {1} is the view name.
|
||||
private const string ViewPathFormat = "Components/{0}/{1}";
|
||||
private const string DefaultViewName = "Default";
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the view name.
|
||||
|
|
@ -63,9 +63,11 @@ namespace Microsoft.AspNet.Mvc
|
|||
{
|
||||
var viewEngine = ViewEngine ?? ResolveViewEngine(context);
|
||||
var viewData = ViewData ?? context.ViewData;
|
||||
var isNullOrEmptyViewName = string.IsNullOrEmpty(ViewName);
|
||||
|
||||
string qualifiedViewName;
|
||||
if (ViewName != null && ViewName.Length > 0 && ViewName[0] == '/')
|
||||
if (!isNullOrEmptyViewName &&
|
||||
(ViewName[0] == '~' || ViewName[0] == '/'))
|
||||
{
|
||||
// View name that was passed in is already a rooted path, the view engine will handle this.
|
||||
qualifiedViewName = ViewName;
|
||||
|
|
@ -83,11 +85,13 @@ namespace Microsoft.AspNet.Mvc
|
|||
// Areas/Blog/Views/Shared/Components/Cart/Default.cshtml
|
||||
//
|
||||
// This supports a controller or area providing an override for component views.
|
||||
var viewName = isNullOrEmptyViewName ? DefaultViewName : ViewName;
|
||||
|
||||
qualifiedViewName = string.Format(
|
||||
CultureInfo.InvariantCulture,
|
||||
ViewPathFormat,
|
||||
context.ViewComponentDescriptor.ShortName,
|
||||
ViewName ?? "Default");
|
||||
viewName);
|
||||
}
|
||||
|
||||
var view = FindView(context.ViewContext, viewEngine, qualifiedViewName);
|
||||
|
|
|
|||
|
|
@ -275,22 +275,53 @@ namespace Microsoft.AspNet.Mvc
|
|||
Assert.Equal(expected, ex.Message);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Execute_CallsFindPartialView_WithExpectedPath()
|
||||
[Theory]
|
||||
[InlineData(null)]
|
||||
[InlineData("")]
|
||||
public void Execute_CallsFindPartialView_WithExpectedPath_WhenViewNameIsNullOrEmpty(string viewName)
|
||||
{
|
||||
// Arrange
|
||||
var shortName = "SomeShortName";
|
||||
var viewData = new ViewDataDictionary(new EmptyModelMetadataProvider());
|
||||
var componentContext = GetViewComponentContext(new Mock<IView>().Object, viewData);
|
||||
componentContext.ViewComponentDescriptor.ShortName = shortName;
|
||||
var expectedViewName = $"Components/{shortName}/Default";
|
||||
var viewEngine = new Mock<ICompositeViewEngine>(MockBehavior.Strict);
|
||||
viewEngine
|
||||
.Setup(v => v.FindPartialView(It.IsAny<ActionContext>(), expectedViewName))
|
||||
.Returns(ViewEngineResult.Found(string.Empty, new Mock<IView>().Object))
|
||||
.Verifiable();
|
||||
|
||||
var componentResult = new ViewViewComponentResult();
|
||||
componentResult.ViewEngine = viewEngine.Object;
|
||||
componentResult.ViewData = viewData;
|
||||
componentResult.ViewName = viewName;
|
||||
|
||||
// Act & Assert
|
||||
componentResult.Execute(componentContext);
|
||||
viewEngine.Verify();
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("~/Home/Index/MyViewComponent1.cshtml")]
|
||||
[InlineData("~MyViewComponent2.cshtml")]
|
||||
[InlineData("/MyViewComponent3.cshtml")]
|
||||
public void Execute_CallsFindPartialView_WithExpectedPath_WhenViewNameIsSpecified(string viewName)
|
||||
{
|
||||
// Arrange
|
||||
var viewEngine = new Mock<ICompositeViewEngine>(MockBehavior.Strict);
|
||||
viewEngine
|
||||
.Setup(v => v.FindPartialView(It.IsAny<ActionContext>(),
|
||||
It.Is<string>(view => view.Contains("Components"))))
|
||||
.Setup(v => v.FindPartialView(It.IsAny<ActionContext>(), viewName))
|
||||
.Returns(ViewEngineResult.Found(string.Empty, new Mock<IView>().Object))
|
||||
.Verifiable();
|
||||
|
||||
var viewData = new ViewDataDictionary(new EmptyModelMetadataProvider());
|
||||
var componentContext = GetViewComponentContext(new Mock<IView>().Object, viewData);
|
||||
var componentResult = new ViewViewComponentResult();
|
||||
componentResult.ViewEngine = viewEngine.Object;
|
||||
componentResult.ViewData = viewData;
|
||||
var componentResult = new ViewViewComponentResult
|
||||
{
|
||||
ViewEngine = viewEngine.Object,
|
||||
ViewData = viewData,
|
||||
ViewName = viewName
|
||||
};
|
||||
|
||||
// Act & Assert
|
||||
componentResult.Execute(componentContext);
|
||||
|
|
|
|||
Loading…
Reference in New Issue