這是我的 ActionFilter:
public class LogAttribute : ActionFilterAttribute
{
public LogAttribute(ILoggerFactory logger)
{
Logger = logger.CreateLogger<LogAttribute>();
}
public string UserId { get; set; }
public string Path { get; set; }
public ILogger Logger { get; }
public override void OnActionExecuting(ActionExecutingContext context)
{
var controller = context.Controller as Controller;
UserId = User.FindFirstValue(ClaimTypes.NameIdentifier);
Path = $"{context.HttpContext.Request.Path.Value}[{context.HttpContext.Request.Method}]";
Logger.LogDebug($"{Path} started. User(id): {UserId}.");
}
}
我想在我的控制器的其他地方使用 UserId 和 Path 屬性。有簡潔的方法嗎?
uj5u.com熱心網友回復:
我同意 Serge 的觀點,最好將 BaseController 用于此任務。沒有辦法用屬性清楚地做到這一點。
例如:
public abstract class BaseController<T> : Controller where T : ControllerBase
{
protected readonly ILogger<T> Logger;
protected BaseController(ILogger<T> logger)
{
Logger = logger;
}
protected string UserId { get; set; }
protected string Path { get; set; }
[NonAction]
public override void OnActionExecuting(ActionExecutingContext context)
{
UserId = User.FindFirstValue(ClaimTypes.NameIdentifier);
Path = $"{context.HttpContext.Request.Path.Value}[{context.HttpContext.Request.Method}]";
Logger.LogDebug($"{Path} started. User(id): {UserId}.");
}
}
public class HomeController : BaseController<HomeController>
{
public HomeController(ILogger<HomeController> logger): base(logger)
{
}
}
或者只是在您的特定控制器中使用覆寫 OnActionExecuting
public class HomeController: Controller
{
private readonly ILogger<HomeController> _logger;
private string _userId;
private string _path;
public HomeController(ILogger<HomeController> logger)
{
_logger = logger;
}
[NonAction]
public override void OnActionExecuting(ActionExecutingContext context)
{
_userId = User.FindFirstValue(ClaimTypes.NameIdentifier);
_path = $"{context.HttpContext.Request.Path.Value}
[{context.HttpContext.Request.Method}]";
_logger.LogDebug($"{Path} started. User(id): {UserId}.");
}
}
我將向您展示為此使用屬性的一些缺點。
1.您可以使用HttpContext.Items實作IDictionary<object,object>并且可以訪問請求(生命周期作為范圍)。但是為此您必須使用資源過濾器。
[AttributeUsage(AttributeTargets.Class)]
public class SampleLogAttribute : Attribute, IResourceFilter
{
public void OnResourceExecuting(ResourceExecutingContext context)
{
context.HttpContext.Items["path"] = $"{context.HttpContext.Request.Path}[{context.HttpContext.Request.Method}]";
context.HttpContext.Items["userId"] = "SomeUserIdFromResource";
}
public void OnResourceExecuted(ResourceExecutedContext context)
{
}
}
然后你可以使用 OnActionExecuting 從你的控制器中獲取它
private string _path;
private string _userId;
public override void OnActionExecuting(ActionExecutingContext context)
{
_path = HttpContext.Items["path"] as string;
_userId = HttpContext.Items["userId"] as string;
}
不這樣做的主要原因 - 您必須知道您的過濾器將值設定為Items并始終在控制器中創建它們。
2.您可以在屬性中使用反射設定私有值
public override void OnActionExecuting(ActionExecutingContext context)
{
var controller = context.Controller;
var path = controller.GetType().GetField("_path", BindingFlags.NonPublic | BindingFlags.Instance);
path?.SetValue(controller, $"{context.HttpContext.Request.Path}[{context.HttpContext.Request.Method}]");
var userId = controller.GetType().GetField("_userId", BindingFlags.NonPublic | BindingFlags.Instance);
userId?.SetValue(controller, "SomeUserId");
}
您必須明白,如果您忘記創建基本變數 - 您將無法訪問它們。
uj5u.com熱心網友回復:
如果我的問題是正確的...我們正在嘗試從當前的 Http Requet 中提取 UserId 和 Path(可能是查詢字串)?
如果是這樣,試試這個
public class LogAttribute : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext context)
{
var userId = context.HttpContext.User.FindFirst(ClaimTypes.NameIdentifier); // claims type depend on how we configure authentication. But many default fall into this constants.
var path = context.HttpContext.Request.Path;
var queryString = context.HttpContext.Request.QueryString;
//... Do whatever we need
}
}
uj5u.com熱心網友回復:
您可以創建基本控制器
public class BaseController : Controller
{
public BaseController(ILoggerFactory logger)
{
Logger = logger.CreateLogger<LogAttribute>();
}
protected string UserId { get; set; }
protected string Path { get; set; }
protected ILogger Logger { get; }
[NonAction]
public override void OnActionExecuting(ActionExecutingContext context)
{
var controllerActionDescriptor = context.ActionDescriptor as
ControllerActionDescriptor;
var controllerName = controllerActionDescriptor?.ControllerName;
var actionName = controllerActionDescriptor?.ActionName;
UserId = User.FindFirstValue(ClaimTypes.NameIdentifier);
Path = $"{context.HttpContext.Request.Path.Value}[{context.HttpContext.Request.Method}]";
Logger.LogDebug($"{Path} started. User(id): {UserId}.");
}
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/321736.html
