---
# System prepended metadata

title: Grimore Structure

---

# Grimore Structure

## TODO
- IActionDescriptorCollectionProvider

## Action

### ActionContext

- ActionContext
  - LineEventContext
  - CommandData
  - ActionDescriptor

- ControllerContext
  - ControllerContext(ActionContext)

### ActionDescriptor

- ActionDescriptor
  - [ActionDescriptor Class (System.Web.Mvc) | Microsoft Docs](https://docs.microsoft.com/en-us/dotnet/api/system.web.mvc.actiondescriptor)

- ControllerActionDescriptor 

### ActionInvoker

- ActionInvoker
  - InvokeAsync()

- ResourceInvoker

- ControllerActionInvoker
  
- **ControllerActionInvokerCache**
  
#### ActionInvokerProvider

- IActionInvokerProvider
  - [IActionInvokerProvider Interface (Microsoft.AspNetCore.Mvc.Abstractions) | Microsoft Docs](https://docs.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.mvc.abstractions.iactioninvokerprovider)
  - OnProvidersExecuting(ActionInvokerProviderContext)
  - OnProvidersExecuted(ActionInvokerProviderContext)

- ControllerActionInvokerProvider
  - OnProvidersExecuting(ActionInvokerProviderContext)
    - new ControllerContext(ActionInvokerProviderContext.ActionContext)
    - ControllerActionInvokerCache.GetCachedResult(controllerContext);
    - ActionInvokerProviderContext.Result = new ControllerActionInvoker

##### ActionInvokerProviderContext

- ActionInvokerProviderContext
  - ActionInvokerProviderContext(ActionContext)
  - ActionContext
  - IActionInvoker Result
    Gets or sets the `IActionInvoker` that will be used to invoke ActionContext

#### ActionInvokerFactory

- ActionInvokerFactory
  - IActionInvokerProvider[] `_actionInvokerProviders`
  - CreateInvoker
    - new ActionInvokerProviderContext(ActionContext)
    - foreach `_actionInvokerProviders` .OnProvidersExecuting(ActionInvokerProviderContext)
    - reversed-foreach `_actionInvokerProviders` .OnProvidersExecuted(ActionInvokerProviderContext)
    - return ActionInvokerProviderContext.Result

# Reference: aspcore structure

- IRouter
  Interface for implementing a router.
  - public Task RouteAsync(RouteContext context)

- Route Builder
  - Default Handler 
  - Routes
  - Build() -> IRouter

![](https://images2015.cnblogs.com/blog/250417/201703/250417-20170327154104998-2053909747.png)

- Route Handler: IRouter
  1. MvcRouteHandler
  2. **MvcAttributeRouteHandler**
     - ActionsAction: Descriptor[]
     - RouteAsync(RouteContext context)
       - var actionDescriptor = `_actionSelector`.SelectBestCandidate(context, Actions)
       - create context.Handler
         - var routeData = httpContext.GetRouteData();
         - var actionContext = new ActionContext(context.HttpContext, routeData, actionDescriptor);
         - var invoker = `_actionInvokerFactory`.CreateInvoker(actionContext)
         - invoker.InvokeAsync()

![](https://images2015.cnblogs.com/blog/250417/201703/250417-20170327220352342-1246687513.png)

### ControllerDescriptor

- ControllerName
- ControllerType
- UniqueId

## Action

- ActionContext
  - HttpContext
  - RouteData
  - ActionDescriptorActionDescriptor
  - ModelStateDictionary

### ActionDescriptor

- ActionDescriptor
  - [ActionDescriptor Class (Microsoft.AspNetCore.Mvc.Abstractions) | Microsoft Docs](https://docs.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.mvc.abstractions.actiondescriptor?view=aspnetcore-5.0)
  - AttributeRouteInfo
  - Id
  - Parameters
  - RouteValues
<!-- No need for Grimoire -->

- ControllerActionDescriptor 
  - ControllerName
  - ActionName
  - MethodInfo
  - ControllerTypeInfo
  - CacheEntry

#### ActionDescriptorProvider

- IActionDescriptorProvider
  - ActionDescriptors

- ControllerActionDescriptorProvider
  - `internal IEnumerable<ControllerActionDescriptor>` GetDescriptors()
  - `private IEnumerable<TypeInfo>` GetControllerTypes()
  - OnProvidersExecuting(ActionDescriptorProviderContext context)
  - OnProvidersExecuted(ActionDescriptorProviderContext context)

#### ActionDescriptorCollectionProvider

- ActionDescriptorCollectionProvider
  - `IReadOnlyList<ActionDescriptor>` ActionDescriptors

- DefaultActionDescriptorCollectionProvider
  - TODO

#### ActionDescriptorProviderContext

- ActionDescriptorProviderContext
  - `IList<ActionDescriptor>` Results `{ get; } = new List<ActionDescriptor>();`

#### AttributeRouteInfo

- AttributeRouteInfo
  - Order
  - Template

### ActionInvoker

- IActionInvoker
  - `Task` InvokeAsync()

- ResourceInvoker

- ControllerActionInvoker
  - ActionContext
  - `Task<IActionResult>` ToActionResultAsync(object result)
  - `static async Task<IActionResult>` ConvertFromTaskAsync`<TValue>(Task<TValue> returnValue, IActionResultTypeMapper mapper)`
  - `static async Task<IActionResult>` ConvertFromValueTaskAsync`<TValue>( ValueTask<TValue> returnValue, IActionResultTypeMapper mapper)`
  - `Task` InvokeAsync()

  
- **ControllerActionInvokerCache**
  
#### ActionInvokerFactory

- ActionInvokerFactory
  - IActionInvokerProvider[] `_actionInvokerProviders`
  - `IActionInvoker` CreateInvoker(ActionContext)
    - new ActionInvokerProviderContext(ActionContext)
    - foreach `_actionInvokerProviders` .OnProvidersExecuting(ActionInvokerProviderContext)
    - reversed-foreach `_actionInvokerProviders` .OnProvidersExecuted(ActionInvokerProviderContext)
    - return ActionInvokerProviderContext.Result

#### ActionInvokerProvider

- IActionInvokerProvider
  - [IActionInvokerProvider Interface (Microsoft.AspNetCore.Mvc.Abstractions) | Microsoft Docs](https://docs.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.mvc.abstractions.iactioninvokerprovider)
  - OnProvidersExecuting(ActionInvokerProviderContext)
  - OnProvidersExecuted(ActionInvokerProviderContext)

- ControllerActionInvokerProvider
  - OnProvidersExecuting(ActionInvokerProviderContext)
    - new ControllerContext(ActionInvokerProviderContext.ActionContext)
    - ControllerActionInvokerCache.GetCachedResult(controllerContext);
    - ActionInvokerProviderContext.Result = new ControllerActionInvoker

##### ActionInvokerProviderContext

- ActionInvokerProviderContext
  - ActionInvokerProviderContext(ActionContext)
  - ActionContext
  - IActionInvoker Result
    Gets or sets the `IActionInvoker` that will be used to invoke ActionContext

### ActionResult

- IActionResult
  - `Task` ExecuteResultAsync(ActionContext)

- ContentResult
- NullActionResult
  Signleton

#### IActionResultTypeMapper

- IActionResultTypeMapper
  - `IActionResult` Convert(object value, Type returnType)

- ActionResultTypeMapper
  - => new ContentResult(value.ToString(), "text/plain");

  
  
## ServiceCollectionExtensions

- ServiceCollectionExtensions
  - `IServiceCollection` AddMvcControllers`(this IServiceCollection services)`

```csharp
return services
.AddSingleton<IActionDescriptorCollectionProvider, DefaultActionDescriptorCollectionProvider>()
.AddSingleton<IActionInvokerFactory, ActionInvokerFactory>()
.AddSingleton<IActionDescriptorProvider, ControllerActionDescriptorProvider>()
.AddSingleton<ControllerActionEndpointDataSource, ControllerActionEndpointDataSource>()
.AddSingleton<IActionResultTypeMapper, ActionResultTypeMapper>();
```

# Others

```csharp=
public interface IRouter
{
    Task RouteAsync(RouteContext context);

    VirtualPathData GetVirtualPath(VirtualPathContext context);
}

public interface IRouteHandler
{
    RequestDelegate GetRequestHandler(HttpContext httpContext, RouteData routeData);
}

// Microsoft.AspNetCore.Routing.RouteCollection
public async Task Invoke(HttpContext httpContext)
{
    var context = new RouteContext(httpContext);
    context.RouteData.Routers.Add(_router);

    await _router.RouteAsync(context);

    if (context.Handler == null)
    {
        _logger.RequestDidNotMatchRoutes();
        await _next.Invoke(httpContext);
    }
    else
    {
        httpContext.Features[typeof(IRoutingFeature)] = new RoutingFeature()
        {
            RouteData = context.RouteData,
        };

        await context.Handler(context.HttpContext);
    }
}
```

> Reference: 
> https://www.cnblogs.com/savorboard/p/aspnetcore-routing.html
> https://www.cnblogs.com/savorboard/p/aspnetcore-mvc-routing-action.html
> [通过极简模拟框架让你了解ASP.NET Core MVC框架的设计与实现\[上篇\]：路由整合 - Artech - 博客园 (cnblogs.com)](https://www.cnblogs.com/artech/p/inside-asp-net-core-mvc-01.html)
