不使用 Web 控件的 ASP.NET(纯 GET 和 POST)
不使用 Web 控件的 ASP.NET(纯 GET 和 POST)。
引言
叫我老古董也罢,但我通常寻找解决问题的最底层、最通用的方法,这种方法不需要学习某个新框架的特性。我经常更喜欢命令行而不是 GUI,更喜欢文本编辑器而不是所见即所得的网页编辑器,我过去主要使用 C 编程。在编程方面,我最终屈服并认识到了 C# 的好处。因此,我现在将它用于桌面应用程序和 Web 开发。这自然会导致使用 ASP.NET。
ASP.NET 有些地方我喜欢,有些地方我讨厌。
我喜欢的地方
- .NET Framework
- C#
- 代码渲染块
<% %>
(用于输出 HTML,无需连接字符串文字) - 源代码更改时自动编译(因此我可以将一个 .aspx 文件放入目录中,它会立即在 Web 浏览器中显示)
我讨厌的地方
- 微软的 Web 控件(例如:
<asp:Button>
、<asp:TextBox>
和<asp:DataGrid>
),它们为我已知的 HTML 添加了新的复杂性 - 微软大部分页面生命周期状态(因为加载、渲染和卸载是我希望 API 在不受我控制的情况下管理的所有状态)
在使用 Web 控件一段时间后,最近我想制作一个简单的网页,它接收一些用户输入并产生一些动态输出,并且我想避免大部分这种复杂性。我想使用一个普通的 HTML <form>
元素(即,不使用 runat="server"
),并且我想使用 HTTP GET 和 POST 变量而不是 ASP.NET 事件回调函数,但我仍然想使用 .NET、C# 和代码渲染块。这里包含几个执行此操作的简单页面。
注意
不要误以为页面生命周期的许多状态仍在这些页面中运行。我甚至连接了 Page_Load
(而且我在现在正在编写的页面中连接了 Page_Unload
)。关键是,通过避免使用 Web 控件和避免 Page
类的任何特殊机制,我可以专注于原始 HTML/HTTP,并且页面生命周期的许多状态变得无关紧要。
我应该更多地解释一下“页面生命周期”这个术语。当我想到“页面生命周期”时,我没有想到 Page_Load
事件、页面渲染或 Page_Unload
事件。我不倾向于对术语过于吹毛求疵。这三个状态对我来说是常识。每个模块通常都会初始化自身、运行,然后关闭。
当我想到“页面生命周期”时,我想到的是那些看似多余和/或冗余的状态,例如 Page_PreInit
、Page_Init
、Page_InitComplete
、Page_PreLoad
、Page_LoadComplete
、Page_PreRender
和 Page_SaveStateComplete
。我还想到了 IsPostBack
标志、视图状态和控件事件的设置。我把所有这些我认为使 ASP.NET 难看的东西放在一起,并将它们视为“页面生命周期”。我在这里尝试做的是尽可能避免这些难看的部分,并保留那些我认为很好理解的部分。
代码
在 GET 示例中,用户输入成为 URL 的一部分,并且可以通过隐藏表单字段持久化。关键的 .NET 机制是用于输入的 Request.QueryString
和用于输出的 Response.Write
。
POST 示例与 GET 几乎完全相同,只有细微的差别。当然,URL 不会存储输入。它不使用 Request.QueryString
,而是使用 Request.Form
来访问它。最后,表单的 method
属性不是 get
,而是 post
。输入仍然可以通过隐藏表单字段(或 Cookie,但我没有使用这种方法)持久化。
HTTP GET
<%@ Page Language="C#" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xml:lang="en" lang="en">
<head>
<title>HTTP GET test</title>
<meta http-equiv="content-type" content="text/html; charset=utf-8"/>
<script runat="server" language="C#">
private string prev_first_name;
private string first_name;
private string prev_last_name;
private string last_name;
private void Page_Load()
{
prev_first_name = Request.QueryString["prev_first_name"];
first_name = Request.QueryString["first_name"];
prev_last_name = Request.QueryString["prev_last_name"];
last_name = Request.QueryString["last_name"];
}
private void WriteDisplay()
{
Response.Write(
Environment.NewLine +
"Previous first name entered: \"" + prev_first_name +
"\"<br/>"
);
Response.Write(
Environment.NewLine +
"First name entered: \"" +
first_name + "\"<br/>"
);
Response.Write(
Environment.NewLine +
"Previous last name entered: \"" +
prev_last_name + "\"<br/>"
);
Response.Write(
Environment.NewLine +
"Last name entered: \"" + last_name +
"\"<br/>"
);
}
private void WritePersistentVars()
{
WriteHiddenFormVar("prev_first_name", first_name);
WriteHiddenFormVar("prev_last_name", last_name);
}
private void WriteHiddenFormVar(string name, string value)
{
if(value != null)
{
Response.Write(
Environment.NewLine +
"<input " + "name=\"" + name + "\"" +
" type=\"hidden\"" +
" value=\"" + value + "\"" +
"/>"
);
}
}
</script>
</head>
<body>
<p><% WriteDisplay(); %></p>
<form action="<% Response.Write(Request.Url.AbsolutePath); %>"
method="get">
<br/>
First name: <input name="first_name"/><br/>
Last name: <input name="last_name"/><br/>
<% WritePersistentVars(); %>
<p><input type="submit" value="Enter"/></p>
</form>
</body>
</html>
HTTP POST
<%@ Page Language="C#" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xml:lang="en" lang="en">
<head>
<title>HTTP POST test</title>
<meta http-equiv="content-type" content="text/html; charset=utf-8"/>
<script runat="server" language="C#">
private string prev_first_name;
private string first_name;
private string prev_last_name;
private string last_name;
private void Page_Load()
{
prev_first_name = Request.Form["prev_first_name"];
first_name = Request.Form["first_name"];
prev_last_name = Request.Form["prev_last_name"];
last_name = Request.Form["last_name"];
}
private void WriteDisplay()
{
Response.Write(
Environment.NewLine +
"Previous first name entered: \"" + prev_first_name +
"\"<br/>"
);
Response.Write(
Environment.NewLine +
"First name entered: \"" + first_name +
"\"<br/>"
);
Response.Write(
Environment.NewLine +
"Previous last name entered: \"" +
prev_last_name + "\"<br/>"
);
Response.Write(
Environment.NewLine +
"Last name entered: \"" + last_name +
"\"<br/>"
);
}
private void WritePersistentVars()
{
WriteHiddenFormVar("prev_first_name", first_name);
WriteHiddenFormVar("prev_last_name", last_name);
}
private void WriteHiddenFormVar(string name, string value)
{
if(value != null)
{
Response.Write(
Environment.NewLine +
"<input " + "name=\"" + name + "\"" +
" type=\"hidden\"" +
" value=\"" + value + "\"" +
"/>"
);
}
}
</script>
</head>
<body>
<p><% WriteDisplay(); %></p>
<form action="<% Response.Write(Request.Url.AbsolutePath); %>"
method="post">
<br/>
First name: <input name="first_name"/><br/>
Last name: <input name="last_name"/><br/>
<% WritePersistentVars(); %>
<p><input type="submit" value="Enter"/></p>
</form>
</body>
</html>
使用代码
要使用此代码,请安装 Windows 安装 CD 中附带的 IIS(Internet Information Server)Web 服务器,或访问运行它的服务器,安装 .NET Framework,使 IIS 和 .NET Framework 协同工作(这可能需要进行 Web 搜索),将 raw_get.aspx 或 raw_post.aspx 放入服务器的一个公共访问目录中,然后在 Web 浏览器中使用诸如 https:///raw_get.aspx 或 https:///raw_post.aspx 之类的 URL 查看它们。
历史
- 修订版 0:初始版本
- 修订版 1:将脚本与页面渲染分开
- 修订版 2:将脚本移动到 head 中
- 修订版 3:尝试阐明“不使用”和“避免”的含义,尤其是在页面生命周期方面