如何从自定义AuthorizeAttribute返回操作结果?

时间:2020-09-16 13:14:39

标签: asp.net-core error-handling attributes authorization actionresult

我正在将ASP.Net Core 3.1与Identity一起使用,并且尝试创建自定义的Authorization属性,该属性将测试某些属性,然后在出现问题时(或简单地)显示无重定向错误如果一切都好,那就什么都不做。


TL; DR -除了http状态代码(如403)之外,我找不到将信息传递到错误页面的方法。我想将属性中的信息(例如错误消息)传递给错误页面,而无需重定向用户,我也不知道该怎么做。


我已经实现了如下授权属性:

public class CustomValidationAttribute : AuthorizeAttribute, IAsyncAuthorizationFilter

然后我将此类用作Razor页面,控制器等上的属性。

[CustomValidation(some props here)]
public class SomePageModel : PageModel {}

在此CustomValidationAttribute中,我有一个重写的方法OnAuthorizationAsync,如果某些道具不满足传递给属性的要求,则该方法不返回任何内容或返回错误。太好了。

但是,除了没有简单的方法可以从此方法返回View结果之外,我设法找到了一种无需重定向即可显示错误的方法。在Startup.cs中,我添加了一些处理程序:

app.UseExceptionHandler("/error");
app.UseStatusCodePagesWithReExecute("/error/{0}");

现在,如果我从属性返回new ForbidResult()new UnathorizedResult(),一切正常-它不会重定向(用户停留在遇到错误的页面上)并且代码是正确地传递到错误处理程序(即401、403等)

在这种情况下,正在加载的视图是/ Error,这是一个路由如下的剃刀页面:@page "/error/{code?}"

问题是,当我尝试更加具体地对待错误时,我便开始遇到麻烦。首先,我找不到将消息从属性传递到错误的方法。

public async Task OnAuthorizationAsync(AuthorizationFilterContext context)
{
    ...
    // just passes the error code
    context.Result = new ForbidResult();

    // same, but has some useless properties like ViewData that won't be kept
    // nor will they be accessible from the target method, e.g. at ErrorModel.OnGet
    context.Result = new ViewResult() {
        StatusCode = (int) HttpStatusCode.Unathorized
    }

    // how do I make it more specific??
    // my wish of an ideal return is:
    context.Result = new ActionResult("Error", "OnGet", new ErrorViewModel { Message, StatusCode, ... }
    // ...but no way to do it
}

没有合适的Result类型可以返回-UnathorizedForbid之类的结果在其构造函数中没有任何特定的信息,ViewResult也没有,并且我唯一想得到的解决方案是返回ObjectResult,它实际上可以完成工作,但不加载页面布局等。(只是按原样返回文本)。

第二,理想情况下,我将错误页面作为局部视图加载,这将消耗包含要显示的信息的模型。这里也没有运气,因为PartialViewResult也没有接受任何参数。

谈论ViewResult,我知道我可以这样设置属性:

    context.Result = new PartialViewResult
    {
        StatusCode = (int)HttpStatusCode.Unauthorized
    };

但是该对象不保留信息。这意味着,错误页面的OnGet方法中什么都没有。

有人对此有解决方案或任何想法吗?我觉得这有点愚蠢,但是我已经尝试了很长时间,并且没有明显的方法可以实现我想要的目标。

0 个答案:

没有答案