我正在将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
类型可以返回-Unathorized
或Forbid
之类的结果在其构造函数中没有任何特定的信息,ViewResult
也没有,并且我唯一想得到的解决方案是返回ObjectResult
,它实际上可以完成工作,但不加载页面布局等。(只是按原样返回文本)。
第二,理想情况下,我将错误页面作为局部视图加载,这将消耗包含要显示的信息的模型。这里也没有运气,因为PartialViewResult
也没有接受任何参数。
谈论ViewResult
,我知道我可以这样设置属性:
context.Result = new PartialViewResult
{
StatusCode = (int)HttpStatusCode.Unauthorized
};
但是该对象不保留信息。这意味着,错误页面的OnGet
方法中什么都没有。
有人对此有解决方案或任何想法吗?我觉得这有点愚蠢,但是我已经尝试了很长时间,并且没有明显的方法可以实现我想要的目标。