ASP.Net Core -核心组件2

静态文件  js 图片 css等 有三个中间件处理 

 

 使用 UseStaticFiles 中间件

复制代码
public static class Sample01
    {
        public static void Run()
        {
            Host.CreateDefaultBuilder()
                .ConfigureWebHostDefaults(builder => builder.Configure(
                    app=>app.UseStaticFiles()))
                .Build()
                .Run();
        }
    }
复制代码

 

如果不在wwwroot 在其他目录的情况:

复制代码
 public static class Sample02
    {
        public static void Run()
        {
            var path = Path.Combine(Directory.GetCurrentDirectory(), "content");

            // 静态文件中间件配置
            var options = new StaticFileOptions
            {
                FileProvider = new PhysicalFileProvider(path),
                RequestPath = "/content"
            };

            Host.CreateDefaultBuilder()
                .ConfigureWebHostDefaults(builder => builder.Configure(
                    app=>app
                        // 静态文件中间件
                        .UseStaticFiles()
                        .UseStaticFiles(options)))
                .Build()
                .Run();
        }
    }
复制代码

 如何在浏览器中访问某个目录可以出现目录出来?使用目录浏览的中间件 UseDirectoryBrowser

复制代码
 public static class Sample03
    {
        public static void Run()
        {
            var path = Path.Combine(Directory.GetCurrentDirectory(), "content");
            var fileProvider = new PhysicalFileProvider(path);

            var staticFileOptions = new StaticFileOptions
            {
                FileProvider = fileProvider,
                RequestPath = "/content"
            };

            // 目录浏览中间件配置
            var directoryBrowserOptions = new DirectoryBrowserOptions
            {
                FileProvider = fileProvider,
                RequestPath = "/content"
            };

            Host.CreateDefaultBuilder()
                .ConfigureWebHostDefaults(builder => builder.Configure(
                    app=>app
                        // 目录浏览中间件
                        .UseStaticFiles()
                        .UseStaticFiles(staticFileOptions)
                        .UseDirectoryBrowser()
                        .UseDirectoryBrowser(directoryBrowserOptions)))
                .Build()
                .Run();
        }
    }
复制代码

默认页面中间件:

复制代码
 public class Sample04
    {
        public static void Run()
        {
            var path = Path.Combine(Directory.GetCurrentDirectory(), "content");
            var fileProvider = new PhysicalFileProvider(path);

            var staticFileOptions = new StaticFileOptions
            {
                FileProvider = fileProvider,
                RequestPath = "/content"
            };

            var directoryBrowserOptions = new DirectoryBrowserOptions
            {
                FileProvider = fileProvider,
                RequestPath = "/content"
            };

            // 默认页面中间件配置
            var defaultFilesOptions = new DefaultFilesOptions
            {
                FileProvider = fileProvider,
                RequestPath = "/content"
            };
            defaultFilesOptions.DefaultFileNames.Add("readme.html");

            Host.CreateDefaultBuilder()
                .ConfigureWebHostDefaults(builder => builder.Configure(
                    app => app
                        // 默认页面中间件,中间件注册时有顺序的 必须要有在前面默认页面中间件
                        .UseDefaultFiles()
                        .UseDefaultFiles(defaultFilesOptions)
                        .UseStaticFiles()
                        .UseStaticFiles(staticFileOptions)
                        .UseDirectoryBrowser()
                        .UseDirectoryBrowser(directoryBrowserOptions)))
                .Build()
                .Run();
        }
    }
复制代码

响应报文能正常被浏览器解析的话需要,终结点路由中间件和终结点中间件

有两种不同的路由方案:传统的路由系统 和 新的路由系统(终结点映射策略)

复制代码
 public static class Sample01
    {
        private static readonly Dictionary<string, string> Cities = new Dictionary<string, string>
        {
            ["010"] = "北京",
            ["027"] = "武汉"
        };

        public static void Run()
        {
            // const string template = @"weather/{city:regex(^{0\d{{2,3}}$)}/{days:int:range(1,4)}"; 
            const string template = @"weather/{city}/{days}"; 
            Host.CreateDefaultBuilder()
                .ConfigureWebHostDefaults(builder => builder
                    //添加路由服务
                    .ConfigureServices(csv => csv.AddRouting())
                    //添加路由中间件
                    .Configure(app => app
                        .UseRouting()//终结点路由中间
                        .UseEndpoints(endpoints => endpoints.MapGet(template, WeatherForecast))))//终结点中间件  路由模板template映射到WeatherForecast的方法上 MapGet代表使用get方法才能路由到
                .Build()
                .Run();
        }
        /// <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];
            var days = int.Parse(context.GetRouteData().Values["days"].ToString() ?? string.Empty);
            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>天气</title></head><body>");
            await context.Response.WriteAsync($"<h3>{report.City}</h3>");
            foreach (var (key, value) in report.WeatherInfos)
            {
                await context.Response.WriteAsync($"{key:yyyy-MM-dd}:");
                await context.Response.WriteAsync(
                    $"{value.Condition}({value.LowTemperature}℃ ~ {value.HighTemperature}℃)<br/><br/> ");
            }

            await context.Response.WriteAsync("</body></html>");
        }
    }
复制代码

 

异常处理中间件

因为Asp.net core 同时处理多个请求的web应用框架,纠错误的难度就会加大,就出现了出现了定制化错误消息,呈现出来

开发者提倡页面,500的响应页面,这个时候就会得到一个很笼统的错误提示

复制代码
public static class Sample01
    {
        public static void Run()
        {
            Host.CreateDefaultBuilder()
                .ConfigureWebHostDefaults(builder => builder
                //这里任何请求都会提示这个异常 提示500,这样不知道绝体原因
                    .Configure(app => app
                        .Run(context => Task.FromException(new InvalidOperationException("这是一个异常")))
                    ))
                .Build()
                .Run();
        }

    }
复制代码

直接显示错误页面,一般是给开发者看 ,叫做开发者异常页面中间件

复制代码
 public static class Sample02
    {
        public static void Run()
        {
            Host.CreateDefaultBuilder()
                .ConfigureWebHostDefaults(builder => builder
                    .ConfigureServices(services => services.AddRouting())//路由
                    .Configure(app => app
                        .UseDeveloperExceptionPage()//开发者异常页面中间件
                        .UseRouting()
                        .UseEndpoints(routeBuilder => routeBuilder.MapGet("/", HandleAsync))//终结点中间件 模板是根目录,HandleAsync这个方法是请求处理器
                    ))
                .Build()
                .Run();
        }

        private static Task HandleAsync(HttpContext context)
        {
            return Task.FromException(new InvalidOperationException("This is Exception"));
        }
    }
复制代码

 

 

 但是在给用户的情况下不应该像上面这样,

复制代码
 public static class Sample03
    {
        public static void Run()
        {
            //异常处理配置
            var options = new ExceptionHandlerOptions
            {
                ExceptionHandler = context => context.Response.WriteAsync("Hello Exception!")
            };

            Host.CreateDefaultBuilder()
                .ConfigureWebHostDefaults(builder => builder
                    .Configure(app => app
                        .UseExceptionHandler(options)//异常处理
                        .Run(context => Task.FromException(new InvalidOperationException("Throw Exception")))
                    ))
                .Build()
                .Run();
        }

    }
复制代码

直接回提示  Hello Exception! 用户屏蔽敏感信息

复制代码
 public static class Sample04
    {
        public static void Run()
        {
            Host.CreateDefaultBuilder()
                .ConfigureWebHostDefaults(builder => builder
                    .Configure(app => app
                         //使用另外一个重载 ,用于配置一个特有的中间件
                        .UseExceptionHandler(applicationBuilder => applicationBuilder
                            .Run(context => context.Response.WriteAsync("Hello Exception!"))
                        )
                        .Run(context => Task.FromException(new InvalidOperationException("这是一个异常")))
                    ))
                .Build()
                .Run();
        }

    }
复制代码
复制代码
 public static class Sample05
    {
        public static void Run()
        {
            Host.CreateDefaultBuilder()
                .ConfigureWebHostDefaults(builder => builder
                    .ConfigureServices(services => services.AddRouting())
                    .Configure(app => app
                    //又是另外一个重载
                        .UseExceptionHandler("/error")
                        .UseRouting()
                        .UseEndpoints(routeBuilder => routeBuilder.MapGet("error", HandleAsync))
//这个是正常的直接设置为报错,然后重定向到/error ===》HandleAsync .Run(context => Task.FromException(new InvalidOperationException("Throw Exception"))) )) .Build() .Run(); } private static Task HandleAsync(HttpContext context) { return context.Response.WriteAsync("Hello Exception"); } }
复制代码

注意:http通先的错误大体分为两种类型

客户端错误:400~499

服务端错误:表示服务器处理自身问题出现的错误 500~599

所以可以使用状态码页面中间件,后续请求的过程中,产生了一个错误响应状态码,根据不同的状态码显示不同的页面

以下是所有的错误都显示500的情况

复制代码
  public static class Sample06
    {
        public static void Run()
        {
            Host.CreateDefaultBuilder()
                .ConfigureWebHostDefaults(builder => builder
                    .Configure(app => app
                    //响应状态码
                        .UseStatusCodePages("text/plain", "Error ({0})")
                        .Run(context => Task.Run(() => context.Response.StatusCode = 500))
                    ))
                .Build()
                .Run();
        }
    }
复制代码

 

 

 如果我们需要根据不同的状态码设置为不同的页面的时候

复制代码
  public static class Sample07
    {
        private static readonly Random Random = new Random();
        public static void Run()
        {
            Host.CreateDefaultBuilder()
                .ConfigureWebHostDefaults(builder => builder
                    .Configure(app => app
                        .UseStatusCodePages(Handler)
                        .Run(context => Task.Run(() => context.Response.StatusCode = Random.Next(400,599)))
                    ))
                .Build()
                .Run();
        }

        private static async Task Handler(StatusCodeContext context)
        {
            var response = context.HttpContext.Response;

            if (response.StatusCode < 500)
            {
                await response.WriteAsync($"Client Error ({response.StatusCode})");
            }
            else
            {
                await response.WriteAsync($"Server Error ({response.StatusCode})");
            }
        }
    }
复制代码

 客户端重定向方式和服务端重定向

复制代码
public static class Sample08
    {
        private static readonly Random Random = new Random();
        public static void Run()
        {
            Host.CreateDefaultBuilder()
                .ConfigureWebHostDefaults(builder => builder
                    .ConfigureServices(collection => collection.AddRouting())//路由
                    .Configure(app => app
                        .UseStatusCodePagesWithRedirects("/error/{0}")//带有重定向的状态码中间件
                        .UseRouting()
                        .UseEndpoints(routeBuilder => routeBuilder.MapGet("error/{status_code}", HandlerError))//通过这个模板获取状态码
                        .Run(context => Task.Run(() => context.Response.StatusCode = Random.Next(400,599)))
                    ))
                .Build()
                .Run();
        }

        private static async Task HandlerError(HttpContext context)
        {
            var code = context.GetRouteData().Values["status_code"];
            await context.Response.WriteAsync($"Error ({code})");
        }
    }
复制代码
复制代码
public static class Sample09
    {
        private static readonly Random Random = new Random();
        public static void Run()
        {
            Host.CreateDefaultBuilder()
                .ConfigureWebHostDefaults(builder => builder
                    .ConfigureServices(collection => collection.AddRouting())
                    .Configure(app => app
                        .UseStatusCodePagesWithReExecute("/error/{0}")//UseStatusCodePagesWithRedirects改为UseStatusCodePagesWithReExecute 就变成服务端重定向
                        .UseRouting()
                        .UseEndpoints(routeBuilder => routeBuilder.MapGet("error/{status_code}", HandlerError))
                        .Run(context => Task.Run(() => context.Response.StatusCode = Random.Next(400,599)))
                    ))
                .Build()
                .Run();
        }

        private static async Task HandlerError(HttpContext context)
        {
            var code = context.GetRouteData().Values["status_code"];
            await context.Response.WriteAsync($"Error ({code})");
        }
    }
复制代码

编译异常信息:在mvc试图文件时可以动态编译的 直接部署视图的,所以由于试图文件是可以动态编译的 ,所以需要编译异常信息

MVC项目中需要添加包 Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation 同时设置被配表示使用动态编译视图

 

 

 

 

 

复制代码
namespace ConsoleApp4
{
    class Program
    {
        static void Main(string[] args)
        {
            var options = new DeveloperExceptionPageOptions
            {
                SourceCodeLineCount = 3
            };

            Host.CreateDefaultBuilder()
                .ConfigureWebHostDefaults(builder => builder
                    .ConfigureServices(collection => collection
                        .AddRouting()
                        .AddControllersWithViews()//mvc
                        .AddRazorRuntimeCompilation())//启用视图图文件运行时编译的
                    .Configure(app=>app
                        .UseDeveloperExceptionPage(options)
                        .UseRouting()
                        .UseEndpoints(routeBuilder => routeBuilder.MapControllers()))
                )
                .Build()
                .Run();
        }
    }

    public class HomeController : Controller
    {
        [HttpGet("/")]
        public IActionResult Index() => View();
    }
}
复制代码

 

 

 总结 :静态文件中间件(目录浏览,默认页面)

 路由 (终结点路由中间件,总结点中间件)

异常中间件 (开发者异常页面,异常处理中间件,响应状态码中间件(客户端重定向,服务器端重定向))

posted @   根仔  阅读(126)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 提示词工程——AI应用必不可少的技术
· 地球OL攻略 —— 某应届生求职总结
· 字符编码:从基础到乱码解决
· SpringCloud带你走进微服务的世界
点击右上角即可分享
微信分享提示