Skip to content

Commit 865f26a

Browse files
committed
Introduce TopicRouteValueTransformer
The `TopicRouteValueTransformer` provides flexible support for using the `MapDynamicControllerRoute<>()` extension method for configuring endpoints. This allows us to implicitly assign route variables if they're missing based on context. Notably, if the `controller` is missing, but `area` is defined, it will set it to `area`, thus supporting an implicit controller convention. E.g., for `/Areas/Forms/Controllers/FormsController.cs`, we can simply route to `/Forms/`, without needing to explicitly define a route for each area along with a `default` controller. Also, if `path` and `area` are defined, but our (custom) `rootTopic` variable is not defined, `rootTopic` will be set to `area`. This is intended to provide support for upcoming extension methods to simplify associating OnTopic routes with areas—something which is currently done manually, but which is both verbose and potentially error prone. Further, doing so mandates individual routes to be setup for implicit controllers, whereas this provides wildcard support.
1 parent 74a8a76 commit 865f26a

1 file changed

Lines changed: 84 additions & 0 deletions

File tree

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
/*==============================================================================================================================
2+
| Author Ignia, LLC
3+
| Client Ignia, LLC
4+
| Project Topics Library
5+
\=============================================================================================================================*/
6+
using System;
7+
using System.Threading.Tasks;
8+
using Microsoft.AspNetCore.Http;
9+
using Microsoft.AspNetCore.Mvc.Routing;
10+
using Microsoft.AspNetCore.Routing;
11+
using OnTopic.Internal.Diagnostics;
12+
13+
namespace OnTopic.AspNetCore.Mvc {
14+
15+
/*============================================================================================================================
16+
| CLASS: TOPIC ROUTE VALUE TRANSFORMER
17+
\---------------------------------------------------------------------------------------------------------------------------*/
18+
/// <summary>
19+
/// Interprets endpoint routes associated with OnTopic in order to dynamically fill in any missing metadata based on the
20+
/// needs of the <see cref="TopicRepositoryExtensions.Load(Repositories.ITopicRepository, RouteData)"/> method.
21+
/// </summary>
22+
public class TopicRouteValueTransformer: DynamicRouteValueTransformer {
23+
24+
/*==========================================================================================================================
25+
| OVERRIDE: TRANSFORM (ASYNC)
26+
\-------------------------------------------------------------------------------------------------------------------------*/
27+
/// <summary>
28+
/// Evaluates the current <see cref="RouteValueDictionary"/> for any missing attributes, and attempts to dynamically
29+
/// inject them based on other values.
30+
/// </summary>
31+
#pragma warning disable CS1998 // Async method lacks 'await' operators and will run synchronously
32+
public override async ValueTask<RouteValueDictionary> TransformAsync(HttpContext httpContext, RouteValueDictionary values) {
33+
34+
/*------------------------------------------------------------------------------------------------------------------------
35+
| Validate parameters
36+
\-----------------------------------------------------------------------------------------------------------------------*/
37+
Contract.Requires(httpContext, nameof(httpContext));
38+
Contract.Requires(values, nameof(values));
39+
40+
/*------------------------------------------------------------------------------------------------------------------------
41+
| Implicitly set controller
42+
>-------------------------------------------------------------------------------------------------------------------------
43+
| If the area is set, but not the controller, assume that the controller is named after the area by convention. If the
44+
| controller is being set in the route pattern, this won't change that.
45+
\-----------------------------------------------------------------------------------------------------------------------*/
46+
var controller = (string)values["controller"];
47+
var area = (string)values["area"];
48+
if (area != null && controller == null) {
49+
values["controller"] = area;
50+
}
51+
52+
/*------------------------------------------------------------------------------------------------------------------------
53+
| Implicitly set action
54+
>-------------------------------------------------------------------------------------------------------------------------
55+
| If the action isn't defined in the route, assume Index—which is the default action for the TopicController.
56+
\-----------------------------------------------------------------------------------------------------------------------*/
57+
var action = (string)values["action"];
58+
if (action == null) {
59+
action = "Index";
60+
values["action"] = action;
61+
}
62+
63+
/*------------------------------------------------------------------------------------------------------------------------
64+
| Implicitly set root topic
65+
>-------------------------------------------------------------------------------------------------------------------------
66+
| If the path is set, but the root topic isn't, then set the root topic to the area/controller name. The root topic is
67+
| required by the TopicRepositoryExtensions to create a fully qualified topic path, and correctly identify the topic
68+
| based on the path. It is not needed when routing by controller/action pairs.
69+
\-----------------------------------------------------------------------------------------------------------------------*/
70+
var path = (string)values["path"];
71+
if (path != null || action.Equals("Index", StringComparison.OrdinalIgnoreCase)) {
72+
values["rootTopic"] = area;
73+
}
74+
75+
/*------------------------------------------------------------------------------------------------------------------------
76+
| Return values
77+
\-----------------------------------------------------------------------------------------------------------------------*/
78+
return values;
79+
80+
}
81+
#pragma warning restore CS1998 // Async method lacks 'await' operators and will run synchronously
82+
83+
} //Class
84+
} //Namespace

0 commit comments

Comments
 (0)