打开Global.asax.cs
先看一下RegisterRoutes方法,该方法用实现URL映射。也就是URL伪静态。
using System.Web.Mvc;
using System.Web.Routing;
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapServiceRoute<GameService>("game");
routes.MapServiceRoute<AuthService>("auth");
routes.MapServiceRoute<UserService>("user");
routes.MapServiceRoute<EventService>("event");
routes.MapRoute(
"Default",
"{controller}/{action}/{id}",
new { controller = "Home", action = "Index", id = UrlParameter.Optional });
}
routes.MapRoute(
"Default",
"{controller}/{action}/{id}",
new { controller = "Home", action = "Index", id = UrlParameter.Optional });
定义了一套默认的映射规则。当http://localhost:2448/Home/About页面时,访问的是controller里的HomeController的About方法。
注意:在命名时,默认情况下XXXController.cs对应View的XXX文件夹,而XXXController的YYY()方法对应XXX文件夹下的YYY.aspx。
这就是C→V的默认对应关系。
这里提到一个概念:扩展方法
假设我想给RouteCollection类扩展一个方法,但由于我无法动到RouteCollection类的代码。所以新做成一个RouteCollectionExtensions类。在RouteCollectionExtensions里定义扩展方法如下。
namespace System.Web.Mvc
{
public static Route MapRoute(this RouteCollection routes, string name, string url, object defaults);
}
第一个参数指出要扩展的类,以this为修饰符前缀。当你使用using指令将命名空间引入源代码时,扩展方法才有效。
值得注意的是,上面虽然以实例方式调用,但扩展方法却是静态方法。
使用扩展方法的风险是:不能保证扩展对象类修改后对扩展方法的影响。
扩展方法与类方法重名时(具有相同的签名),不会被调用。
查看mvc源代码。
public static Route MapRoute(this RouteCollection routes, string name, string url, object defaults, object constraints, string[] namespaces) {
if (routes == null) {
throw new ArgumentNullException("routes");
}
if (url == null) {
throw new ArgumentNullException("url");
}
Route route = new Route(url, new MvcRouteHandler()) {
Defaults = new RouteValueDictionary(defaults),
Constraints = new RouteValueDictionary(constraints)
};
if ((namespaces != null) && (namespaces.Length > 0)) {
route.DataTokens = new RouteValueDictionary();
route.DataTokens["Namespaces"] = namespaces;
}
routes.Add(name, route);
return route;
}
第一个参数"Default",是RouteCollection的键值。
第二个参数"Url",应该是Route规则。
第三个参数new { controller = "Home", action = "Index", id = UrlParameter.Optional }结合第二个参数"Url",表示一个默认Route。
再看routes.MapServiceRoute<GameService>("game");
这里的GameService是处理类名。相当于上面的Controller,game则对应方法。
Route的处理顺序应该是按照程序先后顺利来。
Service和Controller的区别是,Controller方法(Action)的返回值是ActionResult。
可以是Page,文件流或者是一个控件。具体可以参照下图。
类名 | 抽象类 | 父类 | 功能 |
ContentResult | 根据内容的类型和编码,数据内容. | ||
EmptyResult | 空方法. | ||
FileResult | abstract | 写入文件内容,具体的写入方式在派生类中. | |
FileContentResult | FileResult | 通过 文件byte[] 写入文件. | |
FilePathResult | FileResult | 通过 文件路径 写入文件. | |
FileStreamResult | FileResult | 通过 文件Stream 写入文件. | |
HttpUnauthorizedResult | 抛出401错误 | ||
JavaScriptResult | 返回javascript文件 | ||
JsonResult | 返回Json格式的数据 | ||
RedirectResult | 使用Response.Redirect重定向页面 | ||
RedirectToRouteResult | 根据Route规则重定向页面 | ||
ViewResultBase | abstract | 调用IView.Render() | |
PartialViewResult | ViewResultBase | 调用父类ViewResultBase 的ExecuteResult方法. 重写了父类的FindView方法. 寻找用户控件.ascx文件 |
|
ViewResult | ViewResultBase | 调用父类ViewResultBase 的ExecuteResult方法. 重写了父类的FindView方法. 寻找页面.aspx文件 |
Service的返回值是HttpResponseMessage,貌似是给json格式的ajax利用的。由于它与Action没什么关系所以我怀疑。RegisterGlobalFilters里的过滤器对它无效。