路由

15.1 路由映射

ASP.NET Core的路由是通过EndpointRoutingMiddlewareEndpointMiddleware这两个中间件来实现的。

定义在NuGet包 Mircrosoft.AspNetCore.Routing

15.1.1 路由注册

下面是一个简易版的天气预报,用户用户获取某个城市未来N天之内的天气信息,可以直接发一个Get请求在URL中。
https://localhost:44370/weather/0512/4

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace WebApplication15_1_1
{
    public class WeatherReport
    {
        private static string[] _conditions = new string[] { "晴", "多云", "小雨" };
        private static Random _random = new Random();

        public string City { get; }
        public IDictionary<DateTime, WeatherInfo> WeatherInfos { get; }

        public WeatherReport(string city, int days)
        {
            City = city;
            WeatherInfos = new Dictionary<DateTime, WeatherInfo>();
            for (int i = 0; i < days; i++)
            {
                this.WeatherInfos[DateTime.Today.AddDays(i + 1)] = new WeatherInfo
                {
                    Condition = _conditions[_random.Next(0, 2)],
                    HighTemperature = _random.Next(20, 30),
                    LowTemperature = _random.Next(10, 20)
                };
            }
        }

        public WeatherReport(string city, DateTime date)
        {
            City = city;
            WeatherInfos = new Dictionary<DateTime, WeatherInfo>
            {
                [date] = new WeatherInfo
                {
                    Condition = _conditions[_random.Next(0, 2)],
                    HighTemperature = _random.Next(20, 30),
                    LowTemperature = _random.Next(10, 20)
                }
            };

        }
    }

    public class WeatherInfo
    {
        /// <summary>
        /// 条件
        /// </summary>
        public string Condition { get; set; }
        /// <summary>
        /// 最高气温
        /// </summary>
        public double HighTemperature { get; set; }
        /// <summary>
        /// 最低气温
        /// </summary>
        public double LowTemperature { get; set; }
    }
}

用于处理请求的处理器最终体现为一个RequestDelegate对象,以下用WeatherForecast方法来处理请求。
直接调用HttpContext的GetRouteData扩展方法提取RoutingMiddleware中间件在路由解析过程中设置的路由参数。

    public class Program
    {
        private static Dictionary<string, string> _cities = new Dictionary<string, string>
        {
            ["010"] = "北京",
            ["028"] = "成都",
            ["0512"] = "苏州"
        };

        /// <summary>
        /// 天气预测
        /// </summary>
        /// <param name="context"></param>
        /// <returns></returns>
        public static async Task WeatherForecast(HttpContext context)
        {
            var city = (string)context.GetRouteData().Values["city"];
            city = _cities[city];
            int days = int.Parse(context.GetRouteData().Values["days"].ToString());
            var report = new WeatherReport(city, days);
            await RendWeatherAsync(context, report);
        }

        /// <summary>
        /// 天气的返回信息
        /// </summary>
        /// <param name="context"></param>
        /// <param name="report"></param>
        /// <returns></returns>
        private static async Task RendWeatherAsync(HttpContext context, WeatherReport report)
        {
            context.Response.ContentType = "text/html;charset=utf-8";
            await context.Response.WriteAsync("<html><head><title>Weather</title></head><body>");
            await context.Response.WriteAsync($"<h3>{report.City}</h3>");
            foreach (var it in report.WeatherInfos)
            {
                await context.Response.WriteAsync($"{it.Key.ToString("yyyy-MM-dd")}:");
                await context.Response.WriteAsync($"{it.Value.Condition}({ it.Value.LowTemperature}℃ ~ { it.Value.HighTemperature}℃)<br/><br/> ");
            }
            await context.Response.WriteAsync("</body></html>");
        }
    }

下面完成路由注册。
调用IApplicationBuilder的UseRouting方法和UseEndpoints方法分别完成针对EndpointRoutingMiddleware与EndpointMiddleware这两个终结点的注册。

        public static void Main(string[] args)
        {
            Host.CreateDefaultBuilder()
                .ConfigureWebHostDefaults(builder => builder
                    .ConfigureServices(svcs => svcs.AddRouting())
                    .Configure(app => app.UseRouting()
                        .UseEndpoints(endpoints => endpoints
                            .MapGet("weather/{city}/{days}", WeatherForecast))))
                .Build()
                .Run();
        }

UseEndpoints方法提供了一个Action<IEndpointRouteBuilder>类型的参数,利用这个参数调用IEndpointRouteBuilder的MapGet方法,提供了一个路由模板与对应处理器之间的映射。
指定路径模板为“weather/{city}/{days}”,两个路由参数分别代表获取天气预报的目标城市和天数,WeatherForecast方法作为RequestDelegate对象作为第二个参数。MapGet表示HTTP的Get方法。与指定路由模式匹配的请求就会被路由到WeatherForecast对应的终结点。

posted @ 2020-11-25 23:13  一纸年华  阅读(4)  评论(0编辑  收藏  举报  来源