iT邦幫忙

2019 iT 邦幫忙鐵人賽

DAY 9
1

昨天講了中介層的觀念,今天我們來實作中介層!


中介層通常會以一個類別封裝起來,再由擴充方法曝露。假設現在有個需求,要透過 URL 中一個區塊來決定語系。範例程式碼可以參考這邊

URL 語系
/ zh-TW
/en-us/ en-US
/de-de/ de-DE

直接將中介層邏輯寫在 Startup.Configure 方法中:

public class Startup
{
    private static readonly string[] EnabledCultures = new[] {"zh-tw", "en-us", "de-de"};

    public void Configure(IApplicationBuilder app, IHostingEnvironment env)
    {
        app.Use((context, next) =>
        {
            var path = context.Request.Path;

            var match = Regex.Match(path, $"^/({string.Join('|', EnabledCultures)})/CultureMiddleware");
            var defaultCulture = "zh-tw";
            if (match.Success)
            {
                defaultCulture = match.Groups[1].Value;

                context.Request.Path = new PathString("/CultureMiddleware/Index");
            }

            var culture = new CultureInfo(defaultCulture);

            CultureInfo.CurrentCulture = culture;
            CultureInfo.CurrentUICulture = culture;

            // Call the next delegate/middleware in the pipeline
            return next();
        });

        app.Run(async context =>
        {
            await context.Response.WriteAsync(
                $"你的語系是:{CultureInfo.CurrentCulture.DisplayName}",
                Encoding.UTF8);
        });

    }
}

這個範例中,EnabledCultures 變數定義應用程式中支援的語系。

private static readonly string[] EnabledCultures = new[] {"zh-tw", "en-us", "de-de"};

利用正規表示式來搜尋 URL 中的語系區塊,如果找不到會預設為 zh-tw。同時把要求的路徑指定為 /CultureMiddleware/Index,否則 router 會認錯 Controller。

var match = Regex.Match(path, $"/({string.Join('|', EnabledCultures)})");
var defaultCulture = "zh-tw";
if (match.Success)
{
    defaultCulture = match.Groups[1].Value;

    context.Request.Path = new PathString("/CultureMiddleware/Index");
}

最後設定應用程式中的語系。

var culture = new CultureInfo(defaultCulture);

CultureInfo.CurrentCulture = culture;
CultureInfo.CurrentUICulture = culture;

不同 URL 顯示的結果:https://ithelp.ithome.com.tw/upload/images/20181023/20107875hRXWPXu04R.png

封裝中介層

一般習慣會把中介層的邏輯封裝成一個類別,範例程式碼可以參考這邊

把委任封裝成類別:

public class RequestCultureMiddleware
{
    private static readonly string[] EnabledCultures = new[] { "zh-tw", "en-us", "de-de" };

    private readonly RequestDelegate _next;

    public RequestCultureMiddleware(RequestDelegate next)
    {
        _next = next;
    }

    public async Task InvokeAsync(HttpContext context)
    {
        var path = context.Request.Path;

        var match = Regex.Match(path, $"/({string.Join('|', EnabledCultures)})");
        var defaultCulture = "zh-tw";
        if (match.Success)
        {
            defaultCulture = match.Groups[1].Value;

            context.Request.Path = new PathString("/CultureMiddleware/Index");
        }

        var culture = new CultureInfo(defaultCulture);

        CultureInfo.CurrentCulture = culture;
        CultureInfo.CurrentUICulture = culture;

        // Call the next delegate/middleware in the pipeline
        await _next(context);
    }
}

透過 IApplicationBuilder 曝露中介層:

public static class RequestCultureMiddlewareExtensions
{
    public static IApplicationBuilder UseRequestCulture(this IApplicationBuilder builder)
    {
        return builder.UseMiddleware<RequestCultureMiddleware>();
    }
}

Startup.Configure 中設定中介層:

public void Configure(IApplicationBuilder app)
{
    app.UseRequestCulture();

    app.Run(async context =>
    {
        await context.Response.WriteAsync(
            $"你的語系是:{CultureInfo.CurrentCulture.DisplayName}",
            Encoding.UTF8);
    });

}

參考資料


上一篇
Middleware 中介層 - 1/2
下一篇
Static Files 靜態檔案
系列文
.Net Core 網站開發 10131
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言