RedirectToPage from a form-action handler includes the formaction
Fixes #6104
This commit is contained in:
parent
106b34867d
commit
3474bdf776
|
|
@ -89,9 +89,9 @@ namespace Microsoft.AspNetCore.Mvc
|
|||
}
|
||||
|
||||
var routeValues = new RouteValueDictionary(values);
|
||||
var ambientValues = urlHelper.ActionContext.RouteData.Values;
|
||||
if (pageName == null)
|
||||
{
|
||||
var ambientValues = urlHelper.ActionContext.RouteData.Values;
|
||||
if (!routeValues.ContainsKey("page") &&
|
||||
ambientValues.TryGetValue("page", out var value))
|
||||
{
|
||||
|
|
@ -103,6 +103,13 @@ namespace Microsoft.AspNetCore.Mvc
|
|||
routeValues["page"] = pageName;
|
||||
}
|
||||
|
||||
if (!routeValues.ContainsKey("formaction") &&
|
||||
ambientValues.TryGetValue("formaction", out var formaction))
|
||||
{
|
||||
// Clear out formaction unless it's explicitly specified in the routeValues.
|
||||
routeValues["formaction"] = null;
|
||||
}
|
||||
|
||||
return urlHelper.RouteUrl(
|
||||
routeName: null,
|
||||
values: routeValues,
|
||||
|
|
|
|||
|
|
@ -763,6 +763,34 @@ Microsoft.AspNetCore.Mvc.ViewFeatures.ViewDataDictionary`1[AspNetCore._InjectedP
|
|||
Assert.Equal(expected, response.Headers.Location.ToString());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task RedirectDoesNotIncludeFormActionByDefault()
|
||||
{
|
||||
// Arrange
|
||||
var expected = "/Pages/Redirects/RedirectFromFormActionHandler";
|
||||
|
||||
// Act
|
||||
var response = await Client.GetAsync("/Pages/Redirects/RedirectFromFormActionHandler/RedirectToPage/10");
|
||||
|
||||
// Assert
|
||||
Assert.Equal(HttpStatusCode.Redirect, response.StatusCode);
|
||||
Assert.Equal(expected, response.Headers.Location.ToString());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task RedirectToOtherHandlersWorks()
|
||||
{
|
||||
// Arrange
|
||||
var expected = "/Pages/Redirects/RedirectFromFormActionHandler/RedirectToPage/11";
|
||||
|
||||
// Act
|
||||
var response = await Client.GetAsync("/Pages/Redirects/RedirectFromFormActionHandler/RedirectToAnotherHandler/11");
|
||||
|
||||
// Assert
|
||||
Assert.Equal(HttpStatusCode.Redirect, response.StatusCode);
|
||||
Assert.Equal(expected, response.Headers.Location.ToString());
|
||||
}
|
||||
|
||||
private async Task AddAntiforgeryHeaders(HttpRequestMessage request)
|
||||
{
|
||||
var getResponse = await Client.GetAsync(request.RequestUri);
|
||||
|
|
|
|||
|
|
@ -27,9 +27,7 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages
|
|||
{
|
||||
RouteData = routeData,
|
||||
};
|
||||
var urlHelper = new Mock<IUrlHelper>();
|
||||
urlHelper.SetupGet(h => h.ActionContext)
|
||||
.Returns(actionContext);
|
||||
var urlHelper = CreateUrlHelper(actionContext);
|
||||
urlHelper.Setup(h => h.RouteUrl(It.IsAny<UrlRouteContext>()))
|
||||
.Callback((UrlRouteContext context) => actual = context);
|
||||
|
||||
|
|
@ -77,7 +75,7 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages
|
|||
{
|
||||
// Arrange
|
||||
UrlRouteContext actual = null;
|
||||
var urlHelper = new Mock<IUrlHelper>();
|
||||
var urlHelper = CreateUrlHelper();
|
||||
urlHelper.Setup(h => h.RouteUrl(It.IsAny<UrlRouteContext>()))
|
||||
.Callback((UrlRouteContext context) => actual = context);
|
||||
|
||||
|
|
@ -109,7 +107,7 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages
|
|||
{
|
||||
// Arrange
|
||||
UrlRouteContext actual = null;
|
||||
var urlHelper = new Mock<IUrlHelper>();
|
||||
var urlHelper = CreateUrlHelper();
|
||||
urlHelper.Setup(h => h.RouteUrl(It.IsAny<UrlRouteContext>()))
|
||||
.Callback((UrlRouteContext context) => actual = context);
|
||||
|
||||
|
|
@ -141,7 +139,7 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages
|
|||
{
|
||||
// Arrange
|
||||
UrlRouteContext actual = null;
|
||||
var urlHelper = new Mock<IUrlHelper>();
|
||||
var urlHelper = CreateUrlHelper();
|
||||
urlHelper.Setup(h => h.RouteUrl(It.IsAny<UrlRouteContext>()))
|
||||
.Callback((UrlRouteContext context) => actual = context);
|
||||
|
||||
|
|
@ -173,7 +171,7 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages
|
|||
{
|
||||
// Arrange
|
||||
UrlRouteContext actual = null;
|
||||
var urlHelper = new Mock<IUrlHelper>();
|
||||
var urlHelper = CreateUrlHelper();
|
||||
urlHelper.Setup(h => h.RouteUrl(It.IsAny<UrlRouteContext>()))
|
||||
.Callback((UrlRouteContext context) => actual = context);
|
||||
|
||||
|
|
@ -217,9 +215,7 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages
|
|||
RouteData = routeData,
|
||||
};
|
||||
|
||||
var urlHelper = new Mock<IUrlHelper>();
|
||||
urlHelper.SetupGet(p => p.ActionContext)
|
||||
.Returns(actionContext);
|
||||
var urlHelper = CreateUrlHelper(actionContext);
|
||||
urlHelper.Setup(h => h.RouteUrl(It.IsAny<UrlRouteContext>()))
|
||||
.Callback((UrlRouteContext context) => actual = context);
|
||||
|
||||
|
|
@ -246,5 +242,112 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages
|
|||
Assert.Equal("mytesthost", actual.Host);
|
||||
Assert.Equal("#toc", actual.Fragment);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Page_SetsFormActionToNull_IfValueIsNotSpecifiedInRouteValues()
|
||||
{
|
||||
// Arrange
|
||||
UrlRouteContext actual = null;
|
||||
var routeData = new RouteData
|
||||
{
|
||||
Values =
|
||||
{
|
||||
{ "page", "ambient-page" },
|
||||
{ "formaction", "ambient-formaction" },
|
||||
}
|
||||
};
|
||||
var actionContext = new ActionContext
|
||||
{
|
||||
RouteData = routeData,
|
||||
};
|
||||
|
||||
var urlHelper = CreateUrlHelper(actionContext);
|
||||
urlHelper.Setup(h => h.RouteUrl(It.IsAny<UrlRouteContext>()))
|
||||
.Callback((UrlRouteContext context) => actual = context);
|
||||
|
||||
// Act
|
||||
string page = null;
|
||||
urlHelper.Object.Page(page, new { id = 13 }, "https", "mytesthost", "#toc");
|
||||
|
||||
// Assert
|
||||
urlHelper.Verify();
|
||||
Assert.NotNull(actual);
|
||||
Assert.Null(actual.RouteName);
|
||||
Assert.Collection(Assert.IsType<RouteValueDictionary>(actual.Values),
|
||||
value =>
|
||||
{
|
||||
Assert.Equal("id", value.Key);
|
||||
Assert.Equal(13, value.Value);
|
||||
},
|
||||
value =>
|
||||
{
|
||||
Assert.Equal("page", value.Key);
|
||||
Assert.Equal("ambient-page", value.Value);
|
||||
},
|
||||
value =>
|
||||
{
|
||||
Assert.Equal("formaction", value.Key);
|
||||
Assert.Null(value.Value);
|
||||
});
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Page_UsesExplicitlySpecifiedFormActionValue()
|
||||
{
|
||||
// Arrange
|
||||
UrlRouteContext actual = null;
|
||||
var routeData = new RouteData
|
||||
{
|
||||
Values =
|
||||
{
|
||||
{ "page", "ambient-page" },
|
||||
{ "formaction", "ambient-formaction" },
|
||||
}
|
||||
};
|
||||
var actionContext = new ActionContext
|
||||
{
|
||||
RouteData = routeData,
|
||||
};
|
||||
|
||||
var urlHelper = CreateUrlHelper(actionContext);
|
||||
urlHelper.Setup(h => h.RouteUrl(It.IsAny<UrlRouteContext>()))
|
||||
.Callback((UrlRouteContext context) => actual = context);
|
||||
|
||||
// Act
|
||||
string page = null;
|
||||
urlHelper.Object.Page(page, new { formaction = "exact-formaction" }, "https", "mytesthost", "#toc");
|
||||
|
||||
// Assert
|
||||
urlHelper.Verify();
|
||||
Assert.NotNull(actual);
|
||||
Assert.Null(actual.RouteName);
|
||||
Assert.Collection(Assert.IsType<RouteValueDictionary>(actual.Values),
|
||||
value =>
|
||||
{
|
||||
Assert.Equal("formaction", value.Key);
|
||||
Assert.Equal("exact-formaction", value.Value);
|
||||
},
|
||||
value =>
|
||||
{
|
||||
Assert.Equal("page", value.Key);
|
||||
Assert.Equal("ambient-page", value.Value);
|
||||
});
|
||||
}
|
||||
|
||||
private static Mock<IUrlHelper> CreateUrlHelper(ActionContext context = null)
|
||||
{
|
||||
if (context == null)
|
||||
{
|
||||
context = new ActionContext
|
||||
{
|
||||
RouteData = new RouteData(),
|
||||
};
|
||||
}
|
||||
|
||||
var urlHelper = new Mock<IUrlHelper>();
|
||||
urlHelper.SetupGet(h => h.ActionContext)
|
||||
.Returns(context);
|
||||
return urlHelper;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages
|
|||
|
||||
var actionContext = new ActionContext(httpContext, new RouteData(), new ActionDescriptor());
|
||||
|
||||
var urlHelper = GetUrlHelper(returnValue: null);
|
||||
var urlHelper = GetUrlHelper(actionContext, returnValue: null);
|
||||
var result = new RedirectToPageResult("some-page", new Dictionary<string, object>())
|
||||
{
|
||||
UrlHelper = urlHelper,
|
||||
|
|
@ -64,7 +64,7 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages
|
|||
new RouteData(),
|
||||
new ActionDescriptor());
|
||||
|
||||
var urlHelper = GetUrlHelper(expectedUrl);
|
||||
var urlHelper = GetUrlHelper(actionContext, expectedUrl);
|
||||
var result = new RedirectToPageResult("MyPage", new { id = 10, test = "value" }, permanentRedirect)
|
||||
{
|
||||
UrlHelper = urlHelper,
|
||||
|
|
@ -89,10 +89,12 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages
|
|||
var pageContext = new PageContext
|
||||
{
|
||||
HttpContext = httpContext,
|
||||
RouteData = new RouteData(),
|
||||
};
|
||||
|
||||
UrlRouteContext context = null;
|
||||
var urlHelper = new Mock<IUrlHelper>();
|
||||
urlHelper.SetupGet(h => h.ActionContext).Returns(pageContext);
|
||||
urlHelper.Setup(h => h.RouteUrl(It.IsAny<UrlRouteContext>()))
|
||||
.Callback((UrlRouteContext c) => context = c)
|
||||
.Returns("some-value");
|
||||
|
|
@ -174,6 +176,62 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages
|
|||
});
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task RedirectToPage_DoesNotUseAmbientFormAction()
|
||||
{
|
||||
// Arrange
|
||||
var expected = "path/to/this-page";
|
||||
var httpContext = new Mock<HttpContext>();
|
||||
var httpResponse = new Mock<HttpResponse>();
|
||||
httpContext.SetupGet(c => c.Response)
|
||||
.Returns(httpResponse.Object);
|
||||
httpContext.SetupGet(c => c.RequestServices)
|
||||
.Returns(CreateServices());
|
||||
var routeData = new RouteData
|
||||
{
|
||||
Values =
|
||||
{
|
||||
["page"] = expected,
|
||||
["formaction"] = "delete",
|
||||
}
|
||||
};
|
||||
|
||||
var actionContext = new ActionContext(
|
||||
httpContext.Object,
|
||||
routeData,
|
||||
new ActionDescriptor());
|
||||
|
||||
UrlRouteContext context = null;
|
||||
var urlHelper = new Mock<IUrlHelper>();
|
||||
urlHelper.Setup(h => h.RouteUrl(It.IsAny<UrlRouteContext>()))
|
||||
.Callback((UrlRouteContext c) => context = c)
|
||||
.Returns("some-value");
|
||||
urlHelper.SetupGet(h => h.ActionContext)
|
||||
.Returns(actionContext);
|
||||
var pageName = (string)null;
|
||||
var result = new RedirectToPageResult(pageName)
|
||||
{
|
||||
UrlHelper = urlHelper.Object,
|
||||
};
|
||||
|
||||
// Act
|
||||
await result.ExecuteResultAsync(actionContext);
|
||||
|
||||
// Assert
|
||||
Assert.NotNull(context);
|
||||
Assert.Collection(Assert.IsType<RouteValueDictionary>(context.Values),
|
||||
value =>
|
||||
{
|
||||
Assert.Equal("page", value.Key);
|
||||
Assert.Equal(expected, value.Value);
|
||||
},
|
||||
value =>
|
||||
{
|
||||
Assert.Equal("formaction", value.Key);
|
||||
Assert.Null(value.Value);
|
||||
});
|
||||
}
|
||||
|
||||
private static IServiceProvider CreateServices(IUrlHelperFactory factory = null)
|
||||
{
|
||||
var services = new ServiceCollection();
|
||||
|
|
@ -192,9 +250,10 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages
|
|||
return services.BuildServiceProvider();
|
||||
}
|
||||
|
||||
private static IUrlHelper GetUrlHelper(string returnValue)
|
||||
private static IUrlHelper GetUrlHelper(ActionContext context, string returnValue)
|
||||
{
|
||||
var urlHelper = new Mock<IUrlHelper>();
|
||||
urlHelper.SetupGet(h => h.ActionContext).Returns(context);
|
||||
urlHelper.Setup(o => o.RouteUrl(It.IsAny<UrlRouteContext>())).Returns(returnValue);
|
||||
return urlHelper.Object;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,13 @@
|
|||
@page "{formaction?}/{id:int?}"
|
||||
@functions
|
||||
{
|
||||
public IActionResult OnGetRedirectToPage(int id)
|
||||
{
|
||||
return RedirectToPage();
|
||||
}
|
||||
|
||||
public IActionResult OnGetRedirectToAnotherHandler(int id)
|
||||
{
|
||||
return RedirectToPage(new { formaction = "RedirectToPage", id = id });
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue