惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

N
Netflix TechBlog - Medium
J
Java Code Geeks
爱范儿
爱范儿
雷峰网
雷峰网
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
博客园 - 三生石上(FineUI控件)
H
Hackread – Cybersecurity News, Data Breaches, AI and More
B
Blog RSS Feed
Google DeepMind News
Google DeepMind News
Jina AI
Jina AI
The GitHub Blog
The GitHub Blog
I
InfoQ
月光博客
月光博客
博客园 - 聂微东
博客园 - Franky
The Cloudflare Blog
阮一峰的网络日志
阮一峰的网络日志
博客园_首页
G
Google Developers Blog
Blog — PlanetScale
Blog — PlanetScale
L
LangChain Blog
罗磊的独立博客
Apple Machine Learning Research
Apple Machine Learning Research

博客园 - 阿不

10年总结,得到与失去 Windows phone7 软件发布:理财计算器(包括wp7房贷计算器,wp7个税计算器,wp7存款利息计算器) 从.NET到Mono-记Kooboo CMS对Mono的兼容历程:三、平台的兼容性 从.NET到Mono-记Kooboo CMS对Mono的兼容历程:二、大小写敏感问题,到处都是地雷 从.NET到Mono-记Kooboo CMS对Mono的兼容历程:一、Mono以及移平台的基本注意要点 ASP.NET MVC3 on Mono的折腾(一):Windows下的部署 ASP.NET MVC3 on Mono的折腾(二):Linux(openSUSE)下的部署 迟到的2010总结 周末随想之移动随笔 NVelocity for ASP.NET MVC ASP.NET 4.0在IIS6原生支持没有后缀名的URL请求 闲语MVC3和Razor ASP.NET MVC3 RC2和一些小bug DataAnnotation脱离MVC独立验证 Attribute与TypeDescriptor的故事 DataContext是否可以静态化? 今日手记:ASP.NET进程内的定时任务 有趣的同名不同约束泛型扩展方法的编译问题 在程序中动态执行T4模板,如何传参数给T4模板?
ASP.NET MVC 的统一异常处理有多难?(衍生的意图,出错后如何...
阿不 · 2010-12-05 · via 博客园 - 阿不

一个比较顺手的开发框架,我们都希望开发人员不要去太关心异常的处理,除了一个特定异常需要特定处理外,我们都希望我们很多普通的异常都能由框架来帮我们搞定。比如异常的日志记录,异常信息的提示,异常的进一步分类的判断等等,我们都不希望开发人员去使用相同或类似的代码去完成。简单来讲,我们不希望我们的代码中出现太多的try…catch 代码。如果在一个项目中,频繁出现try…catch的代码块,一方面代码不太优雅,另一方面也会给我们的代码编码带来一定的障碍,由于变量作用域(try和catch属于不同的代码块)的问题,我们很多时候不得不把变量定义在try…catch之外的代码块当中。因此,在很多业务逻辑的代码中,我们一般都不太会去专门做异常的处理,而相反,我们经常会根据业务逻辑的需要抛出很多业务逻辑异常出来,抛给UI或是业务调用者,而这种异常很多时候是希望显示给最终用户的友好信息提示。

因此,将异常的捕获,处理和显示放在UI代码中,无论从哪个角度来看都是最好的选择。结合ASP.NET MVC框架,为我们提供了的统一异常处理方案是重写Controller.OnException方法,或者是实现IExceptionFilter接口的ActionFilter。然而,这样真的就可以满足我们统一异常处理的需要吗?来看看下面的几种情况:

1.

public ActionResult Index()
{
    var model = GetModel();
    return View(model);
}

在这种情况下,假设在GetModel的时候出现了异常,这时我们别无他法,即时你把异常捕获处理了,返回到Index View任何无法显示任何有用的信息。此时,我们重定向到统一友好错误页面是可以接受的。因此,在这种情况下,MVC提供的异常处理机制来统一处理这种情况下的异常就会非常简单有效。

2.

[HttpPost]
public ActionResult Edit(User model)
{
    if (ModelState.IsValid)
    {
        SaveModel(model);
	 return RedirectToAction("Index", "Home")
    }
   
    return View(model);
}

在这种情况下,假设我们在SaveModel时出现了异常,这个异常假设不是系统性异常,而是一个业务性异常。我们更希望是的,在用户当前操作页面上提示该异常信息,保持用户输入值不变,用户只需要根据提示消息,修改一两个输入值即可再次提交表单,而不是重定向到错误提示页面之后再返回回来完全重新输入表单。在这种要求下,MVC提供的异常处理机制就无法满足需要,因为model这种异常在统一的异常处理上下文中无法得到。因此,我们就只能添加异常处理代码块了:

[HttpPost]
public ActionResult Edit(User model)
{
    try
    {
        if (ModelState.IsValid)
        {
            SaveModel(model);
	    return RedirectToAction("Index", "Home")
        }
    }
    catch (Exception e)
    {
        //log
        ModelState.AddModelError("", e.Message);
    }
    return View(model);
}

而这样的代码,正是我们所希望避免的,然而这样的性质的Action在我们的系统中比比皆是。不过,此时在满足某种前提条件的情况下,假设我们的Model变量名都是”model”,我们是有可能通过ActionExecutingContext.ActionParameters得到我们所要的model值,提供给View。通过这种workaround的处理,我们也许可以很好的绕过此问题。我们再来看另一种情况:

3.

[HttpPost]
public ActionResult Edit(User user)
{
    if (ModelState.IsValid)
    {
        SaveModel(user);
    }
    var model = GetModel(user.Name);
    ViewData["Title"] = "Edit";
    return View(model);
}

在这种情况下,也许我们除了try…catch外,真的没有其它更好的办法了。

异常处理一直都是我们软件开发过程当中,不得不去面对的麻烦。我们程序员都很害怕,因为一个个不可预期的异常而导致我们的业务模块无法正确运行,无法友好的提示给用户而招来抱怨,但是我们又不喜欢因为这些可能并不经常发生的意外而多做很多零碎事情,而且会让代码变得很丑。在一般的业务系统当中,我们更加不会加很多的catch并列句,去分门别类的处理各种各样的异常。如何更加简单,省事的把异常纳入可控的范围一直是我们努力的方向。