Java自学者论坛

 找回密码
 立即注册

手机号码,快捷登录

恭喜Java自学者论坛(https://www.javazxz.com)已经为数万Java学习者服务超过8年了!积累会员资料超过10000G+
成为本站VIP会员,下载本站10000G+会员资源,会员资料板块,购买链接:点击进入购买VIP会员

JAVA高级面试进阶训练营视频教程

Java架构师系统进阶VIP课程

分布式高可用全栈开发微服务教程Go语言视频零基础入门到精通Java架构师3期(课件+源码)
Java开发全终端实战租房项目视频教程SpringBoot2.X入门到高级使用教程大数据培训第六期全套视频教程深度学习(CNN RNN GAN)算法原理Java亿级流量电商系统视频教程
互联网架构师视频教程年薪50万Spark2.0从入门到精通年薪50万!人工智能学习路线教程年薪50万大数据入门到精通学习路线年薪50万机器学习入门到精通教程
仿小米商城类app和小程序视频教程深度学习数据分析基础到实战最新黑马javaEE2.1就业课程从 0到JVM实战高手教程MySQL入门到精通教程
查看: 522|回复: 0

【ASP.NET Core】处理异常(上篇)

[复制链接]
  • TA的每日心情
    奋斗
    2024-11-24 15:47
  • 签到天数: 804 天

    [LV.10]以坛为家III

    2053

    主题

    2111

    帖子

    72万

    积分

    管理员

    Rank: 9Rank: 9Rank: 9

    积分
    726782
    发表于 2021-5-14 13:26:36 | 显示全部楼层 |阅读模式

    依照老周的良好作风,开始之前先说点题外话。

    前面的博文中,老周介绍过自定义 MVC 视图的搜索路径,即向 ViewLocationFormats 列表添加相应的内容,其实,对 Razor Page 模型,也可以向 PageViewLocationFormats 列表添加相应的搜索路径,比如 /MyPages/{1}/{0}.cshtml。其中,0 是视图名,1 是页面名称。比如这样。

                services.AddMvc().AddRazorOptions(opt =>
                {
                    opt.ViewLocationFormats ...
     opt.PageViewLocationFormats ...
                });

    然而,我们知道,基于 Razor 的 Web Page 模型是以页面为单位的,也就是说路径路由是直接指向页面的(不包含.cshtml 扩展名),即不需要 MVC 模型的路由方式。所以,我们并不需要修改 PageViewLocationFormats 中的内容。许多时候,我们只要告诉应用程序在哪个目录下查找 Page 就行了。

    默认的搜索位置是 /Pages 目录,我们可以通过以下代码来修改。

            public void ConfigureServices(IServiceCollection services)
            {
                services.AddMvc().AddRazorPagesOptions(opt =>
                {
                    opt.RootDirectory = "/UI";             });
            }

    以上代码写在 Startup 类中,这个应该明白吧。RootDirectory 就是用来指定应用程序查找 Razor 页面的根目录路径,此处我指写了 /UI,所以,在我的项目中,我只要建一个 UI 目录,然后各类 Razor 页就往里面放就行了。

     

     ========================================================================================

    好了,题外话扯完了,开始说正题吧。今天咱们聊聊有关异常处理的破事吧,也可以说是错误处理,反正就这个意思,你理解就好,专业名词不必较劲,只有那些吃饱了撑着的“学术人才”才会跟名词较劲。

    老办法,咱们结合示例来讲述,这样各位观众不会乏味。

    大家知道,娱乐产品肾Phone已经成为流行玩具,近年来,购买肾Phone不一定只能用货币,比较典型的一种支付方式是卖肾买Phone。说实话,现在许多国产娱乐产品也很便宜,配置也不错,几百块钱就能玩得刷刷响了,割肾真没什么必要。

    为了方便人们以肾换 Phone ,老周特意开发了一个在线卖肾系统。大致流程是这样的,如果你有闲置的肾,可以打开主页,输入你的一些信息,然后报个价,其他用户看见后,如果觉得合理,就认购此肾。

     

     为了使操作流程更简单,易上手,轻入门,该平台只需要输入姓名和肾的价格即可参加报价。

     

    大致的页面代码如下。

            <form method="post">
                <div class="form-group">
                    <label for="name">姓名:</label>
                    <input type="text" class="form-control" name="name"/>
                </div>
                <div class="form-group">
                    <label for="price">价格:</label>
                    <input type="number" name="price" class="form-control"/>
                </div>
                <div class="form-group">
                    <button type="submit" class="btn btn-success w-100">提  交</button>
                </div>
            </form>

    Razor 页面很像我们以前玩过的 aspx 页面,每个页面都配套一个隐藏代码文件。Razor 页也会配有一个页面模型类,注意这个模型类要从 PageModel 派生,不是 Page 类,别搞错了,Page 类只是作为生成 HTML 代码的基类,我们的 .cshtml 文件在预编译后,是隐式继承自 RazorPage 类的。除非你要开发自己的标记语言,否则你不必理会这些类。

    记住了,与 Razor 页关联的模型类是从 PageModel 类派生的,比如,本例中,当有人填写了闲置肾的相关信息后,以 POST 方式提交,这是候,如果页面模型类中包含了名字为 OnPost、OnPostAsync ……的方法时,就会自动调用。如果想把我们上面那个 form 中的 name 和 price 的值传递给方法,直接让 OnPost 方法的参数与 form 中的元素名称相同就可以了。

        public class IndexModel : PageModel
        {
           public IActionResult OnPost(string name, decimal price)
            {
                if (string.IsNullOrWhiteSpace(name)) { throw new Exception("你怎么不留下姓名啊,卖肾又不是丢人的事。"); } if(price <= 0.0M) { throw new Exception("靠!你的肾这么不值钱吗?还免费送,包邮不?"); } return RedirectToPage("/Success");
            }
        }

    OnPost 不是 PageModel 基类的方法,而是我们自己写的,只是代码约定,Asp.net Core 里面用到很多代码约定,它在运行的时候会查找这些特定的名字。

    上面代码中,还对传递进来的 form 值进行验证,如果不符合要求,会抛出异常。

     

    一般来说,在 Startup 类的 Configure 方法中,我们会判断一下,如果应用程序处于开发阶段,为了方便测试,应该加入这些代码。

          if (env.IsDevelopment())
          {
               app.UseDeveloperExceptionPage();
          }

    这样,我们在测试时能看到详细的异常信息。

     

    但是,在实际便用时,我们不能公开这么详细的信息,这样容易勾起人们的犯罪冲动。所以,一般会添加一个页面,专门用来显示错误信息。比如:

    @page
    
    <div class="card">
        <div class="card-header bg-danger">
            <span class="text-light">错误</span>
        </div>
        <div class="card-body">
            <span class="card-text">唉,真抱歉。你提交的肾不符合国际标准,没人要的。</span>
        </div>
    </div>

     

    然后我们要在 Startup.Configure 方法中配置一下。

      app.UseExceptionHandler("/Error");

    加上这一行后,当发生异常时,就会跳转到 /Error 页面。

     

     不过,你也许会觉得,虽然不能公开异常信息,但一些必要的描述应该要的,不然,用户不知道发生了啥事。我们可以通过 HttpContext 的 Features 集合获取一个用来处理异常的 Feature,它的原型接口是 IExceptionHandlerFeature,我们不必关心它的实现类型是谁,只要访问它的 Error 属性就能得到关联的 Exception 实例。

    因此,我们的错误页可以改一下。

    @page
    @using Microsoft.AspNetCore.Diagnostics
    @{
     IExceptionHandlerFeature exf = HttpContext.Features.Get<IExceptionHandlerFeature>(); Exception ex = exf?.Error;
    }
    
    <div class="card">
        <div class="card-header bg-danger">
            <span class="text-light">错误</span>
        </div>
        <div class="card-body">
            @if (ex == null)
            {
                <span class="card-text">唉,真抱歉。你提交的肾不符合国际标准,没人要的。</span>
            }
            else
            {
                <span class="card-text">@ex.Message</span>
            }
        </div>
    </div>

    通过以下代码获得异常实例的引用。

        IExceptionHandlerFeature exf = HttpContext.Features.Get<IExceptionHandlerFeature>();
        Exception ex = exf?.Error;

    这样就可以在页面上显示异常的描述信息了。

     

     

     可能你又想到了,我不想输出个页面,我只想返回一些简单的文本,那么,你在 Startup.Configure 中可以这样写。

                app.UseExceptionHandler(x =>
                {
                    x.Run(async context => { var ex = context.Features.Get<Microsoft.AspNetCore.Diagnostics.IExceptionHandlerFeature>()?.Error; string msg = ex == null ? "发生错误。" : ex.Message; context.Response.ContentType = "text/plain;charset=utf-8"; await context.Response.WriteAsync(msg); });             });

    里面的变量 x 就是当前的 IApplicationBuilder ,与传递给 Configure 方法的 app 参数类型一样,这时候我们可以用 Reponse 的方法返回自定义的文本。

     

     好了,今天的内容就介绍到这儿吧,其实异常处理还有一种方法——使用 Filter,这个咱们留到下一篇博文再和大伙分享。

    本文示例源代码下载

     

    哎...今天够累的,签到来了1...
    回复

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    QQ|手机版|小黑屋|Java自学者论坛 ( 声明:本站文章及资料整理自互联网,用于Java自学者交流学习使用,对资料版权不负任何法律责任,若有侵权请及时联系客服屏蔽删除 )

    GMT+8, 2024-12-23 06:21 , Processed in 0.060932 second(s), 29 queries .

    Powered by Discuz! X3.4

    Copyright © 2001-2021, Tencent Cloud.

    快速回复 返回顶部 返回列表