ASP.NET Core MVC 核心架构深度解析

ASP.NET Core MVC 核心架构深度解析

本文基于 ASP.NET Core 10 源码,深入剖析 MVC 框架的核心组件、请求处理链路、状态机实现及性能优化策略。

一、整体架构总览

MVC Core 的请求处理分为 7 个核心层次
📦 模型层
🏭 执行器层
🔧 调用器层
🎯 端点工厂层
⚙️ 中间件层
🌐 传输层
HTTP Request
Endpoint Routing Middleware
ControllerRequestDelegateFactory
ResourceInvoker

过滤器管道状态机
ControllerActionInvoker

Action执行状态机
ActionMethodExecutor
IActionResultExecutor
ApplicationModel

ControllerModel

ActionModel


二、启动与依赖注入阶段

2.1 服务注册的三个层次

csharp 复制代码
// API 文档:Microsoft.AspNetCore.Builder.MvcApplicationBuilderExtensions

// 层级1:最底层 - 仅 MVC 核心能力(60+ 服务)
services.AddMvcCore();

// 层级2:API 专用 - 核心 + API 相关功能
services.AddControllers();

// 层级3:完整 MVC - 核心 + API + Views + Razor Pages
services.AddMvc();

2.2 核心服务注册分类

AddMvcCore() 注册的服务可分为以下类别:

分类 关键服务 生命周期
应用模型 IApplicationModelFactoryIApplicationModelProvider Singleton
动作发现 IControllerFeatureProviderControllerActionDescriptorProvider Singleton
控制器创建 IControllerFactoryIControllerActivator Singleton
动作调用 ControllerActionInvokerCacheActionInvokerFactory Singleton
模型绑定 IModelBinderFactoryIModelMetadataProvider Singleton
结果执行 IActionResultExecutor<T> 各实现 Singleton
路由 ControllerActionEndpointDataSourceFactory Singleton

源码位置src/Mvc/Mvc.Core/src/DependencyInjection/MvcCoreServiceCollectionExtensions.cs


三、应用程序模型系统

3.1 模型层次结构

ApplicationModel 是 MVC 框架的核心数据结构,采用三层树形结构:

csharp 复制代码
// 简化模型
public class ApplicationModel
{
    public IList<ControllerModel> Controllers { get; }
    public IList<IFilterMetadata> Filters { get; }
    public IDictionary<object, object?> Properties { get; }
}

public class ControllerModel
{
    public TypeInfo ControllerType { get; }
    public IList<ActionModel> Actions { get; }
    public string? ControllerName { get; }
    public string? RouteTemplate { get; }
}

public class ActionModel
{
    public MethodInfo ActionMethod { get; }
    public IList<ParameterModel> Parameters { get; }
    public string? ActionName { get; }
    public IList<SelectorModel> Selectors { get; }
}

public class ParameterModel
{
    public ParameterInfo ParameterInfo { get; }
    public BindingInfo? BindingInfo { get; }
    public string ParameterName { get; }
}

3.2 构建流程

csharp 复制代码
// ApplicationModelFactory.CreateApplicationModel() 核心流程
public ApplicationModel CreateApplicationModel(IEnumerable<ControllerTypeInfo> controllerTypes)
{
    var application = new ApplicationModel();
    
    // 步骤1:按 Order 顺序执行所有 IApplicationModelProvider
    foreach (var provider in _orderedProviders)
    {
        provider.OnProvidersExecuting(applicationContext);
    }
    
    // 步骤2:应用所有 IApplicationModelConvention
    foreach (var convention in _conventions)
    {
        convention.Apply(application);
    }
    
    return application;
}

3.3 Provider 执行顺序

Provider Order 职责
DefaultApplicationModelProvider -1000 反射扫描控制器、动作、参数
ApiBehaviorApplicationModelProvider -900 配置 API 特定行为(如自动 400 响应)
AuthorizationApplicationModelProvider -800 处理 [Authorize] 特性
CorsApplicationModelProvider -700 处理跨域配置

设计要点:Order 值越小越先执行,确保基础模型先构建,后续 Provider 在其基础上扩展。


四、控制器发现与创建

4.1 控制器发现机制

ControllerFeatureProvider 负责从 ApplicationPart 中发现控制器类型:

csharp 复制代码
public class ControllerFeatureProvider : IApplicationFeatureProvider<ControllerFeature>
{
    public void PopulateFeature(IEnumerable<ApplicationPart> parts, ControllerFeature feature)
    {
        foreach (var part in parts.OfType<IApplicationPartTypeProvider>())
        {
            foreach (var type in part.Types)
            {
                if (IsController(type))
                {
                    feature.Controllers.Add(type);
                }
            }
        }
    }
    
    protected virtual bool IsController(TypeInfo typeInfo)
    {
        // 判定条件:
        // 1. 公开类型,非抽象,非泛型
        // 2. 继承 ControllerBase 或标记 [Controller] 特性
        // 3. 不是可见性类型(用于视图组件等)
        return typeInfo.IsPublic 
            && !typeInfo.IsAbstract 
            && !typeInfo.IsGenericTypeDefinition
            && (typeof(ControllerBase).IsAssignableFrom(typeInfo)
                || typeInfo.IsDefined(typeof(ControllerAttribute)));
    }
}

4.2 控制器激活

csharp 复制代码
// DefaultControllerActivator.cs - 控制器创建核心
public class DefaultControllerActivator : IControllerActivator
{
    private readonly ITypeActivatorCache _typeActivatorCache;
    
    public object Create(ControllerContext context)
    {
        var controllerType = context.ActionDescriptor.ControllerTypeInfo.AsType();
        
        // 通过 DI 容器创建实例,支持构造函数注入
        return _typeActivatorCache.CreateInstance(
            context.HttpContext.RequestServices, 
            controllerType);
    }
    
    public void Release(ControllerContext context, object controller)
    {
        // 释放 disposable 控制器
        (controller as IDisposable)?.Dispose();
    }
}

五、过滤器管道状态机

这是 MVC Core 最精妙的设计 ,使用状态机模式而非递归来实现过滤器管道。

5.1 过滤器类型与执行顺序

阶段 过滤器类型 接口 短路能力
1 Authorization Filter IAuthorizationFilter / IAsyncAuthorizationFilter ✅ 可短路
2 Resource Filter IResourceFilter / IAsyncResourceFilter ✅ 可短路
3 Action Filter IActionFilter / IAsyncActionFilter ❌ 仅影响 Action
4 Exception Filter IExceptionFilter / IAsyncExceptionFilter ✅ 仅异常时触发
5 Result Filter IResultFilter / IAsyncResultFilter ❌ 仅影响 Result
6 Always Run Result Filter IAlwaysRunResultFilter ✅ 短路后仍执行

5.2 状态机状态定义

csharp 复制代码
// ResourceInvoker 内部状态枚举
private enum State
{
    InvokeBegin,
    AuthorizationBegin,
    AuthorizationNext,
    AuthorizationEnd,
    ResourceBegin,
    ResourceNext,
    ResourceInside,
    ExceptionBegin,
    ExceptionNext,
    ExceptionEnd,
    ActionBegin,
    ActionNext,
    ActionInside,
    ActionEnd,
    ResultBegin,
    ResultNext,
    ResultEnd,
    InvokeEnd
}

5.3 状态转换流程

无短路
短路
无短路
短路
无异常
异常
InvokeBegin
AuthorizationBegin
AuthorizationNext
AuthorizationEnd
AlwaysRunResultFilters
ResourceBegin
ResourceNext
ResourceInside
ResultBegin
ActionBegin
ActionNext
ActionInside
ExceptionBegin
ActionEnd
ExceptionNext
ResultNext
InvokeEnd

5.4 状态机核心代码模式

csharp 复制代码
internal sealed class ResourceInvoker
{
    private State _state = State.InvokeBegin;
    private Task? _currentTask;
    
    public async Task InvokeAsync()
    {
        while (_next != null)
        {
            switch (_state)
            {
                case State.InvokeBegin:
                    _state = State.AuthorizationBegin;
                    break;
                    
                case State.AuthorizationBegin:
                    _state = await InvokeAuthorizationFilterAsync();
                    break;
                    
                case State.ResourceBegin:
                    _state = await InvokeResourceFilterAsync();
                    break;
                    
                // ... 其他状态处理
            }
        }
    }
}

设计要点

  • 状态机避免递归调用产生的堆栈分配
  • 短路时直接跳转到 AlwaysRunResultFilters,确保必要的清理逻辑执行
  • IAlwaysRunResultFilter 即使在前置阶段短路也会执行(如日志记录)

六、Action 执行策略

6.1 策略模式结构

ActionMethodExecutor 使用策略模式处理 8 种返回类型

返回类型 执行器 处理方式
void VoidResultExecutor EmptyResult
IActionResult (同步) SyncActionResultExecutor 直接返回
object (同步) SyncObjectResultExecutor 通过 IActionResultTypeMapper 转换
Task TaskResultExecutor await → EmptyResult
自定义 awaitable void AwaitableResultExecutor await → EmptyResult
Task<IActionResult> TaskOfIActionResultExecutor await → 直接返回
Task<SomeResult> TaskOfActionResultExecutor await → 通过 Mapper 转换
Task<object> AwaitableObjectResultExecutor await → 通过 Mapper 转换

6.2 执行器选择逻辑

csharp 复制代码
internal static ActionMethodExecutor GetExecutor(MethodInfo methodInfo)
{
    var returnType = methodInfo.ReturnType;
    
    // 1. 同步 void
    if (returnType == typeof(void))
        return VoidResult;
    
    // 2. 同步 IActionResult
    if (typeof(IActionResult).IsAssignableFrom(returnType))
        return SyncActionResult;
    
    // 3. 同步 object (非 Task 返回类型)
    if (!typeof(Task).IsAssignableFrom(returnType))
        return SyncObjectResult;
    
    // 4. 异步处理 Task<T> 等
    // ... 省略详细判断逻辑
}

七、ActionResult 处理机制

7.1 ActionResult 的设计

csharp 复制代码
public sealed class ActionResult<TValue> : IConvertToActionResult
{
    private readonly ActionResult? _result;
    private readonly TValue? _value;
    
    // 隐式转换 1: TValue → ActionResult<TValue>
    public static implicit operator ActionResult<TValue>(TValue value)
        => new ActionResult<TValue>(value);
    
    // 隐式转换 2: ActionResult → ActionResult<TValue>
    public static implicit operator ActionResult<TValue>(ActionResult result)
        => new ActionResult<TValue>(result);
    
    public IActionResult Convert()
    {
        if (_result != null)
            return _result;
        
        // TValue 自动包装为 200 OK 响应
        return new ObjectResult(_value) { StatusCode = 200 };
    }
}

7.2 类型转换接口

csharp 复制代码
// IConvertToActionResult.cs
public interface IConvertToActionResult
{
    IActionResult Convert();
}

IActionResultTypeMapper.Convert() 调用此接口完成最终转换。

7.3 使用示例

csharp 复制代码
[ApiController]
public class UsersController : ControllerBase
{
    // 直接返回值 → 自动转换为 200 OK
    public ActionResult<UserDto> Get(int id) 
        => new UserDto { Id = id };
    
    // 返回 ActionResult → 透传
    public ActionResult<UserDto> Get(int id)
        => NotFound();
    
    // 混合使用
    public ActionResult<UserDto> Get(int id)
        => Ok(new UserDto { Id = id });
}

八、性能优化设计

8.1 缓存策略

csharp 复制代码
internal sealed class ControllerActionInvokerCache
{
    // 按 Action 缓存,首次后零反射
    private readonly ConcurrentDictionary<CacheKey, CacheEntry> _cache;
    
    private sealed class CacheEntry
    {
        public ObjectMethodExecutor ObjectMethodExecutor { get; }
        public ControllerBinderDelegate? ControllerBinderDelegate { get; }
        public object?[]? ControllerPropertyInjectionCache { get; }
    }
}

8.2 零分配优化

优化技术 实现方式 效果
表达式树编译 将绑定逻辑编译为委托 100x 性能提升 vs 反射
同步路径检查 IsCompletedSuccessfully 检查 减少 async/await 状态机分配
Sealed 类型 ActionExecutingContextSealed 避免虚方法调用
写时复制 CopyOnWriteList<T> 多线程安全,零锁读取

8.3 缓存键设计

csharp 复制代码
private sealed class CacheKey
{
    public ActionDescriptor ActionDescriptor { get; }
    public IFilterMetadata[] Filters { get; }
    public ParameterInfo[] Parameters { get; }
    
    // 重写 GetHashCode/Equals 以确保正确缓存
}

九、核心扩展点

扩展场景 实现接口 注册方式
自定义控制器激活 IControllerActivator services.AddSingleton<IControllerActivator, CustomActivator>()
自定义模型绑定 IModelBinder / IModelBinderProvider MvcOptions.ModelBinderProviders.Add()
自定义输入/输出格式化 IInputFormatter / IOutputFormatter MvcOptions.InputFormatters.Add()
全局应用约定 IApplicationModelConvention MvcOptions.Conventions.Add()
自定义参数绑定 IBinderTypeProviderMetadata 通过 [ModelBinder] 属性
自定义验证 IModelValidatorProvider MvcOptions.ModelValidatorProviders.Add()
自定义返回值处理 IActionResultTypeMapper services.AddSingleton<IActionResultTypeMapper, CustomMapper>()

十、完整请求链路

IActionResultExecutor Action Method ModelBinder ControllerFactory ControllerActionInvoker ResourceInvoker ControllerRequestDelegateFactory EndpointRoutingMiddleware Client IActionResultExecutor Action Method ModelBinder ControllerFactory ControllerActionInvoker ResourceInvoker ControllerRequestDelegateFactory EndpointRoutingMiddleware Client 路由匹配阶段 过滤器管道执行 Action 执行阶段 结果处理阶段 1. HTTP Request 2. 匹配端点 3. 返回 RequestDelegate 4. Authorization Filters 5. Resource Filters 6. 进入 Action 阶段 7. 创建控制器 8. 控制器实例 9. 绑定参数 10. 参数值 11. 执行 Action 方法 12. 返回值 13. 执行 IActionResultExecutor 14. HTTP Response


总结

ASP.NET Core MVC Core 架构的设计精髓可概括为:

  1. 模块化分层:中间件层 → 路由层 → 调用器层 → 执行器层,职责清晰
  2. 状态机驱动ResourceInvokerControllerActionInvoker 使用状态机模式,零递归
  3. 策略模式 :8 种 ActionMethodExecutor,每种返回类型有专属优化路径
  4. 缓存优先:表达式树编译 + 并发字典缓存,启动后零反射
  5. 扩展友好:60+ 可替换服务 + 多个扩展点接口
  6. 零分配设计:同步路径检查、sealed 类型、CopyOnWriteList 等

这些设计使 MVC Core 在保持高扩展性的同时实现卓越性能。


参考文献

相关推荐
邪修king2 小时前
UE5 进阶篇第一弹:中期架构升级 —— 组件化开发与 Gameplay 框架实战
c++·游戏·架构·ue5
亚空间仓鼠10 小时前
Docker容器化高可用架构部署方案(六)
docker·容器·架构
RInk7oBjo10 小时前
从零设计生产级 Multi-Agent Harness:架构、评估、记忆、成本与 MCP 工具接入全拆解
架构
张伯毅11 小时前
如何构建一个生产级 AI Agent CLI —— 以 Claude Code 架构探索
人工智能·架构
covco12 小时前
分布式架构实战:全平台矩阵管理系统的技术实现与性能优化
分布式·矩阵·架构
dhashdoia13 小时前
GPT-5.5 代码开发实战:Codex与Browser Use深度集成与星链4SAPI优化方案
java·数据库·人工智能·gpt·架构
AiTop10014 小时前
商汤发布SenseNova 6.7 Flash-Lite:原生多模态架构打破“视觉转文本“瓶颈,Token消耗直降 60%
人工智能·ai·架构
不懂的浪漫14 小时前
02|Netty 服务端是怎么启动的:从 ServerBootstrap.bind() 看源码主线
架构·netty
小白编程锤炼15 小时前
深入解析:质量门禁
人工智能·算法·架构·vibe-coding