官术网_书友最值得收藏!

Using dynamic routing

Up until now, we've seen routing tables that statically map route templates to controller actions, but there is another kind: dynamic routes. In this case, we are still using route templates, but the thing is, we can change them dynamically.

A dynamic route handler is registered through a call to MapDynamicControllerRoute. I will provide an example that uses a translation service to translate the controller and action names supplied by the user, in any language to plain English, as they exist in the project.

Let's start from the beginning. We define the interface for the translation service:

public interface ITranslator
{
Task<string> Translate(string sourceLanguage, string term);
}

As you can see, this has a single asynchronous method, Translate, that takes two parameters: the source language and the term to translate. Let's not waste much time with this.

The core dynamic routing functionality is implemented as a class inheriting from DynamicRouteValueTransformer. Here is an example of one such class, followed by its explanation:

publicsealedclassTranslateRouteValueTransformer : DynamicRouteValueTransformer
{
    privateconststring _languageKey ="language";
    privateconststring _actionKey ="action";
    privateconststring _controllerKey ="controller";
 
    privatereadonlyITranslator _translator;
 
    publicTranslateRouteValueTransformer(ITranslatortranslator)
    {
        this._translator =translator;
    }
 
    publicoverride async ValueTask<RouteValueDictionary> TransformAsync(
HttpContexthttpContext, RouteValueDictionaryvalues) { varlanguage=values[_languageKey] asstring; varcontroller=values[_controllerKey] asstring; varaction=values[_actionKey] asstring; controller= await this._translator.Translate(
language, controller) ??controller; action= await this._translator.Translate(language, action)
??action; values[_controllerKey] =controller; values[_actionKey] =action; returnvalues; } }

The TranslateRouteValueTransformer class receives on its constructor an instance of ITranslator, which it saves as a local field. On the TransformAsync method, it retrieves the values for the route template values, language, controller, and action; for controller andaction, it has them translated by ITranslator. The resulting values are then stored again in the route values dictionary, which is returned in the end.

To make this work, we need three things:

  1. We need to register ITranslator as a service in ConfigureServices:
services.AddSingleton<ITranslator, MyTranslator>();
//MyTranslator is just for demo purposes, you need to roll out your own dictionary implementation
  1. We need to registerTranslateRouteValueTransformer as a service too:
services.AddSingleton<TranslateRouteValueTransformer>();
  1. And finally, we need to register a dynamic route:
app.UseEndpoints(endpoints=>
{
endpoints.MapDynamicControllerRoute<TranslateRouteValueTransformer>(
pattern: "{language}/{controller}/{action}/{id?}");
//now adding the default route
endpoints.MapDefaultControllerRoute();
});

As you can see, our dynamic route looks for a pattern of language/controller/action/id, where the id part is optional. Any request that can be mapped to this pattern will fall into this dynamic route.

Keep in mind that the purpose of dynamic routes is not to change the route pattern, but just to change the route template tokens. This will not cause any redirect, but will actually determine how the request is to be processed, the action method and the controller, and any other route parameters.

To bring this section to a close, this example allows the resolution of these routes, provided that the dictionary supports French (fr), German (de), and Portuguese (pt):

  • /fr/Maison/Index to /Home/Index
  • /pt/Casa/Indice to /Home/Index
  • /de/Zuhause/Index to /Home/Index
You can have multiple dynamic routes with different patterns; this is perfectly OK.

Having learned about dynamic routes, let's go back to static routes, this time using attributes in classes and methods to define the routes.

主站蜘蛛池模板: 梅州市| 龙海市| 丁青县| 吉隆县| 射阳县| 疏附县| 淮北市| 江都市| 永胜县| 台中县| 乐陵市| 安新县| 松滋市| 鸡泽县| 邓州市| 石河子市| 武功县| 彰化市| 峨边| 乳山市| 民县| 中方县| 固原市| 柏乡县| 黔西县| 紫金县| 平顶山市| 修水县| 且末县| 安图县| 阳新县| 林芝县| 绥德县| 合肥市| 梓潼县| 顺平县| 木兰县| 黎川县| 彰化市| 赤城县| 扎赉特旗|