一个简单的WML文档
我们将会看到一个简单的WML文档,你得懂点最基本的XML。
以下是引用片段:
<?xml version="1.0"?>
<!DOCTYPE WML PUBLIC "-//WAPFORUM//DTD WML 1.1//EN" "http://www.wapforum.org/DTD/wml_1.1.xml">
<wml>
<!-- root element -->
<card id="card1" title="Example 1">
<p> <!-- 卡片只能支持p和do块 -->
<do type="accept" label="go to card 2">
<go href="#card2"/>
</do>
This is the first card.
</p>
</card>
<card id="card2" title="Example 1">
<p>
This is the second card.
</p>
</card>
</wml>
一旦手机接收了这个块,它就会显示第一个卡片,当你按下左边的软键时,就会看到第二个卡片。
第四节:另一种预订你电影票的方法
在上一节中,我讲解了最基本的WAP和WML的概念,这一节我们就来看看ASP和WAP是如何结合的.
现在在奥斯陆,电影院提供了一种基于电话系统的来销售门票,这个系统是很复杂的,还必须给用户一些说明才能指导用户买票,而且用户还必须在报纸上找到某种电影的代码,这个很烦,我们来介绍另一种方法。
这里这将给你展示一个简单的让手机用户订票的WAP应用:一个肯定让人叫好的服务。用户不必记住那些烦人的代码,他们能够直接从菜单中选取电影和电影院,并且用户也不需要认证。在这个例子中用户被要求在电影开始前40分钟交费,但是在真正的生活中,用户同样可以通过手机来结帐.
此应用程序想像的条件是一个电影能够在同一时间在多个电影院上映,一个电影院不同的时间上演不同的电影。
这里我没有过多的考虑错误处理的问题,因为这不是本章节的重点,你喜欢你可以自己加上.
为了简单,我使用了Access 97来做为数据库,当然真正的系统不会用它了,其它的数据库如SQL Server,也不必改动多少代码.
数据库图表
数据库图表
.Movie 和Theater表是显然需要的。Show表用于追踪现在还有多少空位可以出售。
怎样调试这个程序
为了访问这个WAP服务,你需要一个WAP仿真器,这个程序主要是在Nokia Toolkit 1.2上调试,详细情况请查看上一章节。
选择电影
在list表中选择一个电影:
这里是代码:
以下是引用片段:
< !--#include file=\"conn.asp\" -- >< % 'send the right MIME type
Response.ContentType = \"text/vnd.wap.wml\"
第一件事就是声明wml,仿真器如何不在正确的地方声明XML,它是不会接受WML的尽管Nokia 7110可以忽略这一点,但是不能保证其它的手机也行,所以你不得不做这事。同样你也得设置好MIME类型。
< ?xml version=\"1.0\"? >
< !DOCTYPE wml PUBLIC \"-//WAPFORUM//DTD WML 1.1//EN\" \"http://www.wapforum.org/DTD/wml_1.1.xml\" >
< wml >
在进入下一个card以前会有一个闪烁的屏幕来显示一个图片WBMP一种新的格式。这个事件是由timer属性决定的,这里我们设置的时间为5秒.ontimer事件引发后将带你去另一个card.(wmbp的photoshop插件可以从网上免费下载).
< card id=\"splash\" ontimer=\"#card1\" title=\"Welcome to\" > < timer value=\"50\"/ >
< p align=\"center\" >
< br / >
< img src=\"pix/logo.wbmp\" alt=\"WAP movies\"/ >
< /p >
< /card >
< card id=\"card1\" title=\"choose a film\" >
< %
sqlQuery = \"SELECT [Movie_ID], [title] FROM Movie\"
set rsMovies = conn.Execute(SQLquery)
:
% >
< p >
< select name='movie' >
< %
Do while not rsMovies.eof
response.write(\"< option value='\" & rsMovies(\"Movie_ID\") & \"' >\" & rsMovies(\"title\") & \"< /option >\" & vbcrlf)
rsMovies.MoveNext
loop % >
< /select >
这一部分是本文的焦点。从数据库中读出需要的数据显示出来,作为一个asp程序员,这个没有什么特别的,但是就是这个简单的程序现在被用于一种全新的服务器就显得不一样了。这也使得我更加认为在基于WML的商业站的网络编程asp更胜于Java servlet.
以下是引用片段:
< small > < anchor title=\"next!\" >Next
< go href=\"step2.asp\" method=\"get\" >
< postfield name=\"movie\" value=\"$(movie)\" / >
< /go >
< /anchor >
< /small >
< /p >
表单的提交也可以通过软开关函数(do 和 anchor)来完成。在这里,我是通过简单的内嵌链接来完成的,因为我觉得这样能够使用户感觉直观和友好。Postfields大至和HTML中的hidden差不多,但是wml的变量不像html中的那样需要在javascript中传送,它可以直接写在wml中,这一点上一节已经讲解了.在这里的传递的方法是get,post方法在WAP的规范也是被支持的,仿真器也能识别它,但是很不幸,在Nokia 7110中,这个post不被支持,所以你没得选择.
选择电影院和上映时间
这部分代码让用户来选择看什么时间的电影,所有的记录根据前一页所选的电影来决定。在这里来选择电影院和上映时间.
以下是引用片段:
movie_id = Request(\"movie\")
sqlQuery = \"SELECT title FROM movie WHERE Movie_id = \" & movie_id
set rsMovie = conn.Execute(sqlQuery)
movie_title = rsMovie(\"title\")
:
sqlQuery = \"SELECT [name], [time], [show_id] FROM Show, Theater \" &_
\"WHERE show.movie_id = \" & movie_id &_
\" AND theater.theater_id = show.theater_id\"
set rsShows = conn.Execute(SQLquery)
如果你仔细研究了这个代码,你就会想用Session来保存电影信息,再在这页进行查询更简单。同样很不幸,Session是需要cookies的支持,虽说在WAP规范中也是被支持的,但是在Nokia 7110中也是不被支持,这就是说现在我们还不能把session用在WAP服务中。
下面有一些有趣的事情:
以下是引用片段:
< select name='show' >
< %
Do while not rsShows.eof
response.write(\"< option value='\" & rsShows(\"show_id\") & \"' >\" & Left(rsShows(\"name\"),cutter) & \" (\" & rsShows(\"time\") & \")\" & \"< /option >\" &vbcrlf)
rsShows.MoveNext
loop % >
< /select >
如果你对cutter变量感到疑惑,那么就有一些事让你哭笑不得
以下是引用片段:
Dim cutter
if InStr(Request.ServerVariables(\"HTTP_USER_AGENT\"), \"Nokia7110\") then
cutter = 12
else
cutter = 7
end if
这段代码根据不同的设备来显示选项。我们有充足的理由的这样做,Nokia Toolit 1.2仿真器喜欢把砍掉我的的选项到只有几个字符,而我们要显示电影名字和上映时间,所以我们就不得不减少电影名字的字符。在真的手机中不会出现这种问题,所以我们就必须先判断设备的类型.
一旦我有机会(飞刀我很穷,没有钱,这是仅仅是遥远的梦想.......)在真的Nokia 7110上测试我的代码,我们会立即感到我们有比我们想像更大的屏幕。实际上,有些电影院的名字很古怪,而且这些长名字会占用很大屏幕空间,我们没有必要浪费这些显示空间,尽量把这些名字简化。
下一步就是让用户选择需要的票数.这部分的代码很像其它的部分。我将从数据库中查询相同的数据,因为Session不能在真正的WAP手机中使用,所以我必须对有些内容进行确认,看看是否还有座位出售.
以下是引用片段:
SQLquery = \"SELECT * FROM show WHERE Show_id = \" & show_id
set rsShow = conn.Execute(SQLquery)
:
seats = rsShow(\"free_seats\")
:
if seats = 0 then
Response.write(\"Sorry, no more seats\")
rsShow.close
set rsShow = nothing
Response.write(\"< /p >< /card >< /wml >\")
Response.end
else
if seats > 6 then 'book up to 6 tickets or max available
max_seats=6
else
max_seats = seats
end if
end if
% >
< %=movie_title% > at < % =theater_name% >
< select name='ticket' >
< %
dim i
i = 1
Do while i < = max_seats
response.write(\"< option value='\" & i & \"' >\" & i & \" ticket(s)\" & \"< /option >\" &vbcrlf)
i = i + 1
loop % >
< /select >
储存票数
现在我们已经有了所有需要的数据了,我们得把它们保存起来:
以下是引用片段:
tickets = Request(\"ticket\")
:
free_seats = rsShow(\"free_seats\")
:
free_seats = free_seats - tickets
:
SQLUpdate = \"UPDATE Show \" &_
\"SET Show.free_seats=\" & free_seats & \" \" &_
\" WHERE Show_ID=\" & show_id
conn.Execute(SQLupdate)
SQLquery = \"SELECT max([Booking_ID]) as bookingnumber FROM booking\"
Set rsBooking = conn.execute(SQLquery)
maxbookid = rsBooking(\"bookingnumber\") + 1
SQLinsert = \"INSERT INTO Booking ( show_id, booked_seats ) \" & _
\"VALUES ('\" & show_id & \"', '\" & tickets & \"')\"
conn.Execute(SQLinsert) % >
You have booked < %=tickets% > ticket(s) for < %=movie_title% >< br / >
The show will take place at < %=theater_name% > (< %=time% >)
< br / >
Your reference number is < %=maxbookid% >
下面是显示:
Figure 4:完成交易.
交易已经完成了,电影院可以坐着电影院门口收钱了.
结论
WAP现在才刚刚走出它的第一步,然而它是最近几年内最有革命性的IT发展之一。在这篇文章中我介绍了怎样用asp写WAP应用程序,并对你们提出了一些警告,希望对你们以后的发展有用。多媒体技术依然不能太多的用于WAP,但是它的可移动性却是重要的,也为商家提供了不少的商机。