简体   繁体   English

在不更改url的情况下显示自定义页面

[英]Getting a custom page to show without changing the url

I want to show a page when users try to access something that they shouldn't. 当用户尝试访问不应访问的内容时,我想显示一个页面。 This restriction is check in custom middleware. 此限制是在自定义中间件中检查的。 When the middleware returns a false and the new controller gets called I don't want the client side url to change. 当中间件返回一个false并且新控制器被调用时,我不想更改客户端的url。

This is my middleware check: 这是我的中间件检查:

public async Task Invoke(HttpContext context, IAutorisationService service)
        {
            var user = service.CreateUserModel(context);
            var page = service.CreatePageModel(context);
            context.Items.Add("CurrentUser", user);

            if (service.UserAllowedToPage(user, page))
                await _next.Invoke(context);
            else
            {
                context.Response.Redirect("/Error/CustomError");
            }
        }

This is the error controller: 这是错误控制器:

public IActionResult CustomError()
        {
            if (!HttpContext.Items.TryGetValue("CurrentUser", out var o) || !(o is UserModel userModel))
            {
                return View();
            }

            if (userModel.IsSuperUser)
            {
                return View();
            }

The views returned here all work fine. 在这里返回的视图都工作正常。

This is my startup.cs (where I'm struggling now): 这是我的startup.cs(我现在在这里挣扎):

app.UseMvc(routes =>
            {
                //routes.MapRoute(
                    //name: "ErrorRoute",
                    //template: "{controller=Error}",
                    //defaults: new {controller = "Error", action = "CustomError"});

                routes.MapRoute(
                    name: "default",
                    template: "{controller=Home}/{action=Index}/{id?}");

            });

I just can't seem to get it right with any of the combinations I find on the web. 我在网上找到的任何组合似乎都无法正确实现。

Update 更新资料

Ok so I'm not getting any further with the policies. 好的,因此我对政策没有进一步的了解。 I'll try to explain my situation a bit better: I have a custom middleware at the end of the pipeline (just before app.UseMvc ) That middleware has a async Task Invoke method that calls a boolean operator in a different class. 我将尝试更好地解释我的情况:我在管道末尾(在app.UseMvc之前)有一个自定义中间件,该中间件具有异步Task Invoke方法,该方法在另一个类中调用布尔运算符。 Now if the boolean returns true the middleware task does: await _next.Invoke(HttpContext) and I want the middleware to excecute an exception if that boolean returns false. 现在,如果布尔值返回true,则中间件任务执行以下操作: await _next.Invoke(HttpContext) ,如果该布尔值返回false,我希望中间件执行异常。 And when the exception is thrown I want the: app.UseExceptionHandler("/Error/CustomError"); 并且当引发异常时,我想要: app.UseExceptionHandler("/Error/CustomError"); or the app.UseStatusCodePagesWithReExecute("/Error/CustomError"); app.UseStatusCodePagesWithReExecute("/Error/CustomError"); to catch it and activate the CustomError action in the ErrorController to then return a custom view. 捕获它并在ErrorController中激活CustomError操作,然后返回一个自定义视图。 Is this even possible? 这有可能吗? (Sorry if my first question wasn't complete) (对不起,如果我的第一个问题还没有完成)

hi you can return error view using 嗨,您可以使用返回错误视图

return View("Error")

you can check what ever you need and if something is wrong instead of the main view you can return the error view 您可以检查所需的内容,如果出现问题,可以代替主视图,然后返回错误视图

You cannot redirect to a page, without changing the URL. 您不能重定向到页面,而无需更改URL。 The redirect actually happens client-side. 重定向实际上发生在客户端。 The server simply sends a 302 response with a Location header containing the alternate URL. 服务器仅发送带有包含备用URL的Location标头的302响应。 It is the client's responsibility to actually make a request for that alternate URL, which is what browsers do by default. 客户有责任实际请求该备用URL,这是浏览器默认执行的操作。 As a result, the browser will literally be requesting /Error/CustomError . 结果,浏览器实际上将请求/Error/CustomError

What you need to do is return the actual error response directly from the middleware, so that the URL stays what it is. 您需要做的是直接从中间件返回实际的错误响应,以使URL保持原样。 However, middleware is the wrong approach here, actually. 但是,实际上,中间件在这里是错误的方法。

Instead, you should be using the built-in authorization framework. 相反,您应该使用内置的授权框架。 You can apply custom policies to controllers/actions by implementing requirements and handlers and then referencing the policy with the Authorize attribute: 您可以通过实现需求和处理程序,然后使用Authorize属性引用该策略,将自定义策略应用于控制器/操作。

[Authorize(Policy = "MyPolicy")]
public IActionResult MyProtectedAction()

Then, when the user fails to meet the policy requirements, they'll fall through into the exception handling middleware, where you can tie in your custom view via configuring app.UseStatusCodePagesWithReExecute : 然后,当用户不符合策略要求时,他们将陷入异常处理中间件,在中间件中,您可以通过配置app.UseStatusCodePagesWithReExecute来绑定自定义视图:

public class Startup
{
    ...

    public void Configure(IApplicationBuilder app, IHostingEnvironment env)
    {
        app.UseStatusCodePagesWithReExecute("/error/{0}");

        ...
    }
}

That will then execute the controller and action defined for the /error/{0} route, without affecting the URL (the "ReExecute" part). 然后将执行为/error/{0}路由定义的控制器和操作,而不会影响URL(“ ReExecute”部分)。 The {0} bit will be replaced with the the HTTP status code, which will be 401 Unauthorized . {0}位将被替换为HTTP状态代码,该状态代码将为401 Unauthorized So you can literally have an action tied to /error/401 or a catch all action with a route like /error/{statusCode} and then branch inside on the status code to handle multiple different error types. 因此,您可以按照字面上的方式将操作绑定到/error/401或使用/error/{statusCode}类的路由来捕获所有操作,然后在状态代码内分支以处理多种不同的错误类型。 For what it's worth, this is also how you'd provide custom 404 pages, 500 pages, etc. 对于它的价值,这也是您提供自定义404页,500页等的方式。

For more information see: 有关更多信息,请参见:

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM