You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在ASP.NET中利用Base Controller记录用户操作并避免代码冗余?

Is Using BaseController for Operation Logging Reasonable? Are There Better Alternatives?

First off, using a BaseController to handle cross-cutting concerns like operation logging is totally valid—it’s a straightforward way to inject shared logic into all controllers that inherit from it, eliminating repetitive code across your actions. That said, there’s a more flexible alternative: Action Filters (implementing IActionFilter or AsyncActionFilter).

Filters are modular, decoupled from controller inheritance, and let you apply logging logic selectively: you can attach them to specific controllers, individual actions, or even register them globally for the entire app. This avoids forcing all controllers to inherit from your base class (which can be restrictive if some controllers don’t need logging). Plus, filters are easier to test in isolation and can be reused across different projects without tying to a base controller.


Answering Your Specific Code Questions

Let’s walk through how to solve each of your questions within your BaseController’s OnActionExecuting method:

1. Get the Current Controller Name

You can pull this from the RouteData in the ActionExecutingContext, or get the full type name of the controller instance:

// Gets the controller name without the "Controller" suffix (e.g., "Home")
var controllerName = context.RouteData.Values["controller"]?.ToString();

// Gets the full type name (e.g., "YourApp.Controllers.HomeController")
var fullControllerType = context.Controller.GetType().FullName;

2. Get the Current Action Method Name

Use the ActionDescriptor from the context to get the action name or its display name:

// Gets the action method name (e.g., "Index")
var actionName = context.ActionDescriptor.ActionName;

// Gets a more detailed display name (includes controller and action)
var actionDisplayName = context.ActionDescriptor.DisplayName;

3. Pass Additional Parameters

You have a few options here depending on your needs:

  • Access action method parameters: Use context.ActionArguments to grab values passed to the current action:
    // If your action has a parameter named "userId", retrieve it like this
    if (context.ActionArguments.TryGetValue("userId", out var userIdValue))
    {
        var userId = userIdValue.ToString();
        // Use userId in your log
    }
    
  • Use custom attributes: Create a custom attribute to attach metadata to actions, then read it in OnActionExecuting:
    // First define the attribute
    public class OperationLogAttribute : Attribute
    {
        public string Description { get; set; }
    }
    
    // Attach it to your action: [OperationLog(Description = "Updated user profile")]
    // Then read it in BaseController:
    var logAttribute = context.ActionDescriptor.EndpointMetadata
        .OfType<OperationLogAttribute>()
        .FirstOrDefault();
    if (logAttribute != null)
    {
        var operationDesc = logAttribute.Description;
        // Log the description
    }
    
  • Store data in HttpContext.Items: If you need to pass data from elsewhere in the pipeline, use context.HttpContext.Items["KeyName"] to retrieve it.

4. Get User Information

Since your BaseController inherits from Controller, you can directly use the built-in User property, or access it from the context’s HttpContext:

// Option 1: Use the Controller's User property
var currentUser = this.User;

// Option 2: Get from the context's HttpContext
var currentUser = context.HttpContext.User;

// Example: Get the user's ID from claims (assuming it's stored in NameIdentifier)
var userId = currentUser.FindFirst(System.Security.Claims.ClaimTypes.NameIdentifier)?.Value;
var userName = currentUser.Identity?.Name;

Modified BaseController Example

Here’s how your updated BaseController might look with all these pieces put together:

using System.Security.Claims;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;

public class BaseController : Controller 
{ 
    protected readonly ILogger logger; 

    public BaseController(ILogger<BaseController> logger) 
    { 
        this.logger = logger; 
    } 

    public override void OnActionExecuting(ActionExecutingContext context) 
    {
        // Get controller and action names
        var controllerName = context.RouteData.Values["controller"]?.ToString();
        var actionName = context.ActionDescriptor.ActionName;

        // Get user info
        var currentUser = context.HttpContext.User;
        var userId = currentUser.FindFirst(ClaimTypes.NameIdentifier)?.Value;
        var userName = currentUser.Identity?.Name;

        // Get custom operation description (if using the attribute)
        var logAttribute = context.ActionDescriptor.EndpointMetadata
            .OfType<OperationLogAttribute>()
            .FirstOrDefault();
        var operationDesc = logAttribute?.Description ?? "No description provided";

        // Log the operation
        logger.LogInformation("User {User} ({UserId}) executed {Controller}.{Action}: {Description}",
            userName, userId, controllerName, actionName, operationDesc);

        base.OnActionExecuting(context); 
    } 
}

// Custom attribute for operation metadata
public class OperationLogAttribute : Attribute
{
    public string Description { get; set; }
}

内容的提问来源于stack exchange,提问作者punkouter

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 04:03:51