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

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.

主站蜘蛛池模板: 洛隆县| 宝鸡市| 精河县| 北川| 祥云县| 隆子县| 遂溪县| 庆云县| 乌拉特后旗| 宁津县| 陈巴尔虎旗| 永德县| 平和县| 托克逊县| 陆河县| 兰坪| 三门峡市| 准格尔旗| 美姑县| 历史| 祁门县| 锦屏县| 桦川县| 响水县| 子洲县| 五家渠市| 桐乡市| 淮阳县| 荔浦县| 遵义县| 家居| 绥棱县| 讷河市| 涿鹿县| 西乌珠穆沁旗| 灵宝市| 鸡西市| 通化市| 乐至县| 郧西县| 无极县|