# 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

- 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()

### 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)