今天你抛弃了ASP.NET了吗? @@银蛋篇@@

 

让一头大象跳舞,不是去找一头母象,而是一只小老鼠。

----  IT民工 第10xx01号“名言”

 

今天你抛弃了ASP.NET了吗?问题篇中,我被各位“猛士们”骂了个狗血淋头,感到鸭梨很大。既然已经里外不是人,我就爽快来个玉石俱焚,鱼死网破吧!这篇文章,我通过分析现有的一些前端开发技术,显示一种ASP.NET下的快速开发模型——银蛋(SILVER EGG)!

 

ASP.NET中的银蛋

------------------------------------------------------------------------

asp.net就是一头大象,为了让asp.net敏捷起来,无数的烈士们不断的去寻找着各种类型母象(ASP.NET AJAX, ASP.NET MVC, Nvelocity...),可是这头大象就是提不起精神。既然如此难伺候,那我何不请只小老鼠出来试试?

我先展示一下快速开发模型的代码和实现,然后介绍我的思考过程和资料收集过程。

1. 我的小老鼠-- JsonPage

ExpandedBlockStart.gif 代码
using System;
using System.Collections.Generic;
using System.Text;
using System.Reflection;
using System.ComponentModel;
using System.Globalization;
using System.Data;

namespace AspNetSilverBullet
{
    public class JsonPage
< T >  : System.Web.UI.Page
    {
        protected override void OnLoad(EventArgs e)
        {
            // if Non-json request, directly return.
            if (Request.QueryString.Count == 0) { base.OnLoad(e); return; }

            // get method name
            string methodname = Request.QueryString["method"];

            // reflect method info.
            MethodInfo method = typeof(T).GetMethod(methodname);

            // construct method call arguments
            List
< object >  arguments = new List < object > ();
            foreach (ParameterInfo parameterType in method.GetParameters())
            {
                arguments.Add(EnsureType(parameterType.ParameterType, Request.QueryString[parameterType.Name]));
            }

            // reflect object instance
            object targetObject = typeof(T).GetConstructor(Type.EmptyTypes).Invoke(new object[] { });

            // invoke method result
            object result = method.Invoke(targetObject, arguments.ToArray());

            // response
            Response.Clear(); Response.Write(ObjectToJson(result)); Response.Flush(); Response.End();
        }
        private object EnsureType(Type targetType, string argument)
        {
            if (targetType.Equals(typeof(string))) return argument;
            return TypeDescriptor.GetConverter(targetType).ConvertFrom(null, CultureInfo.InvariantCulture, argument);
        }
        private string ObjectToJson(object result)
        {
            if (result == null) return "0";
            if (result.GetType().IsValueType) return result.ToString();
            if (result.GetType().Equals(typeof(string))) return result.ToString();
            if (result.GetType().Equals(typeof(DataTable))) return DataTableToJson(result as DataTable);
            return result.ToString();// TODO use Newtonsoft to serialize object to json.
        }
        private string DataTableToJson(DataTable table)
        {
            StringBuilder builder = new StringBuilder();
            builder.Append("[");
            foreach (DataRow row in table.Rows)
            {
                builder.Append("{");
                foreach (DataColumn column in table.Columns)
                {
                    builder.AppendFormat("\"{0}\"", column.ColumnName.Trim().ToUpper()); builder.AppendFormat(":", new object[0]);
                    if (column.DataType.IsValueType) { builder.Append(row[column]); } else { builder.Append("\"").Append(row[column]).Append("\""); } builder.Append(",");
                }
                builder.Remove(builder.Length - 1, 1); builder.Append("},");
            }
            if (builder.Length > 1) { builder.Remove(builder.Length - 1, 1); } builder.Append("]");
            return builder.ToString();
        }

    }
}
 

这是个继承了Page的类,负责分析用户请求,转化为JSon请求,然后返回客户端。

 

2. Default.aspx + Default.aspx.cs 微软的大象

ExpandedBlockStart.gif 代码
<% @ Page Language = " C# "  AutoEventWireup = " true "  CodeFile = " Default.aspx.cs "  Inherits = " _Default "   %>
< html  xmlns ="http://www.w3.org/1999/xhtml" >
< head  runat ="server" >
    
< title > Asp.net Silver Bullet </ title >
    
< script  type ="text/javascript"  src ="js/jquery-1.2.3.min.js" ></ script >
    
< script  type ="text/javascript"  src ="js/ejs.04.js" ></ script >
    
< script  type ="text/javascript"  src ="js/parseuri.js" ></ script >
    
< script  type ="text/javascript"  src ="js/getfunctionname.js" ></ script >
    
    
< script  type ="text/javascript" >   //  jquery extend by pixysoft, http://www.cnblogs.com/zc22    
     function  invoke(param,callback)    
    {
        
var  method  =  getFnName(invoke.caller);      
        $.get(parseUri(window.location).file
+ " ?method= " + method, param, callback);              
    }
    
</ script >
    
    
< script  type ="text/javascript" >   //  jquery ajax
    $(document).ready( function ()  //  register event
    { 
        $(
" #Button1 " ).bind( " click " , Caculate);        
    });       
    
function  Caculate()  //  invoke server side.
    {
        invoke({ a: $(
" #Text_a " ).val(), b: $( " #Text_b " ).val() },  function (responseText,textStatus)
        {
            $(
" #Text1 " ).val(responseText);
        });           
    }       
    
</ script >     
</ head >
< body >
< div >
    
< b > Asp.net + Jquery Example: </ b >< br  />
    a:
< input  id ="Text_a"  style ="width: 52px"  type ="text"   />
    b:
< input  id ="Text_b"  style ="width: 52px"  type ="text"   />
    Result:
< input  id ="Text1"  type ="text"   />< input  id ="Button1"  type ="button"  value ="Invoke Value"  style ="width: 104px"   />
</ div >
</ body >
</ html >

 

ExpandedBlockStart.gif 代码
using  System;
using  System.Data;
using  System.Configuration;
using  System.Collections;
using  System.Web;
using  AspNetSilverBullet;

public   partial   class  _Default : JsonPage < DefaultController >
{
}

  

3. 让大象跳舞吧!

using  System;
using  System.Data;
using  System.Configuration;

public   class  DefaultController
{
    
public   int  Caculate( int  a,  int  b)
    {
        
return  a  +  b;
    }
}

 

 

4. 大象的舞姿!

 

 

5. 银蛋下载:

http://www.boxcn.net/shared/4t3qpevyap

 

 

银蛋的 WHAT? HOW? WHY?

------------------------------------------------------------------------

1. 什么是JsonPage, 为什么继承Page?

JsonPage就是一个HttpHandler,通过拦截页面的ajax回调请求,反射逻辑方法,然后返回json结果。

同时JsonPage使用了泛型参数作为了逻辑方法的注册机制,极大简化了开发。

 

首先,我必须使用ASP.NET,否则所有c#代码都会报废。

我曾经思考过HttpHandler,虽然实现一个Httphandler,然后在web.config里面注册,貌似整个架构变得很干净。但是,在实际使用中,用户对服务端发出的URL请求如何被映射到我的逻辑类里面呢?

如果用spring的机制,另写一个xml做映射,这简直就是自掘坟墓。一个action写一个xml,那么一个网站不就100+条的配置了?而且一旦修改起来,很快就会崩溃,接下来就需要再写一个xml配置器了;之后xml配置器变得庞大功能越来越多,就希望集成到VS里面了。。。然后就是自己不断给自己挖坑,还被蒙的理所当然。

ASP.NET使用了一些trick,在aspx文件头有个<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %>, 这是啥?这个就是个spring的动态加载!微软把用户请求路由到了磁盘的aspx文件,然后读取了头声明,动态加载了逻辑类(Codebehind),然后输出的时候再过滤掉头声明。

多么的优雅又巧妙的设计!这个是Java servlet学不来的!而且Page最终会被动态编译为一个HttpHandler。

既然微软提供了如此优雅的架构,我何不顺手拈来!

所以,最终我使用了一个继承JsonPage的类作为拦截器。即利用了微软aspx的优势,同时又嵌入了自己

 

2. 不使用Web Control, 页面如何回调服务端代码?

这部分就是微软的ASP.NET大象,也是让我最头疼的地方。最终:

前端我使用了Jquery作为页面的核心模块;

使用了来自博客园伟大的司徒正美的Javasctipt Template(EJS)作为前端模板

再引入了一些技巧性的Javascipt,例如获取当前页面请求的URl、当前JS调用的函数名等,简化JS代码。因此我们调用一个服务端代码仅仅需要:

注册js事件:

$( " #Button1 " ).bind( " click " , Caculate);  

 

声明js事件内容并回调 invoke(param, callback):

ExpandedBlockStart.gif代码

     function  Caculate()  //  invoke server side.
    {
        invoke({ a: $(
" #Text_a " ).val(), b: $( " #Text_b " ).val() },  function (responseText,textStatus)
        {
            $(
" #Text1 " ).val(responseText);
        });           
    }    

 

通过一些js技巧,前端的js函数直接调用了服务端同名的类方法,简化了开发流程。

 

之前花了一个多星期搜索前端开发的技术,看了EXTJS,那500k+的体积让我顿时害怕。看了Mootools/Prototype/YUI等等,最终选择了Jquery,原因只有一个,很多人在用。多人用,就意味着很多人会在JQuery有贡献有积累,有沟通。我们快速开发网站也变得更加容易(copy+Paste嘛)。

 

可是Jquery仅仅实现了一个选择器的功能,涉及到了和服务器互通又遇到了困难。网络有人介绍使用web service / WCF / HttpHandler等和Jquery通讯,可是我实在没有兴趣。一个简单的http调用干嘛又要引入一堆的技术架构?而且使用了web service等,项目开发部署又变得复杂了,肯定又被PHP们嘲笑了。所以我就十两挑千斤,回归Page。

 

使用原有的aspx技术,如何去控制页面逻辑呢?例如最简单的GridView、Repeater之类的。于是看了Php/Cocoon/NVelocity/ASP.net MVC。但是都让我很失望。无意中搜索到了JQuery Template,顿时眼前一亮。我搜索了JavaScript Micro-TemplatingJTS(Javascript Template Syntax)微软的JQuery提议甚至是让我非常激动的PURE,可是,他们离完美就是这么的差一点,So Close...。最后,我来到了博客园的司徒正美,我知道我找到了。首先不需要写各种奇怪的模板标记({{ }} ...)其次用JS就完美演绎了页面模板编程,这让前端的技术学习曲线下降了很多。使用司徒的模板,我们仅仅需要:

ExpandedBlockStart.gif 代码
     < script id = " tmpl "  type = " text/html " >   < ## javascript template # >
            
< ul >
                
< for ( var  i = 0 ; i <  json.length; i ++ ){ # >
                
< li >< # =   json[i].COLUMN # >< / li>
                 < #  }  # >
            
< / ul>
     < / script>    

 

多么的优雅啊。

 

 

后续

------------------------------------------------------------------------

曾经,作为一名asp.net的我,总是发现google的前端技术, fackbook, kaixin001, digg等等他们的前端技术离我很远。看着他们很炫的JS效果,丰富的plugin,我总是不知所措。我真的很想用,但是一打开VS20xx,打开了aspx就不知所措,仿佛他们是来自另外一个世界的。

现在,我总算尝试走出了一步。

用了本文的思路,业务逻辑可以完全打包进入一个类库DLL,前端也完全可以脱离了asp.net的代码,直接用JS写各种逻辑。上一篇怨文中各种问题都不再出现。

而且,我并没有改变ASPX的开发习惯,页面还是那个页面,c#还是那个c#。如果有人觉得不爽,想用web control, 用<%%>服务端标记也没有任何问题。

这,还不能作为一个银弹吗?

 

 

转载于:https://www.cnblogs.com/zc22/archive/2010/09/29/1838232.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值