如何在ASP.NET环境中建立基于WML的站点
2009-11-01 14:41
441 查看
<!--
/* Font Definitions */
@font-face
{font-family:Wingdings;
panose-1:5 0 0 0 0 0 0 0 0 0;
mso-font-charset:2;
mso-generic-font-family:auto;
mso-font-pitch:variable;
mso-font-signature:0 268435456 0 0 -2147483648 0;}
@font-face
{font-family:宋体;
panose-1:2 1 6 0 3 1 1 1 1 1;
mso-font-alt:SimSun;
mso-font-charset:134;
mso-generic-font-family:auto;
mso-font-pitch:variable;
mso-font-signature:3 135135232 16 0 262145 0;}
@font-face
{font-family:"/@宋体";
panose-1:2 1 6 0 3 1 1 1 1 1;
mso-font-charset:134;
mso-generic-font-family:auto;
mso-font-pitch:variable;
mso-font-signature:3 135135232 16 0 262145 0;}
/* Style Definitions */
p.MsoNormal, li.MsoNormal, div.MsoNormal
{mso-style-parent:"";
margin:0cm;
margin-bottom:.0001pt;
text-align:justify;
text-justify:inter-ideograph;
mso-pagination:none;
font-size:10.5pt;
mso-bidi-font-size:12.0pt;
font-family:"Times New Roman";
mso-fareast-font-family:宋体;
mso-font-kerning:1.0pt;}
h1
{mso-style-next:正文;
margin-top:17.0pt;
margin-right:0cm;
margin-bottom:16.5pt;
margin-left:0cm;
text-align:justify;
text-justify:inter-ideograph;
line-height:240%;
mso-pagination:lines-together;
page-break-after:avoid;
mso-outline-level:1;
font-size:22.0pt;
font-family:"Times New Roman";
mso-font-kerning:22.0pt;}
pre
{margin:0cm;
margin-bottom:.0001pt;
mso-pagination:widow-orphan;
font-size:12.0pt;
font-family:宋体;
mso-bidi-font-family:宋体;}
/* Page Definitions */
@page
{mso-page-border-surround-header:no;
mso-page-border-surround-footer:no;}
@page Section1
{size:612.0pt 792.0pt;
margin:72.0pt 90.0pt 72.0pt 90.0pt;
mso-header-margin:36.0pt;
mso-footer-margin:36.0pt;
mso-paper-source:0;}
div.Section1
{page:Section1;}
-->
一、
现在还有很多工具和嵌入式平台(如
QuickWAP
)可以用来很便利地实现
WAP
页面,这些平台一般都因为能够提供一定的便利性(如控件、状态管理等)而流行,笔者不是不建议大家使用,而是希望我们做软件的,能够知其然亦知其所以然,还是要花些时间在
wml
和
xhtml
上(就和普通
aspx
网页,也不要满足于在设计模式下拖拽控件,而是要习惯于直接编写
html
和
css
代码一样)。
我们自己生成
WML
文档并
Response
回去,其原理相当于在普通
aspx
页面中,我们不拖拽控件,而是直接
Response.Write(“<html><head><title>hello</title></head><body>Hello
world</body></html>”);
一样,而且不需要任何其他配置。
二、服务器端生成
为了支持绝大多数的手机用户,我们只能使用最基本的
wml1.1
语法来生成文档。一个
wml
文档,就是一个合法的
xml
文档,要了解
wml
语法,
“
OReilly Learning WML & WMLScript.pdf
”这本书给出了比较详尽的讲述。这里仅就基本结构、常用的链接、图片、段落等给出一些事例,能看懂
html
代码的人应该也能看懂是什么意思。
<?xml version="1.0"?>
<!DOCTYPE wml PUBLIC
"-//WAPFORUM//DTD WML 1.1//EN"
"http://www.wapforum.org/DTD/wml_1.1.xml">
<wml>
<card title="
标题
">
<p>
段落
1</p>
<!—
图片的
width
和
height
属性一般仅用来提示浏览器在图片装载之前保留适当位置,如果这与图片实际大小不符,将可能被忽略
. -->
<p><img src="img/pic.wbmp" alt="
图片示例
"/></p>
<!—
和
html
里一样,注释
. -->
<setvar name="variable1" value="
变量
variable1
的值
"/>
<setvar name="v2" value="v2"/>
<!—
下面这个是输入框,和上面的变量
v2
都用来作为
QueryString
的一部分
-->
<input name="input1" size="18"
emptyok="true"/>
<!—
下面这个
anchor
内有个
go
,除了自身的
arg1
外,还有来自
v2
的
arg2
和来自
input1
的
arg3
,假设用户点击“搜索”时输入框内的文字为
abcd
,则页面跳转到
test.aspx?arg1=1&arg2=v2&arg3=abcd
,这样就实现了基本的百度搜索功能了
à
<anchor>
<go href="test.aspx?arg1=1" method="get">
<postfield name="arg2" value="$(v2)"/>
<postfield name="arg3" value="$(input1)"/>
</go>
搜索
</anchor>
<input name=”passwordInput1” type=”password”/>
<!—
本段落演示登录页
.
-->
<p>
<p>Username: <input name="user"
format="*x"/></p>
<p>Password: <input name="pass"
type="password"/></p>
<do
type="accept" title="Log In">
<go href="login.aspx?u=$(user:e)&p=$(pass:e)"/>
</do>
</p>
<!—
本段落演示下拉框
.
-->
<select name="airport">
<option
value="LHR">London Heathrow</option>
<option
value="LGW">London Gatwick</option>
<option
value="STN">London Stansted</option>
<option value="LCY">London
City</option>
<option
value="LTN">London Luton</option>
</select>
<!—
普通的链接
. -->
<a title="
链接
1" href="testPage2.aspx">
点击我来跳转页面
</a>
<!—
和
html
一样功能的换行
. -->
<br/>
<!—
下划线、粗体和斜体
.
-->
<p align="left">
Some text with bits in <b>
粗体
</b> and <i>
斜体
</i> and <u>
下划线
</u>.
</p>
</card>
</wml>
看懂了上面的示例,我们就有能力创建一些普通功能的页面了。由于绝大部分应用的页面都是动态的,我们需要动态地生成
wml
文档。生成
xml
文档有多种方式,可以用
System.Xml.XmlDocument
、可以用字符串拼接(
StringBuilder
)、
System.Xml.XmlTextWriter
以及使用
System.Xml.Linq.Xdocument
。基于性能和便利性结合考虑,推荐使用
XmlTextWriter
来生成页面
xml
文档。
protected void Page_Load(object sender, EventArgs e)
{
Response.ContentType =
"text/vnd.wap.wml";
MemoryStream ms = new MemoryStream();
Encoding ec = new
System.Text.UTF8Encoding(false);
StreamWriter sw = new
StreamWriter(ms, ec);
XmlTextWriter xtw =
new XmlTextWriter(sw);
//xtw.Formatting =
Formatting.Indented;
xtw.WriteStartDocument();
xtw.WriteDocType("wml", wmlUsage.s_wmlPubId,
wmlUsage.s_wmlSysId, null);
xtw.WriteStartElement("wml");
wmlUsage.WriteWmlHead(xtw);
xtw.WriteStartElement("card");
xtw.WriteAttributeString("id", "home");
xtw.WriteAttributeString("title", "
标题
");
xtw.WriteStartElement("p");
xtw.WriteStartElement("img");
xtw.WriteAttributeString("src", "images/logo.jpg");
xtw.WriteAttributeString("alt", "
网站
logo");
xtw.WriteEndElement();
xtw.WriteElementString("br", null);
//
在这里生成页面其他信息,最后要让每个
WriteStartElement
都有一个
WriteEndElement
//
与之对应
xtw.WriteEndElement();
xtw.WriteEndElement();
xtw.WriteEndDocument();
xtw.Flush();
sw.Flush();
string str = Usage.GetStreamString(ms, ec);
Response.Write(str);
sw.Close();
try
{
Response.End();
}
catch
{
}
}
三、如何解决图片显示问题
手机客户端对图片的支持良莠不齐,且很多
wap
浏览器都不支持图片的大小设置,这样就要求我们对过大的图片进行设置。
.net
Framwork
提供的
System.Drawing
命名空间内有很多对图像处理的类,使用
System.Drawing.Bitmap
就可以轻松实现生成新大小的图片。具体请查看
msdn
。
四、如何解决用户状态相关问题
很多应用都要求手机用户也能支持用户登陆、购物车等会话相关的功能。在
Internet
网页中,一般都是使用
Session
或
Profile
来实现的。手机页面,为了保证最大程度的通用性,不应该再依赖于
Session
和
Profile
。本文提供一种基于
URL
的方法。
该方法原理很简单,为每个需要存储相关登陆状态的用户生成全局唯一的
ID
,并将此
ID
以明文或加密的方式存放在返回给用户的每个
URL
中,作为
QueryString
的一部分。这样用户进行任何操作后,再次与服务器通信时,服务器都可以通过这个
ID
来识别该用户。
<a href=”test.aspx?uid=11223344”>
点击进入测试页面
</a>
在服务器端,提供一个通用的用于识别用户的对象
IdentitiVerification
,页面把当前的
Request
对象传入,就能够得到相关请求用户的相关信息(
UserInfo
)
:
public class UserInfo
{
public string ID { get; set; }
public string Name { get; set; }
public bool IsAnnonymous { get; set; }
public ShppingCart Sc { get; set; }
public string IdentityID { get; set; }
}
大部分页面的处理模式:
protected void Page_Load(object sender,
EventArgs e)
{
UserInfo ui = IdentitiVerification.GetUserInfo(Request);
if (ui.IsAnnonymous)
{
//
未登录用户的页面生成
}
else
{
//
已登录用户
}
//
在可能与服务器通信处的链接,都加上
String.Format("xxx.aspx?uid={0}", ui.IdentityID)
字样。
...
}
注
1
:
如果网页页面程序使用
Profile
来存储用户信息,那么这个
UserInfo
基本上可以与之通用。
注
2
:
用户信息与
ID
对照表可使用
ASP.NET
全局缓存来保存。
注
3
:
为了安全性考虑,生成的
ID
应该复杂且不可被猜测、没有上下文相关信息、最好也没有用户相关信息。建议使用
GUID
之类无上下文信息生成技术。同时
ID
不能太短,以免被人手工改动试出。
IdentitiVerification
对象还应该具有一些基本的智能识别攻击的技术(比如某段时间频繁调用
GetUserInfo
方法时,传入的
id
都是不存在的,这时基本可以判定有人在恶意攻击,应对
Request
对象进行日志记录并通知管理员等)。
注
4
:
为了性能考虑,
IdentitiVerification
应具有对长时间无动作的存储
ID
进行清除操作。
/* Font Definitions */
@font-face
{font-family:Wingdings;
panose-1:5 0 0 0 0 0 0 0 0 0;
mso-font-charset:2;
mso-generic-font-family:auto;
mso-font-pitch:variable;
mso-font-signature:0 268435456 0 0 -2147483648 0;}
@font-face
{font-family:宋体;
panose-1:2 1 6 0 3 1 1 1 1 1;
mso-font-alt:SimSun;
mso-font-charset:134;
mso-generic-font-family:auto;
mso-font-pitch:variable;
mso-font-signature:3 135135232 16 0 262145 0;}
@font-face
{font-family:"/@宋体";
panose-1:2 1 6 0 3 1 1 1 1 1;
mso-font-charset:134;
mso-generic-font-family:auto;
mso-font-pitch:variable;
mso-font-signature:3 135135232 16 0 262145 0;}
/* Style Definitions */
p.MsoNormal, li.MsoNormal, div.MsoNormal
{mso-style-parent:"";
margin:0cm;
margin-bottom:.0001pt;
text-align:justify;
text-justify:inter-ideograph;
mso-pagination:none;
font-size:10.5pt;
mso-bidi-font-size:12.0pt;
font-family:"Times New Roman";
mso-fareast-font-family:宋体;
mso-font-kerning:1.0pt;}
h1
{mso-style-next:正文;
margin-top:17.0pt;
margin-right:0cm;
margin-bottom:16.5pt;
margin-left:0cm;
text-align:justify;
text-justify:inter-ideograph;
line-height:240%;
mso-pagination:lines-together;
page-break-after:avoid;
mso-outline-level:1;
font-size:22.0pt;
font-family:"Times New Roman";
mso-font-kerning:22.0pt;}
pre
{margin:0cm;
margin-bottom:.0001pt;
mso-pagination:widow-orphan;
font-size:12.0pt;
font-family:宋体;
mso-bidi-font-family:宋体;}
/* Page Definitions */
@page
{mso-page-border-surround-header:no;
mso-page-border-surround-footer:no;}
@page Section1
{size:612.0pt 792.0pt;
margin:72.0pt 90.0pt 72.0pt 90.0pt;
mso-header-margin:36.0pt;
mso-footer-margin:36.0pt;
mso-paper-source:0;}
div.Section1
{page:Section1;}
-->
一、
ASP.NET
环境下实现手机浏览页面的几种方法
ASP.NET 本身就提供了对Mob ile 页面的支持,只要页面继承这个对象就可以了:“System.Web.UI.MobileControls.MobilePage ”。但是由于其目标宏大,为了在各种设备的请求下有相应的回应,需要作出各种不同的回应,因此需要很复杂的配置。而且为了应对不支持Cookie 的设备,需要在有Cookie 和无Cookie 的会话管理方式中切换,此时涉及到相对URL 时就会出现很大的问题。当前许多站点的手机页面和Internet 页面是放在同一个web 服务器下的,这无疑将影响Internet 页面的会话管理方式。
现在还有很多工具和嵌入式平台(如
QuickWAP
)可以用来很便利地实现
WAP
页面,这些平台一般都因为能够提供一定的便利性(如控件、状态管理等)而流行,笔者不是不建议大家使用,而是希望我们做软件的,能够知其然亦知其所以然,还是要花些时间在
wml
和
xhtml
上(就和普通
aspx
网页,也不要满足于在设计模式下拖拽控件,而是要习惯于直接编写
html
和
css
代码一样)。
我们自己生成
WML
文档并
Response
回去,其原理相当于在普通
aspx
页面中,我们不拖拽控件,而是直接
Response.Write(“<html><head><title>hello</title></head><body>Hello
world</body></html>”);
一样,而且不需要任何其他配置。
二、服务器端生成
XML
文档的方式来生成页面
为了支持绝大多数的手机用户,我们只能使用最基本的wml1.1
语法来生成文档。一个
wml
文档,就是一个合法的
xml
文档,要了解
wml
语法,
“
OReilly Learning WML & WMLScript.pdf
”这本书给出了比较详尽的讲述。这里仅就基本结构、常用的链接、图片、段落等给出一些事例,能看懂
html
代码的人应该也能看懂是什么意思。
<?xml version="1.0"?>
<!DOCTYPE wml PUBLIC
"-//WAPFORUM//DTD WML 1.1//EN"
"http://www.wapforum.org/DTD/wml_1.1.xml">
<wml>
<card title="
标题
">
<p>
段落
1</p>
<!—
图片的
width
和
height
属性一般仅用来提示浏览器在图片装载之前保留适当位置,如果这与图片实际大小不符,将可能被忽略
. -->
<p><img src="img/pic.wbmp" alt="
图片示例
"/></p>
<!—
和
html
里一样,注释
. -->
<setvar name="variable1" value="
变量
variable1
的值
"/>
<setvar name="v2" value="v2"/>
<!—
下面这个是输入框,和上面的变量
v2
都用来作为
QueryString
的一部分
-->
<input name="input1" size="18"
emptyok="true"/>
<!—
下面这个
anchor
内有个
go
,除了自身的
arg1
外,还有来自
v2
的
arg2
和来自
input1
的
arg3
,假设用户点击“搜索”时输入框内的文字为
abcd
,则页面跳转到
test.aspx?arg1=1&arg2=v2&arg3=abcd
,这样就实现了基本的百度搜索功能了
à
<anchor>
<go href="test.aspx?arg1=1" method="get">
<postfield name="arg2" value="$(v2)"/>
<postfield name="arg3" value="$(input1)"/>
</go>
搜索
</anchor>
<input name=”passwordInput1” type=”password”/>
<!—
本段落演示登录页
.
-->
<p>
<p>Username: <input name="user"
format="*x"/></p>
<p>Password: <input name="pass"
type="password"/></p>
<do
type="accept" title="Log In">
<go href="login.aspx?u=$(user:e)&p=$(pass:e)"/>
</do>
</p>
<!—
本段落演示下拉框
.
-->
<select name="airport">
<option
value="LHR">London Heathrow</option>
<option
value="LGW">London Gatwick</option>
<option
value="STN">London Stansted</option>
<option value="LCY">London
City</option>
<option
value="LTN">London Luton</option>
</select>
<!—
普通的链接
. -->
<a title="
链接
1" href="testPage2.aspx">
点击我来跳转页面
</a>
<!—
和
html
一样功能的换行
. -->
<br/>
<!—
下划线、粗体和斜体
.
-->
<p align="left">
Some text with bits in <b>
粗体
</b> and <i>
斜体
</i> and <u>
下划线
</u>.
</p>
</card>
</wml>
看懂了上面的示例,我们就有能力创建一些普通功能的页面了。由于绝大部分应用的页面都是动态的,我们需要动态地生成
wml
文档。生成
xml
文档有多种方式,可以用
System.Xml.XmlDocument
、可以用字符串拼接(
StringBuilder
)、
System.Xml.XmlTextWriter
以及使用
System.Xml.Linq.Xdocument
。基于性能和便利性结合考虑,推荐使用
XmlTextWriter
来生成页面
xml
文档。
protected void Page_Load(object sender, EventArgs e)
{
Response.ContentType =
"text/vnd.wap.wml";
MemoryStream ms = new MemoryStream();
Encoding ec = new
System.Text.UTF8Encoding(false);
StreamWriter sw = new
StreamWriter(ms, ec);
XmlTextWriter xtw =
new XmlTextWriter(sw);
//xtw.Formatting =
Formatting.Indented;
xtw.WriteStartDocument();
xtw.WriteDocType("wml", wmlUsage.s_wmlPubId,
wmlUsage.s_wmlSysId, null);
xtw.WriteStartElement("wml");
wmlUsage.WriteWmlHead(xtw);
xtw.WriteStartElement("card");
xtw.WriteAttributeString("id", "home");
xtw.WriteAttributeString("title", "
标题
");
xtw.WriteStartElement("p");
xtw.WriteStartElement("img");
xtw.WriteAttributeString("src", "images/logo.jpg");
xtw.WriteAttributeString("alt", "
网站
logo");
xtw.WriteEndElement();
xtw.WriteElementString("br", null);
//
在这里生成页面其他信息,最后要让每个
WriteStartElement
都有一个
WriteEndElement
//
与之对应
xtw.WriteEndElement();
xtw.WriteEndElement();
xtw.WriteEndDocument();
xtw.Flush();
sw.Flush();
string str = Usage.GetStreamString(ms, ec);
Response.Write(str);
sw.Close();
try
{
Response.End();
}
catch
{
}
}
三、如何解决图片显示问题
手机客户端对图片的支持良莠不齐,且很多wap
浏览器都不支持图片的大小设置,这样就要求我们对过大的图片进行设置。
.net
Framwork
提供的
System.Drawing
命名空间内有很多对图像处理的类,使用
System.Drawing.Bitmap
就可以轻松实现生成新大小的图片。具体请查看
msdn
。
四、如何解决用户状态相关问题
很多应用都要求手机用户也能支持用户登陆、购物车等会话相关的功能。在Internet
网页中,一般都是使用
Session
或
Profile
来实现的。手机页面,为了保证最大程度的通用性,不应该再依赖于
Session
和
Profile
。本文提供一种基于
URL
的方法。
该方法原理很简单,为每个需要存储相关登陆状态的用户生成全局唯一的
ID
,并将此
ID
以明文或加密的方式存放在返回给用户的每个
URL
中,作为
QueryString
的一部分。这样用户进行任何操作后,再次与服务器通信时,服务器都可以通过这个
ID
来识别该用户。
<a href=”test.aspx?uid=11223344”>
点击进入测试页面
</a>
在服务器端,提供一个通用的用于识别用户的对象
IdentitiVerification
,页面把当前的
Request
对象传入,就能够得到相关请求用户的相关信息(
UserInfo
)
:
public class UserInfo
{
public string ID { get; set; }
public string Name { get; set; }
public bool IsAnnonymous { get; set; }
public ShppingCart Sc { get; set; }
public string IdentityID { get; set; }
}
大部分页面的处理模式:
protected void Page_Load(object sender,
EventArgs e)
{
UserInfo ui = IdentitiVerification.GetUserInfo(Request);
if (ui.IsAnnonymous)
{
//
未登录用户的页面生成
}
else
{
//
已登录用户
}
//
在可能与服务器通信处的链接,都加上
String.Format("xxx.aspx?uid={0}", ui.IdentityID)
字样。
...
}
注
1
:
如果网页页面程序使用
Profile
来存储用户信息,那么这个
UserInfo
基本上可以与之通用。
注
2
:
用户信息与
ID
对照表可使用
ASP.NET
全局缓存来保存。
注
3
:
为了安全性考虑,生成的
ID
应该复杂且不可被猜测、没有上下文相关信息、最好也没有用户相关信息。建议使用
GUID
之类无上下文信息生成技术。同时
ID
不能太短,以免被人手工改动试出。
IdentitiVerification
对象还应该具有一些基本的智能识别攻击的技术(比如某段时间频繁调用
GetUserInfo
方法时,传入的
id
都是不存在的,这时基本可以判定有人在恶意攻击,应对
Request
对象进行日志记录并通知管理员等)。
注
4
:
为了性能考虑,
IdentitiVerification
应具有对长时间无动作的存储
ID
进行清除操作。
相关文章推荐
- 如何建立ASP.NET站点
- [转]基于AJAX的ASP.NET聊天室 & 如何建立共识
- 英语阅读推荐:基于AJAX的ASP.NET聊天室 & 如何建立共识
- 基于AJAX的ASP.NET聊天室-如何建立共识
- 如何建立ASP.NET站点
- 英语阅读推荐:基于AJAX的ASP.NET聊天室 & 如何建立共识
- ASP.NET页面如何建立静态缓存
- ASP.NET MVC是如何运行的[1]: 建立在“伪”MVC框架上的Web应用
- [PHP/.NET]如何把PHP站点用户登录会话传递到ASP.NET站点
- 技术笔记5_Asp.net:如何在vs环境下调试sqlserver中的存储过程
- 微软ASP.NET站点部署指南(5):部署到IIS上作为测试环境
- JavaScript组件之JQuery(A~Z)教程(基于Asp.net运行环境)[示例代码下载]
- 如何处理asp.net的webapi项目的测试环境与生产环境的help页面可见/不可见问题。
- JavaScript组件之JQuery(A~Z)教程(基于Asp.net运行环境)[示例代码下载]
- 如何在ASP.Net中取得环境变量的值
- 如何在Windows中配置ASP.Net环境过程解析
- [转载]ASP.NET Web 服务还是 .NET Remoting:如何选择,使用 Microsoft .NET 建立分布式应用程序
- JavaScript组件之JQuery(A~Z)教程(基于Asp.net运行环境)[示例代码下载]
- 如何建立asp.net的mvc工程
- 构建高性能ASP.NET站点 第七章 如何解决内存的问题(后篇)―托管资源优化―监常用优化措施