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

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.

主站蜘蛛池模板: 漳州市| 海晏县| 兰坪| 临漳县| 上思县| 凤庆县| 长治县| 南通市| 海伦市| 三河市| 潞城市| 平安县| 佛山市| 衡南县| 霍邱县| 北安市| 洪洞县| 武定县| 文登市| 东辽县| 山阴县| 前郭尔| 大兴区| 玛纳斯县| 韩城市| 青河县| 汤原县| 永和县| 东源县| 蚌埠市| 伊川县| 汤阴县| 乡宁县| 樟树市| 峡江县| 龙南县| 阜新| 利川市| 尼勒克县| 安乡县| 石河子市|