当HTTP发送http://localhost/App/IndexController/Index.htm请求时,
IIS会查看Web.Config中的配置.URL正好符合*.htm这个过滤条件
于是IIS会在Bin目录下查找具有NFinal.Handler.HandlerFactory的类,
并调用其中的GetHandler返回Handler对象,然后再调用Handler对象的BeginProcess方法.
/// <summary> /// NFinal框架重写的HttpHandlerFactory /// </summary> public class HandlerFactory:IHttpHandlerFactory { /// <summary> /// 返回一个用于处理HttpRequest的类 /// </summary> /// <param name="context"></param> /// <param name="requestType"></param> /// <param name="url"></param> /// <param name="pathTranslated"></param> /// <returns></returns> public IHttpHandler GetHandler(HttpContext context, string requestType, string url, string pathTranslated) { return new Handler(); } /// <summary> /// 释放占用的资源,实际无效果 /// </summary> /// <param name="handler"></param> public void ReleaseHandler(IHttpHandler handler) { } }
而handler类中有一个BeginProcess方法
{ try { //这里调用了Main函数 Main main = new Main(); main.Run(context); } catch (Exception ex) { context.Response.Write("exception eccurs ex info : " + ex.Message); } finally { context.Response.End(); EndProcess();////最后别忘了end } }
Main函数用于理URL,把不同的URL分发给不同的模块.此类位于NFinal根目录下,由生成器生成.
{ protected string GetString(string val, string de) { return string.IsNullOrEmpty(val) ? de : val; } protected string UCFirst(string val) { CultureInfo cultureInfo = Thread.CurrentThread.CurrentCulture; return cultureInfo.TextInfo.ToTitleCase(val); } //第一个是app/第二个是Controller/第三个是Folder/第四个是Controller_Short/第五个是方法名/第六个是参数 private static Regex reg = new Regex(@"(/[^/\s]+)(((?:/[^/\s]+)*)/([^/\s]+)Controller)/([^/\s.]+)((?:/[^/\s.]+)*)", RegexOptions.IgnoreCase); public void Run(HttpContext context) { string[] hostName=context.Request.Url.Host.ToString().Split('.'); string subdomain=hostName.Length==3?hostName[0]:"www"; string folder = "/Manage"; string controller = "/Manage/Index"; string app = "/App"; string controller_short = "Index"; string action = "Index"; string[] parameters = null; string url = context.Request.RawUrl; NameValueCollection get = new NameValueCollection(); Match mat= reg.Match(context.Request.Path); if (mat.Success) { app =GetString(mat.Groups[1].Value,app); controller = GetString(mat.Groups[2].Value, folder); folder =mat.Groups[3].Value; controller_short =GetString(mat.Groups[4].Value,controller_short); action =GetString(mat.Groups[5].Value,action); if(mat.Groups[6].Success) { parameters = mat.Groups[6].Value.Split('/'); //如果长度为奇数说明正确 if((parameters.Length&1)==1) { int count=parameters.Length>>1; if (count > 0) { for (int i = 0; i < count; i++) { get.Add(parameters[((i << 1)+1)], parameters[(i << 1) + 2]); } } } } if (context.Request.Form.Count > 0) { for (int i = 0; i < context.Request.Form.Count; i++) { get.Add(context.Request.Form.Keys[i], context.Request.Form[i]); } } switch (app) { case "/App": { WebMvc.App.Router router = new WebMvc.App.Router(); router.Run(context,subdomain, app, folder, controller, action,get); break; } default: break; } } else { context.Response.Write("wrong url"); } } }
测测到请求是属于App模块,就去调用此模块下的Router类.
而Router类的Run方法负责调用具体类下的具体函数,执行输出字符串操作.
{ private string GetString(string val, string de) { return string.IsNullOrEmpty(val) ? de : val; } private string UCFirst(string val) { CultureInfo cultureInfo = Thread.CurrentThread.CurrentCulture; return cultureInfo.TextInfo.ToTitleCase(val); } public void Main(System.Web.HttpContext context) { string module = "index"; string action = "index"; string[] pathInfo = null; NameValueCollection get = new NameValueCollection(); if (!string.IsNullOrEmpty(context.Request.PathInfo)) { pathInfo = context.Request.PathInfo.Trim(new char[] { '/' }).Split('/'); module=UCFirst(GetString(pathInfo[0], module)); action=GetString(pathInfo[1], action); if (pathInfo.Length > 2) { for (int i = 2; i < pathInfo.Length; i += 2) { get.Add(pathInfo[i], pathInfo[i + 1]); } } } else { module =UCFirst(GetString(context.Request.QueryString["m"], module)); action =GetString(context.Request.QueryString["a"], action); } //Run(context,module,action,get); } public void Run(System.Web.HttpContext context,string subdomain,string app,string folder,string controller,string action,NameValueCollection get) { switch (controller) { //relativeName="/Manage/IndexController" //RelativeDotName=".Manage.IndexController" case "/IndexController": { switch (action) { case "Index": { Web.Default.IndexController.IndexAction control= new Web.Default.IndexController.IndexAction(context.Response.Output); control._context = context; control._subdomain = subdomain; control._url=context.Request.RawUrl; control._get = get; control._app=app; control._controller = controller; control._action = action; control.Before(); control.Index(); control.After(); break; } default: context.Response.Write("找不到类" + controller + "下的" + action + "方法");context.Response.End(); break; } break; } //relativeName="/Manage/IndexController" //RelativeDotName=".Manage.IndexController" case "/SampleController": { switch (action) { case "Show": { Web.Default.SampleController.ShowAction control= new Web.Default.SampleController.ShowAction(context.Response.Output); int id=get["id"]==null?5:int.Parse(get["id"]); control._context = context; control._subdomain = subdomain; control._url=context.Request.RawUrl; control._get = get; control._app=app; control._controller = controller; control._action = action; control.Before(); control.Show(id); control.After(); break; } default: context.Response.Write("找不到类" + controller + "下的" + action + "方法");context.Response.End(); break; } break; } //relativeName="/Manage/IndexController" //RelativeDotName=".Manage.IndexController" case "/Common/Public": { switch (action) { case "Success": { Web.Default.Common.Public.SuccessAction control= new Web.Default.Common.Public.SuccessAction(context.Response.Output); string message=get["message"]==null?null:get["message"];string url=get["url"]==null?null:get["url"];int second=get["second"]==null?0:int.Parse(get["second"]); control._context = context; control._subdomain = subdomain; control._url=context.Request.RawUrl; control._get = get; control._app=app; control._controller = controller; control._action = action; control.Before(); control.Success(message,url,second); control.After(); break; } case "Error": { Web.Default.Common.Public.ErrorAction control= new Web.Default.Common.Public.ErrorAction(context.Response.Output); string message=get["message"]==null?null:get["message"];string url=get["url"]==null?null:get["url"];int second=get["second"]==null?0:int.Parse(get["second"]); control._context = context; control._subdomain = subdomain; control._url=context.Request.RawUrl; control._get = get; control._app=app; control._controller = controller; control._action = action; control.Before(); control.Error(message,url,second); control.After(); break; } default: context.Response.Write("找不到类" + controller + "下的" + action + "方法");context.Response.End(); break; } break; } default: context.Response.Write("找不到类" + controller); context.Response.End(); break; } } }
而最终调用的类是这个样子.
using System.Collections.Generic; using System.Web; namespace WebMvc.App.Web.Default.IndexController { public class IndexAction : NFinal.BaseAction { public IndexAction(System.IO.TextWriter tw):base(tw){} public IndexAction(string fileName) : base(fileName) {} public void Index() { Write("<!doctype html><html><head><script src=\"/App/Content/js/jquery-1.11.2.min.js\"></script><link href=\"/App/Content/css/frame.css\" type=\"text/css\" rel=\"stylesheet\" /><style type=\"text/css\"> .auto-style1 { width: 140px; } .auto-style2 { width: 197px; } </style></head><body>"); Write("\r\n<header class=\"header\">\r\n NFinal框架:这是头\r\n</header><article> Hello,NFinal! </article>"); Write("\r\n<footer>\r\n NFinal框架.这是尾\r\n</footer></body></html>"); } } }