zoukankan      html  css  js  c++  java
  • .Net Core在Middleware中解析RouteData

    在ASP.Net Core中,如果直接在Middleware中获取RouteData返回的是空值,这是因为RouterMiddleware还没执行。但有些情况下需要获取RouteData,这要怎么做呢?

    public async Task Invoke(HttpContext context)
    {
        var routeData = context.GetRouteData(); null
    }

    TemplateMatcher

    TemplateMatcher是获取路由值的关键类。使用它可以将URL按路由Template解析成RouteData。所以我们可以使用它来获取RouteData。

    下面是一个简单的辅助类供参考,如果直接使用可能会有一些性能问题,因为解析路由模板(TemplateParser.Parse(routeTemplate))需要时间,所以应当在实际使用的时候优化它:

    public class RouteMatcher
    {
        public RouteValueDictionary Match(string routeTemplate, string requestPath)
        {
            var template = TemplateParser.Parse(routeTemplate);
            var matcher = new TemplateMatcher(template, GetDefaults(template));
            var values = matcher.Match(requestPath);
            return values;
        }
    
        private RouteValueDictionary GetDefaults(RouteTemplate parsedTemplate)
        {
            var result = new RouteValueDictionary();
            foreach (var parameter in parsedTemplate.Parameters)
            {
                if (parameter.DefaultValue != null)
                {
                    result.Add(parameter.Name, parameter.DefaultValue);
                }
            }
            return result;
        }
    }

    有了这些,就可以在Middleware里面来解析RouteData了。

    注意

    在解析路由时,应当按照路由的注册的先后顺序来解析,并且在成功解析时退出,这样可以保证和程序匹配时的路由是一致的。并且你应当考虑是否加上使用路由的约束(RouteConstraint)来判断当前的路由模板是否匹配。

    应用场景

    在纸壳CMS里面,当开启多语言时,用户访问了一个不带语言的地址,应当要自动跳转加上用户对应的语言。所以需要使用Middleware来做跳转,同时需要将用户访问的Url解析成RoteData来判断是否需要跳转。

    namespace ZKEACMS.MultiLanguage
    {
        public class LocalizeRedirectMiddleware
        {
            class LocalizeRoute
            {
                public Easy.Mvc.Route.RouteDescriptor Descriptor { get; set; }
                public TemplateMatcher TemplateMatcher { get; set; }
            }
            private readonly RequestDelegate _next;
            private List<LocalizeRoute> _routes;
    
            public LocalizeRedirectMiddleware(RequestDelegate next)
            {
                _next = next;
            }
            public Task Invoke(HttpContext context)
            {
                if (IsGetMethod(context) && IsSupportContentType(context))
                {
                    IApplicationContextAccessor applicationContextAccessor = context.RequestServices.GetService<IApplicationContextAccessor>();
                    var setting = applicationContextAccessor.Current.CultureSetting;
                    if (setting.UseUrlCode(context.User.Identity.IsAuthenticated))
                    {
                        var acitveCultures = context.RequestServices.GetService<ICultureService>().GetActiveCulture();
                        if (_routes == null)
                        {
                            _routes = context.RequestServices.GetService<IRouteProvider>().GetRoutes().OrderByDescending(m => m.Priority).Select(m =>
                            {
                                var template = TemplateParser.Parse(m.Template);
                                return new LocalizeRoute
                                {
                                    Descriptor = m,
                                    TemplateMatcher = new TemplateMatcher(template, GetDefaults(template))
                                };
                            }).ToList();
                        }
                        foreach (var item in _routes)
                        {
                            var routeData = new RouteValueDictionary();
                            if (item.TemplateMatcher.TryMatch(context.Request.Path.Value, routeData))
                            {
                                if(item.Descriptor is LocalizeRouteDescriptor)
                                {
                                    object cultureCode;
                                    if (routeData.TryGetValue("culture", out cultureCode))
                                    {
                                        if (!acitveCultures.Any(m => cultureCode.Equals(m.UrlCode)))
                                        {
                                            context.Response.Redirect($"/{context.GetUserCulture().UrlCode}{context.Request.GetAbsoluteUrl()}");
                                            return Task.CompletedTask;
                                        }
                                    }
                                    else
                                    {
                                        context.Response.Redirect($"/{context.GetUserCulture().UrlCode}{context.Request.GetAbsoluteUrl()}");
                                        return Task.CompletedTask;
                                    }
                                }
                                break;
                            }
                        }
                    }
                }
                return _next(context);
            }
            private bool IsGetMethod(HttpContext context)
            {
                return string.Equals("GET", context.Request.Method, StringComparison.OrdinalIgnoreCase);
            }
            private bool IsSupportContentType(HttpContext context)
            {
                return true;
            }
    
            private RouteValueDictionary GetDefaults(RouteTemplate parsedTemplate)
            {
                var result = new RouteValueDictionary();
    
                foreach (var parameter in parsedTemplate.Parameters)
                {
                    if (parameter.DefaultValue != null)
                    {
                        result.Add(parameter.Name, parameter.DefaultValue);
                    }
                }
    
                return result;
            }
        }
    }

    另外

    对于对于多语言的跳转,微软其实有提供了一个Localization middleware,只不过在纸壳CMS的多语言场景里有点不太适用,所以重新写了这个LocalizeRedirectMiddleware。如果你也有正在考虑多语言的解决方案,可以查看下面的链接:

    https://docs.microsoft.com/en-us/aspnet/core/fundamentals/localization?view=aspnetcore-2.1

    原文链接:http://www.zkea.net/codesnippet/detail/middleware-routedata.html

  • 相关阅读:
    第12组 Beta冲刺 (3/5)
    第12组 Beta冲刺 (2/5)
    第12组 Beta冲刺 (1/5)
    每周小结(1/3)
    第03组 Beta冲刺 (4/5)
    第03组 Beta冲刺 (3/5)
    第03组 Beta冲刺 (1/5)
    第03组 Alpha冲刺 总结
    第03组 Alpha冲刺 (6/6)
    第03组 Alpha冲刺 (4/6)
  • 原文地址:https://www.cnblogs.com/seriawei/p/9639131.html
Copyright © 2011-2022 走看看