纸上得来终觉浅,绝知此事要躬行,若干年后,自己曾经写过的博文,收藏的博文也许成为自己学习的地方。写不出什么洋洋洒洒的文章,也没有生花妙笔的天赋,只希望用自己稍微一点点的坚持来弥补这些先天的不足。
我这个人不喜欢长篇大作,也不喜欢议论纷纷,只是将自己突然想到的,记录下来,因为我喜欢健忘,甚至不到1分钟就可以将自己脑海中闪过的一个东西忘得一干二净。
前面的博文中也说过,在写一个东西之前我总喜欢写一下自己的一些想法,和感触,当这些介绍完了之后,内容却是言简意赅,只言片语,让别人看了不知所云,所以今天决定一改前面的作风,来一个长篇累牍。
最近完成了《ArcGIS API for Javascript开发教程》,目前正在校正之中,不久便会和大家见面,在我分享这个的同时,也希望得到大家的指点,算是互惠吧!
在开发教程中有一章是JavaScript和服务器通讯相关的内容,因为时间关系,我只介绍了Web Service,准备后期补充点其他的料,这样内容也会让人觉得丰满点,其实通讯不仅仅用Web Service,JSP,ASP .NET等也是可以的,今天的这篇博文就是因为ASP.NET而突发其感。
ASP.NET的开发跟是将后台处理和HTML混合在一起了,初次接触的话可能不太适应,在这里我只讨论后台的这个,也就是和.aspx相关的.aspx.cs文件。在添加了一个aspx页面的时候,往往会在头文件中添加一行类似下面的语句:
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="WebX.aspx.cs" Inherits="AspWebTest.WebX" %>
意思也应该很明确,就是当请求来的时候,可以交由CodeBehind指定的这个cs页面去处理,往往我们将这种方式就叫做“CodeBehind”,这种方式实现了页面布局和后台逻辑的分离,这也是ASP.NET的一个特点吧,因为ASP.NET的一个aspx不仅仅有一个这样的后台处理文件,还可以动态的生成浏览器可以识别的HTML文件,所以这个aspx文件就有了自己特有的生命周期,比如说何时实例化前台的这些服务器控件,什么时候初始化完毕等,页面什么时候加载完毕等,当然在.cs文件中有一个很重要的事件 protected void Page_Load(object sender, EventArgs e),对我们来说,代码往往就是从这里开始的。
也许说了这么多,看得人都看晕了,都不知道我在说什么,其实我也有点迷糊,因为按照我的作风,上代码让大家瞧一瞧似乎更能说明问题,但是已经说了是累牍,将就下吧。
如果我们要实现Javascript向ASP.NET发送请求,那么我们只需要在Page_Load下面通过Request对象和Response对象即可,将.aspx 页面中的东西都删除,只留下这样的一句话:
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="WebX.aspx.cs" Inherits="AspWebTest.WebX" %>
如果还有其他的服务器控件,那么我当请求的时候,由于ASP.NET的生命周期,这些控件是要被解析的,这个是要时间的,因为我现在的目的是和这个无关的,所以只留下最开始的一句话。
这个功能是实现一个摄氏温度和华氏温度的转换,我自己新建一个html文件,ASP.NET工程生成默认的aspx文件被弃而不用,或者删掉自己新建立一个,通讯是通过XMLHttpRequest对象来完成的,相信看的人对这个已经很了解。现在很多框架都很好的封装了XMLHttpRequest,在这里我是原生的。
namespace AspWebTest
{
public partial class WebX : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
string pStringAspx= HttpContext.Current.Request.RawUrl.ToLower();
//如何阻止用户直接访问aspx文件
//是否首次加载
if (!Page.IsPostBack)
{
Response.Clear();
string temp = Request.QueryString["q"];
if (temp != null)
{
try
{
double tempC = double.Parse(temp);
string pResult = GetTem(tempC).ToString();
Response.Write(pResult);
}
catch
{ }
}
Response.End();
}
}
public double GetTem(double pTemp)
{
double pResult = pTemp * 5 / 9 + 32;
return pResult;
}
}
}
HTML文件的内容如下:
<html>
<head>
<title>温度转换</title>
<script type="text/javascript">
var xmlHttp;
var is_ie = (navigator.userAgent.indexOf('MSIE') >= 0) ? 1 : 0;
var is_ie5 = (navigator.appVersion.indexOf("MSIE 5.5")!=-1) ? 1 : 0;
var is_opera = ((navigator.userAgent.indexOf("Opera6")!=-1)||(navigator.userAgent.indexOf("Opera/6")!=-1)) ? 1 : 0;
//netscape, safari, mozilla behave the same???
var is_netscape = (navigator.userAgent.indexOf('Netscape') >= 0) ? 1 : 0;
function show_data(strName){
if (strName.length > 0){
//访问的文件和参数
var requestURL = 'WebX.aspx?q=';
//var requestURL = "HandlerData.ashx?q=";
var url = requestURL + strName;
//创建发送请求的 XMLHTtp对象
xmlHttp = GetXmlHttpObject(stateChangeHandler,error);
//向那个特定的url发送xmlHttp请求
xmlHttp_Get(xmlHttp, url);
}
else {
document.getElementById('nameList').innerHTML = '';
}
}
//用来监控xmlhttp对象的状态,每次状态改变它就会fire
function stateChangeHandler()
{
if (xmlHttp.readyState == 4 || xmlHttp.readyState == 'complete'){
//返回结果
var str = xmlHttp.responseText;
document.getElementById('result').innerHTML = str;
}
}
function xmlHttp_Get(xmlhttp, url) {
xmlhttp.open('GET', url, true);
xmlhttp.send(null);
}
function error() {
alert("出现错误!");
}
function GetXmlHttpObject(handler,error) {
var objXmlHttp = null;
//根据不同的浏览器创建不同的对象
if (is_ie){
var strObjName = (is_ie5) ? 'Microsoft.XMLHTTP' : 'Msxml2.XMLHTTP';
try{
objXmlHttp = new ActiveXObject(strObjName);
objXmlHttp.onreadystatechange = handler;
}
catch(e){
alert('IE detected, but object could not be created. Verify that active scripting and activeX controls are enabled');
return;
}
}
else if (is_opera){
alert('Opera detected. The page may not behave as expected.');
return;
}
else{
// Mozilla | Netscape | Safari
objXmlHttp = new XMLHttpRequest();
objXmlHttp.onload = handler;
objXmlHttp.onerror = error;
}
//返回实例化的对象
return objXmlHttp;
}
function UseValue(strVal){
document.frmStuff.txtName.value = strVal;
}
</script>
</head>
<body>
<table border="0" cellpadding="4" cellspacing="0" id="Table2">
<tr>
<td width="100">测试:</td>
<td><input type="text" name="txtName" id="txtName" autocomplete="off" onkeyup="show_data(this.value);"/></td>
</tr>
<tr>
<td width="100" valign="top">结果:</td>
<td>
<div id="result"></div>
</td>
</tr>
</table>
</body>
</html>
可以自己去跟踪下这个代码,看下,因为aspx是和html页面相关的,而我的目的只想处理请求和接受请求,那么这个也是有办法的,可以用ashx文件,关于这个大家可以动手搜索下相关资料。和aspx文件类似,在创建了ashx文件后,也有一个与其相关的.cs文件,在ashx文件中的声明都很雷同。
<%@ WebHandler Language="C#" CodeBehind="HandlerData.ashx.cs" class="AspWebTest.HandlerData" %>
代码内容如下:
using System; using System.Collections.Generic; using System.Linq; using System.Web; namespace AspWebTest { /// <summary> /// HandlerData 的摘要说明 /// </summary> public class HandlerData : IHttpHandler { public void ProcessRequest(HttpContext context) { context.Response.ContentType = "text/plain"; context.Response.Clear(); string temp = context.Request.QueryString["q"]; if (temp != null) { try { double tempC = double.Parse(temp); string pResult = GetTem(tempC).ToString(); context.Response.Write(pResult); } catch { } } context.Response.End(); } public bool IsReusable { get { return false; } } private double GetTem(double pTemp) { double pResult = pTemp * 5 / 9 + 32; return pResult; } } }
功能算是实现了,但是有没有发现,后台的CS都是一个类,却没有构造函数,如果自己定义了一个带参数的构造函数,那么程序是运行不成功的。
public HandlerData(int x) {
}
错误信息自己可以看下。
不管是ashx,还是Web Service,或者aspx 都必须有一个不带参数的构造函数,因为默认没有定义,系统会自己生成,这个不带参数的构造函数才是我今天的话题,此事峰回路转,对不住了,我这个人喜欢乱想,也不知道是不是脑子有问题,类的是对象的模板,但是用的时候是要有具体的对象的,而对象是构造函数产生的,为什么定义一个有参数的构造函数就出错。
这就是因为系统在处理的时候使用了无参数的构造函数生成了对象,然后使用这个对象对外提供功能的,无参数的构造函数能提到自动初始化的作用,所以往往我们在看一些配置文件的时候,配置文件中也是通过类名,而且这个类也必须有一个无参数的构造函数,当然除了特殊说明,使用无参数的构造函数似乎是一个管理,看一些声明式编程的语言如WPF,Flex不都是这样,JSP的Servlet似乎也是如此,这背后不知道还有什么?
反射是一个很不错的功能或者工具,它能动态的生成你想要的对象,这后面也许真的是反射作怪,我不得而知。
Web Service 我用的最多,大学的时候曾将图书馆的一个和Web Service相关的书籍《Web Services原理与研发实践》看了个遍,了解了UDDI,WSDL,SOAP,XML等,但是这个跟ashx通讯的区别是什么?在使用Web Service的时候,往往是通过代理交互,而后者好像直接是Ihttphandler,区别是否在这里,还需要确认,不到谜底出来,誓不罢休。
多了解一些细节,多了解一些区别,生活更美好!
关于数据访问的内容大家可以参阅:http://blog.youkuaiyun.com/dujingjing1230/article/details/5552351(含WCF)
http://blog.youkuaiyun.com/dujingjing1230/article/details/4191841(比较老,就当看历史了)