。Net Core 3.1中的更改 请求路径

问题描述 投票:-1回答:2

3.0之前,我可以通过访问HttpRequestHttpContext属性,然后更改Path的值来更改请求的路径(无需任何形式的浏览器重定向)。

作为示例,为需要更改密码的用户显示页面(与用户打算访问的页面无关),我扩展了[[HttpContext

public static void ChangeDefaultPassword(this HttpContext context) => context.Request.Path = "/Account/ChangePassword";
这段代码将用户带到ChangePassword中的操作方法AccountController

不执行

用户打算访问的操作方法。然后进入dotnet core 3.1。

在3.1中,扩展方法更改路径。但是,它从不执行action方法。它

忽略

更新的路径。
我知道这是由于路由中的更改所致。现在可以使用扩展方法HttpContext.GetEndpoint()访问该端点。还有一个扩展方法HttpContext.SetEndpoint,它似乎是设置新端点的正确方法。但是,没有有关如何完成此操作的示例。

问题

如何更改请求路径,而不执行原始路径?

我尝试过的事情

    我尝试更改路径。似乎在dotnet core 3.1中的路由会忽略HttpRequest路径值的值。
  1. 我尝试使用context.Response.Redirect("/Account/ChangePassword");重定向。此方法有效,但是它
  2. first
  3. 执行了用户请求的原始操作方法。这种行为无法达到目的。我尝试使用扩展方法HttpContext.SetEndpoint,但没有可用的示例。
  • 3.0之前,我可以通过仅访问HttpContext的HttpRequest属性,然后更改Path的值来更改请求的路径(无需任何形式的浏览器重定向)。如...
  • .net-core url-routing asp.net-core-3.1 .net-core-3.1
    2个回答
    1
    投票
    protected override async Task HandleRequirementAsync(AuthorizationHandlerContext context, FooBarRequirement requirement) { var hasAccess = await requirement.CheckAccess(context.User); if (hasAccess) context.Succeed(requirement); else { var message = "You do not have access to this Foobar function"; AuthorizeHandler.NoPermission(mHttpContextAccessor.HttpContext, context, requirement, message); } }

    我写了一个静态类来处理重定向,传入控制器和操作所需的url以及错误消息,并将重定向永久标志设置为true:

    using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Http; namespace Foo.BusinessLogic.Security { public static class AuthorizeHandler { public static void NoPermission(HttpContext httpContext, AuthorizationHandlerContext context, IAuthorizationRequirement requirement, string errorMessage) { context.Succeed(requirement); httpContext.Response.Redirect($"/home/nopermission/?m={errorMessage}", true); } } }

    最后,是处理视图和消息的控制器和动作

    [AllowAnonymous] public IActionResult NoPermission(string m) { return View("NoPermission", m); } }


    0
    投票
    private static void RedirectToPath(this HttpContext context, string controllerName, string actionName ) { // Get the old endpoint to extract the RequestDelegate var currentEndpoint = context.GetEndpoint(); // Get access to the action descriptor collection var actionDescriptorsProvider = context.RequestServices.GetRequiredService<IActionDescriptorCollectionProvider>(); // Get the controller aqction with the action name and the controller name. // You should be redirecting to a GET action method anyways. Anyone can provide a better way of achieving this. var controllerActionDescriptor = actionDescriptorsProvider.ActionDescriptors.Items .Where(s => s is ControllerActionDescriptor bb && bb.ActionName == actionName && bb.ControllerName == controllerName && (bb.ActionConstraints == null || (bb.ActionConstraints != null && bb.ActionConstraints.Any(x => x is HttpMethodActionConstraint cc && cc.HttpMethods.Contains(HttpMethods.Get))))) .Select(s => s as ControllerActionDescriptor) .FirstOrDefault(); if (controllerActionDescriptor is null) throw new Exception($"You were supposed to be redirected to {actionName} but the action descriptor could not be found."); // Create a new route endpoint // The route pattern is not needed but MUST be present. var routeEndpoint = new RouteEndpoint(currentEndpoint.RequestDelegate, RoutePatternFactory.Parse(""), 1, new EndpointMetadataCollection(new object[] { controllerActionDescriptor }), controllerActionDescriptor.DisplayName); // set the new endpoint. You are assured that the previous endpoint will never execute. context.SetEndpoint(routeEndpoint); }

    重要

    您必须将操作方法​​的视图放置在Shared

    文件夹中,以使其可用。或者,您可以决定提供IViewLocationExpander的自定义实现
      访问端点之前,路由中间件必须已执行。
    © www.soinside.com 2019 - 2024. All rights reserved.