c# - ActionFilters 用于获取用户 ID 并在为 null 时返回错误
问题描述
我有一个基类,我的(api)控制器从中继承。我这样做是为了让我可以从我的身份验证提供者那里获取用户 ID,然后用它来处理用户、更新它或获取它的数据等。
public class BaseController : ControllerBase
{
protected readonly IBaseData _baseData;
public BaseController(IBaseData baseData)
{
_baseData = baseData;
}
public Guid GetUserId()
{
string nameIdentifier = User.FindFirst(ClaimTypes.NameIdentifier).Value;
Guid? userId = _baseData.GetInvestorId(nameIdentifier);
return userId != null ? (Guid)userId : Guid.Empty;
}
}
然后我在我的 API 端点中调用它:
Guid userId = GetUserId();
BaseModel m = _userData.GetBaseModel(userId);
return Ok(m);
很简单。它在控制器中的多个位置被调用。不理想但工作正常。但是现在我需要捕获一个错误,该错误有时会在用户不在数据库中时发生。我可以向 API 端点添加一些代码来执行此操作:
Guid userId = GetUserId();
if (userId == Guid.Empty)
return NotFound(new ResponseGapiModel { Response = Response.NotFound, Message = "user not found in DB" });
BaseModel m = _userData.GetBaseModel(userId);
return Ok(m);
但这意味着我会在整个地方重复很多代码。我一直在尝试使用动作过滤器。但我无法理解它。我不知道如何在 actionfilter 中传递参数,比如我需要找到用户的名称标识符。也没有坦率地说如何将 ID 传回。
-更新-
我现在已经设法让 actionfilter 在找不到用户时返回失败的结果,所以我需要的一半有效。问题是现在我两次调用数据库,因为我仍然调用原始的 BaseCass GetUserId 来获取要在以后的方法中使用的 ID。
为了让 ActionFilter 检查丢失的用户,我将 datacontext 注入其中:
private readonly NodeDBContext _context;
public ValidateAuth0UserInDBAttribute(NodeDBContext context)
{
_context = context;
}
以及使用 ActionExecutingContext 中的 HttpContext 来查找我的用户 Nameidentifier:
public void OnActionExecuting(ActionExecutingContext context)
{
//check if the user it in DB
var id = _context.Users.SingleOrDefault(i => i.NameIdentifier == context.HttpContext.User.FindFirst(ClaimTypes.NameIdentifier).Value)?.Id;
if (id == null)
{
context.Result = new NotFoundObjectResult(new ResponseModel { Response = Response.UserNotFound, Message = "User not found in DB" });
return;
}
}
现在的问题是我如何将“id”从这里传回给我的控制器?有办法吗?还是我必须两次调用数据库?
解决方案
现在的问题是我如何将“id”从这里传回给我的控制器?
尝试使用以下代码将 id 传递回控制器:
public class MyActionFilter : Attribute,IActionFilter
{
public void OnActionExecuting(ActionExecutingContext context)
{
var id = _context.Users.SingleOrDefault(i => i.NameIdentifier == context.HttpContext.User.FindFirst(ClaimTypes.NameIdentifier).Value)?.Id;
if (id == null)
{
context.Result = new NotFoundObjectResult(new ResponseModel { Response = Response.UserNotFound, Message = "User not found in DB" });
return;
}
var controller = (ControllerBase)context.Controller;
controller.HttpContext.Items.Add("CurrentUserId", id );
}
public void OnActionExecuted(ActionExecutedContext context) { }
}
行动:
[MyActionFilter]
public IActionResult Get()
{
var id = HttpContext.Items["CurrentUserId"]?.ToString();
//...
}
推荐阅读
- visual-studio - 如何从 Visual Studio 为 Xamarin Forms 项目创建 IPA 文件
- python - 带有 2 个矩阵的向量场图 quiver
- xcode - 为什么在 Xcode 中总是要提交这么多文件?(即使在我刚刚提交它们之后。)
- c++ - 关于“有向图”的头文件给出了分段错误
- java - 有没有办法在 Ubuntu 上用 Java 创建系统托盘图标?
- sqlite - 如何修复“错误:此 QuadStore 未注册”?
- sql-server - 使用游标更新大量数据的问题
- javascript - 如何修复使用正则表达式验证用户名/密码的 .addEventListener 按钮
- opencv - 'cv2.cv2' 没有属性 'face'
- python - python中的staticmethod和classmethod不可调用吗?