Supporting Urls With ~/ while redirecting.

Fix for Issue#304
This commit is contained in:
harshgMSFT 2014-05-05 11:24:00 -07:00
parent 2ad5847132
commit 483e9038b4
3 changed files with 122 additions and 4 deletions

View File

@ -3,6 +3,7 @@
using System;
using Microsoft.AspNet.Mvc.Core;
using Microsoft.Framework.DependencyInjection;
namespace Microsoft.AspNet.Mvc
{
@ -30,10 +31,18 @@ namespace Microsoft.AspNet.Mvc
public override void ExecuteResult([NotNull] ActionContext context)
{
// It is redirected directly to the input URL.
// We would use the context to construct the full URL,
// only when relative URLs are supported. (Issue - WEBFX-202)
context.HttpContext.Response.Redirect(Url, Permanent);
var destinationUrl = Url;
var urlHelper = context.HttpContext
.RequestServices
.GetService<IUrlHelper>();
// IsLocalUrl is called to handle Urls starting with '~/'.
if (urlHelper.IsLocalUrl(destinationUrl))
{
destinationUrl = urlHelper.Content(Url);
}
context.HttpContext.Response.Redirect(destinationUrl, Permanent);
}
}
}

View File

@ -0,0 +1,108 @@
// 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;
using System.Collections.Generic;
using Microsoft.AspNet.Http;
using Microsoft.AspNet.Routing;
using Microsoft.Framework.DependencyInjection;
using Microsoft.Framework.DependencyInjection.Fallback;
using Moq;
using Xunit;
namespace Microsoft.AspNet.Mvc.Core.Test
{
public class RedirectResultTest
{
[Theory]
[InlineData("", "/Home/About", "/Home/About")]
[InlineData("/myapproot", "/test", "/test")]
public void Execute_ReturnsContentPath_WhenItDoesNotStartWithTilde(string appRoot,
string contentPath,
string expectedPath)
{
// Arrange
var httpResponse = new Mock<HttpResponse>();
httpResponse.Setup(o => o.Redirect(expectedPath, false))
.Verifiable();
var httpContext = GetHttpContext(appRoot, contentPath, expectedPath, httpResponse.Object);
var actionContext = GetActionContext(httpContext);
var result = new RedirectResult(contentPath);
// Act
result.ExecuteResult(actionContext);
// Assert
// Verifying if Redirect was called with the specific Url and parameter flag.
httpResponse.Verify();
}
[Theory]
[InlineData(null, "~/Home/About", "/Home/About")]
[InlineData("/", "~/Home/About", "/Home/About")]
[InlineData("/", "~/", "/")]
[InlineData("", "~/Home/About", "/Home/About")]
[InlineData("/myapproot", "~/", "/myapproot/")]
[InlineData("", "~/Home/About", "/Home/About")]
[InlineData("/myapproot", "~/", "/myapproot/")]
public void Execute_ReturnsAppRelativePath_WhenItStartsWithTilde(string appRoot,
string contentPath,
string expectedPath)
{
// Arrange
var httpResponse = new Mock<HttpResponse>();
httpResponse.Setup(o => o.Redirect(expectedPath, false))
.Verifiable();
var httpContext = GetHttpContext(appRoot, contentPath, expectedPath, httpResponse.Object);
var actionContext = GetActionContext(httpContext);
var result = new RedirectResult(contentPath);
// Act
result.ExecuteResult(actionContext);
// Assert
// Verifying if Redirect was called with the specific Url and parameter flag.
httpResponse.Verify();
}
private static ActionContext GetActionContext(HttpContext httpContext)
{
return new ActionContext(httpContext,
Mock.Of<IRouter>(),
new Dictionary<string, object>(),
new ActionDescriptor());
}
private static IServiceProvider GetServiceProvider(IUrlHelper urlHelper)
{
var serviceCollection = new ServiceCollection();
serviceCollection.AddInstance<IUrlHelper>(urlHelper);
return serviceCollection.BuildServiceProvider();
}
private static HttpContext GetHttpContext(string appRoot,
string contentPath,
string expectedPath,
HttpResponse response)
{
var httpContext = new Mock<HttpContext>();
var actionContext = GetActionContext(httpContext.Object);
var mockContentAccessor = new Mock<IContextAccessor<ActionContext>>();
mockContentAccessor.SetupGet(o => o.Value).Returns(actionContext);
var mockActionSelector = new Mock<IActionSelector>();
var urlHelper = new UrlHelper(mockContentAccessor.Object, mockActionSelector.Object);
var serviceProvider = GetServiceProvider(urlHelper);
httpContext.Setup(o => o.Response)
.Returns(response);
httpContext.SetupGet(o => o.RequestServices)
.Returns(serviceProvider);
httpContext.Setup(o => o.Request.PathBase)
.Returns(new PathString(appRoot));
return httpContext.Object;
}
}
}

View File

@ -25,6 +25,7 @@
<Compile Include="ActionExecutorTests.cs" />
<Compile Include="ActionResults\RedirectToActionResultTest.cs" />
<Compile Include="ActionResults\RedirectToRouteResultTest.cs" />
<Compile Include="ActionResults\RedirectResultTest.cs" />
<Compile Include="ActionSelectionConventionTests.cs" />
<Compile Include="AntiXsrf\AntiForgeryTokenSerializerTest.cs" />
<Compile Include="AntiXsrf\ITokenProvider.cs" />