您的位置:首页 > 编程语言 > ASP

使用一般处理程序,模拟ASP.NET MVC,开发一个轻量级的学习版MVC框架。

2016-04-16 14:42 971 查看

使用一般处理程序,模拟ASP.NET MVC,开发一个轻量级的学习版MVC框架。

本篇博文是笔者学习MVC的总结

有人说MVC是一种设计模式,有人说MVC是一种框架,还有人说MVC是一种思想.

这里是整个项目的文件结构,模型层可以根据需求选用EntityFramework或者直接使用原生的ADO.NET,封装一个SQLHelper,再写一个实例化任意Model的方法.



这里是index.ashx,网站的单一入口点,网站所有的请求都要通过index.ashx处理

using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using System.Web;
using MVCFrameWork.Controllers;

namespace MVCFrameWork
{
/// <summary>
/// index 的摘要说明
/// </summary>
public class index : IHttpHandler
{
//关于HttpContext:在处理请求执行链的各个阶段中,
//                会有一个对象在各个对象之间进行传递,
//                也即会保存请求的上下文信息,
//                这个对象就是HttpContext对象
public void ProcessRequest(HttpContext context)
{
context.Response.ContentType        =   "text/plain";
C(context);                 //实例化任意控制器,并执行该控制器中的任意动作
}

private static void C(HttpContext context)
{
string controllerName               = (context.Request["C"] as string ?? "Home").ToLower();//获取HTTP请求中的控制器
controllerName                      = controllerName.Substring(0, 1).ToUpper() + controllerName.Substring(1) + "Controller";//容错处理
string actionName                   = (context.Request["A"] as string ?? "Index").ToLower();//获取HTTP请求中的动作
Assembly assembly                   = Assembly.GetExecutingAssembly();//获取当前应用程序域中,正在运行的程序集
string assemblyName                 = assembly.GetName().Name;//反射获取当前解决方案的名称
string controllerTypeName           = assemblyName + ".Controllers." + controllerName;//反射获取控制器的类型名,约定大于配置,约定好所有Controller文件,必须存放在Controllers文件夹下
if (File.Exists(context.Server.MapPath("Controllers") + "\\" + controllerName + ".cs"))//判断当前解决方案中,指定的相对目录中,是否存在指定控制器类文件
{
Type controllerType             = Type.GetType(controllerTypeName);//反射出控制器类型对象
if (!controllerType.IsClass)//如果反射出来的对象不是类,结束方法
return;
var controller = Activator.CreateInstance(controllerType);//动态创建控制器的实例
List<string> actions            = new List<string>();//创建一个集合存放当前控制器中的所有行为
foreach (var method in controllerType.GetMethods())//反射出控制器对象中的所有方法
{
actions.Add(method.Name);
}
if (actions.Contains(actionName))//检测当前action是否是可调用结构
{
try
{
var action              = controllerType.GetMethod(actionName);//反射出指定动作
var actionParameters    = action.GetParameters();//反射出参数
var actionAttributes    = action.GetCustomAttributes();//反射出自定义特性
foreach (var attr in actionAttributes)//过滤自定义特性
{
if((attr is ResPOST) && !context.Request.RequestType.Equals("POST"))
{
context.Response.Write("执行" + actionName + "失败,该action只响应POST请求");
return;
}
if (attr is NotAction)
{
context.Response.Write(actionName+"未定义");
return;
}
}

if (actionParameters.Length >= 1)//反射出参数
{
List<object> list  = new List<object>();
foreach(var param in actionParameters)
{
list.Add(context.Request[param.Name]);      //根据参数名,获取表单中的参数值并填充到集合中
}
action.Invoke(controller,list.ToArray());       //执行带表单参数的action
}
else {
action.Invoke(controller, null);                //执行动作,此处只执行无参数的action
}
}
catch
{
context.Response.Write("执行" + actionName + "失败");
}
}
else
{
context.Response.Write("未定义" + actionName + "动作");
}

}
else
{
context.Response.Write("未定义" + controllerName + "控制器");
}
}

public bool IsReusable
{
get
{
return false;
}
}
}
//林志霄 2016年4月16日
}


自定义的Controller基类

using System;
using System.Diagnostics;
using System.Runtime.CompilerServices;
using System.Web;

namespace MVCFrameWork.Controllers
{
public abstract class MyController
{
/// <summary>
/// 默认加载任意action的对应视图,也可以指定加载哪个视图
/// </summary>
/// <param name="context"></param>
/// <param name="viewName">视图的名字,使用了编译器特性,默认就是调用者的名称</param>
/// <param name="viewData"></param>
protected static void View([CallerMemberName]string viewName = "", params object[] viewData)
{
Debug.WriteLine(viewName);

//此处根据视图名字加载对应的视图文件
//约定大于配置,视图文件必须存放在Views文件夹下
}
}
//自定义特性,标志该方法只响应POST请求
public class NotAction : Attribute { }

//自定义特性,标志该方法不是Action方法
public class ResPOST : Attribute { }

}


这里是控制器的使用

namespace MVCFrameWork.Controllers
{
public class IndexController:MyController
{
public void index()
{
View();
}

[ResPOST]
public void login()
{
View();
}

[NotAction]
public void getModel() { }
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: