对于asp.net mvc 2.0 异步控制器中hard code的一点不满
微软的.net类库里面好多对象的名字为了统一都有个基本的约定,比如接口名称以I开头,事件信息类型以EventArgs结尾等等。为了代码的可读性,作为程序员最好去遵守这些约定,这些约定我认为仅仅是为了代码的可读性,而不是必须的,而有一天你一觉醒来却发现:如果接口名称不以I开头,接口就会报错。事件信息类型不以EventArgs结尾也会报错。。。。。。。。。
我想肯定会豪迈的喊出fuck ms。当然上面的事情没有发生,但是我今天在翻阅微软的新框架asp.net mvc 2.0的时候。类似的事情却出现了。
asp.net mvc 2.0版本中新增了异步的控制器(asynchronous controllers);异步控制器的实现方式如下:
namespace MvcApplication1.Areas.Store.Controllers
{
public class HomeController : AsyncController
{
}
}
一般控制器继承自Controller而异步控制器继承自AsyncController。这个没什么问题,继续看一部Action。
继承自AsyncController的控制器既可以当作异步控制器来使用,也可以当作同步控制器来使用,这个主要取决于UI所申请的Action的签名。这就是我今天要说的问题:
- 如果Action的名称以Async结尾则按照异步执行
- 如果Action的名称不以Async结尾则按照同步执行
例子:

namespace MvcApplication1.Areas.Store.Controllers
{
public class HomeController : AsyncController
{
/// <summary>
/// 如果UI请求该Action,则按照异步执行,因为以Async结尾
/// </summary>
public void IndexAsync()
{
}
/// <summary>
/// 如果UI请求该Action,则按照同步执行,没有以Async结尾
/// </summary>
public void Home()
{
}
}
}
硬码一:通过action名称后面是否加Async来判断是否是异步操作
当然异步肯定需要回调函数了。如果有一个ActionNameAsync的异步action,asp.net mvc 2.0要求必须要有一个对应的ActionNameCompleted与之对应(必须要和前面的Action名字相同且以Completed结尾),否则用户在请求ActionName的时候会产生运行时异常的。
所以上面的代码要想正确的运行,则应该修改为:

namespace MvcApplication1.Areas.Store.Controllers
{
public class HomeController : AsyncController
{
/// <summary>
/// 如果UI请求该Action,则按照异步执行
/// </summary>
public void IndexAsync()
{
}
/// <summary>
/// 遥相呼应
/// </summary>
public void IndexCompleted()
{
}
/// <summary>
/// 如果UI请求该Action,则按照同步执行
/// </summary>
public void Home()
{
}
}
}
这样UI在请求Index Action的时候才不会产生运行时异常。
硬码二:通过Action名称后面是否加Completed来寻找回调函数(说回调函数可能有点不准确)
另外在异步controller中,asp.net mvc 2.0还不允许在同一个异步controller中出现ActionName和ActionNameAsync这样的Action。否则也会爆出运行时异常。
例如下面的代码在UI请求Index Action的时候就会产生运行时异常。

namespace MvcApplication1.Areas.Store.Controllers
{
public class HomeController : AsyncController
{
/// <summary>
/// 如果UI请求该Action,则按照异步执行
/// </summary>
public void IndexAsync()
{
}
/// <summary>
/// 遥相呼应
/// </summary>
public void IndexCompleted()
{
}
public void Index()
{
}
/// <summary>
/// 如果UI请求该Action,则按照同步执行
/// </summary>
public void Home()
{
}
}
}
UI请求Index时的异常信息为

--------------------------------------------------------------------------------
对控制器类型“HomeController”的操作“index”的当前请求在下列操作方法之间不明确:
类型 MvcApplication1.Areas.Store.Controllers.HomeController 的 Void IndexAsync()
类型 MvcApplication1.Areas.Store.Controllers.HomeController 的 Void Index()
上面的这些种种现象,作为一名程序员是完全可以理解的,我也做过通过某个字符和特征来识别不同请求的事情,但是个人认为微软作为一个软件帝国,作为asp.net mvc的发布方,以hard code的形式来区分异步和非异步实在是让人有点难以接受(但是还是接受了)。asp.net mvc 3.0 preview1版本已经发布了,不知道有什么改进。