最近在做一个web项目,客户要求所有数据请求和响应都要采用ajax+handle方式,这个不难实现,公司以前的项目也大多都采用这种方式,按照公司以前的做法就是:新建一个handle.ashx,然后往里面不断增加响应ajax的方法,一般是一个ajax请求对应handle文件里的一个方法。这样做其实很麻烦,有时候一个项目做下来,handle文件里面写了上百个响应的方法,真心累,开始做这个项目的时候,我有个比较大胆的想法,能不能在handle.ashx里只写一个方法,响应整个web项目里所有的ajax请求呢?思考了一段时间后,我想到了反射技术,具体操作步骤如下:
其中的GetMethodParms()方法是我自己写的一个获取ajax请求(get或post都可以)中传递过来的参数的方法,因为一般ajax请求都要传参数到后台的,比如查询一个机构信息,肯定会传一个机构ID的参数,GetMethodParms()方法代码如下:
Sys_CompanyInfo_Bll类中的GetModel方法如下:
1、在前台ajax请求的url中加上需要调用的业务逻辑类的类名和方法名,如下所示,GetList参数就是最终响应这个ajax请求的方法,VehPositionList_Bll就是这个方法所在的类的类名,而ajax.ashx就是处理ajax请求的页面。
url: '~/Handler/ajax.ashx?type=VehPositionList_Bll&method=GetList'
2、在ajax.ashx中写一个响应方法,主要用到了反射技术调用前台传过来的xxx类中的xxxx方法,核心代码如下所示,注释写的很详细了,就不一一解释了
public class ajax : IHttpHandler
{
//设置反射的搜索方法的类型
private static readonly BindingFlags BINDINGFLAGS = BindingFlags.Static | BindingFlags.Instance | BindingFlags.Public | BindingFlags.IgnoreCase;
//设定逻辑处理层命名空间
private static readonly string BLLSPACE = "com.tz.hongyan.Bll";
public void ProcessRequest(HttpContext context)
{
context.Response.ContentType = "text/plain";
Assembly BLL = null;
try
{
//加载类库
BLL = Assembly.Load(BLLSPACE);
//根据类名获取类
Type t = BLL.GetType(BLLSPACE + "." + TypeName);
//实例化
object dObj = Activator.CreateInstance(t);
MethodInfo method = null;
if (MethodName.Length > 0)
{
//获取方法名
method = t.GetMethod(MethodName);
}
//通过反射调用方法
object[] param=InvokeHelper.GetMethodParms(method.GetParameters(), context);
object result = method.Invoke(dObj, BINDINGFLAGS, Type.DefaultBinder,param, null);
}
catch
{
context.Response.Write(string.Format("找不到类{0}或方法{1}", TypeName, MethodName));
context.ApplicationInstance.CompleteRequest();
}
}
#region
/// <summary>
/// 类名
/// </summary>
protected string TypeName
{
get {
string sConfig = System.Configuration.ConfigurationManager.AppSettings[UrlHandle.QueryUrl()];
string sType = UrlHandle.QueryParams("type");
return string.IsNullOrEmpty(sType) ? sConfig : sType;
}
}
/// <summary>
/// 方法名
/// </summary>
protected string MethodName
{
get {
string sMethod=UrlHandle.QueryParams("method");
return string.IsNullOrEmpty(sMethod) ? "GetList" : sMethod;
}
}
#endregion
public bool IsReusable
{
get
{
return false;
}
}
}
其中的GetMethodParms()方法是我自己写的一个获取ajax请求(get或post都可以)中传递过来的参数的方法,因为一般ajax请求都要传参数到后台的,比如查询一个机构信息,肯定会传一个机构ID的参数,GetMethodParms()方法代码如下:
/// <summary>
/// 获取方法的参数值
/// </summary>
/// <param name="parms"></param>
/// <param name="inContext"></param>
/// <returns></returns>
public static object[] GetMethodParms(ParameterInfo[] inParms, HttpContext inContext)
{
var objs = new object[inParms.Length];
for (var i = 0; i < inParms.Length; i++)
{
var parm = inParms[i];
if (parm.ParameterType == typeof(NameValueCollection))
{
if (parm.Name == "Form")
objs[i] = inContext.Request.Form;
else if (parm.Name == "QueryString")
objs[i] = inContext.Request.QueryString;
}
else
{
Type paramterType = parm.ParameterType;
if (parm.ParameterType.IsGenericType)
paramterType = Nullable.GetUnderlyingType(parm.ParameterType) ?? parm.ParameterType;
if (IsSimpleType(paramterType))
{
objs[i] = GetMethodParmValue(inContext.Request, parm.Name, parm.ParameterType);
}
}
}
return objs;
}
前台调用示例:
$.ajax({
type: "Post",
url: 'Handler/ajax.ashx?type=Sys_CompanyInfo_Bll&method=GetModel',
data: { inId: id },
datatype: "json",
async: false,
success: function (data) {
}
})
Sys_CompanyInfo_Bll类中的GetModel方法如下:
public string GetModel(decimal inId)//务必要保证参数名一致
{
string result = JsonHelper.Mode2Json(dal.GetModel(inId));
return result;
}
这样便大功告成,完美实现了一个方法响应了web平台所有ajax请求,这种方法不仅会使程序猿少写很多响应方法,而且它还有一个好处,
因为ajax.handle文件处理平台所有数据请求,即用户所有的CRUD操作,我们只需在ajax.handle里写一个日志记录的方法,这样,每次调用反射方法时就可以自动记录用户所有操作行为,两全其美!记录日志的方法很简单,大家自己写写吧!