------------------------------ Windows Phone 7手機開發、.Net培訓、期待與您交流! ----------------------
127.0.0.7是迴環地址(LookBack),就是表示訪問本機,LocalHost是它的別名。是無法在外部訪問的。查看IP地址:ipconfig
Get和Post的區別:
設定Form的Method屬性指定表單提交方式,Get(默認值)是通過URL傳遞表單值,Post傳遞的表單值是隱藏到Http報文件中, URL中看不到。
Get和Post的區別:Get是通過URL傳遞表單值,Post通過URL看不到表單域的值;Get傳遞的數據量是有限的,如果要傳遞大量數據不能用Get,比如Type="file"上傳文章、Type="password"傳遞密碼或者<textarea>發表大段文章,Post則沒有這個限制;Post會有瀏覽器提示重新提交表單的問題,Get則沒有。對於Post的表單位重新敲地址欄再刷新就不會提示重新提交了中,因爲重新敲地址就沒有偷偷提交的數據了。
Get方式URL數據格式,服務器文件名後跟着“?”,由於客戶端可能向服務器端提交多個鍵值對,鍵值對之間用“&”進行分割,如果URL中有漢字、特殊符號等,則需要對URL進行編碼。
表單域只有設定了Name的纔會被提交給服務器(用Get方式看的清楚)。如果給Submit按鈕設定Name,那以按鈕的Value也會被提交給服務器。
例:
<head>
<title></title>
</head>
<body>
<form action ="Hello.ashx"method="post">
<input type ="hidden"name="ispostback" value ="true" />
用戶名:<input type ="text" name="UserName"value="@value" />
<input type ="submit" value ="提交" />
@msg
</form>
</body>
</html>
<%@ WebHandler Language="C#"Class="Hello" %>
using System;
using System.Web;
public class Hello : IHttpHandler {
public void ProcessRequest (HttpContext context) {
context.Response.ContentType = "text/html";
//string username = context.Request["UserName"];
//if (string.IsNullOrEmpty(username))
//{
// context.Response.Write("直接進入");
//}
//else
//{
// context.Response.Write("提交進入");
//}
string username = context.Request["UserName"];
string msg="";
string ispostback = context.Request["ispostback"];
if (ispostback == "true")
{
context.Response.Write("提交進入");
msg = username + "你好!";
}
else
{
context.Response.Write("直接進入");
username = "";
msg = "";
}
string fullpath = context.Server.MapPath("Hello.htm");//得到文件的全路徑
string content = System.IO.File.ReadAllText(fullpath);//讀取文件
content=content.Replace("@value",username);
content = content.Replace("@msg", msg);
context.Response.Write(content);
}
publicbool IsReusable {
get {
return false;
}
}
}
ViewState初探(重點,常考)
Label版本的值存到了ViewState中,TextBox版本的不用存,因爲TextBox就是Input,自己就會提交給服務器,不需要隱藏字段。
用Asp.net重寫Div文本自增(還要同時遞增Label的寬度,注意Width的單位是Unit類型,不是簡單的Int)
Label1.Text=(Convert.ToInt32(Label1.Text)+1).ToString)_;
Label1.Width=new Unit(Label1.Width.Value+10);
查看生成的源代碼,ASP.Net將所有隱藏內容統一放到了名字爲_VIEWSTATE的隱藏字段中,使用序列化算法將所有隱藏內容放到一個字符串中。點擊幾次在使用ViewStateDecode這個工具查看ViewState內容,發現了確實將這些改變的內容放到了ViewState中。存儲非表單域、非Value值的容器。
禁用ViewState的方法:禁用單個控件的ViewState設定enableviewstate=false,禁用ViewState以後TextBox版本不受影響,Div版本受影響,因爲Input的Value不依靠ViewState。禁用整個頁面的在Aspx的Page指令加上 EnableViewState="false" 。內網系統、互聯網的後臺可以盡情的用ViewState。
回答ViewState原理的時候,說Input版本(TextBox)自增和Div版本(Label)的不同。
無狀態Http
Http協議是無狀態的,不會記得和網頁“發生了什麼”。服務器不記得上次給了瀏覽器什麼,瀏覽器需要記信這些值(Input就是記到Value中,對於其他的就要放到隱藏字段中,比如ViewState),下次再提交服務器的時候(請在我的寬度基礎上增加了12)就要把上次的值提交給服務器,讓它想起來。如果要知道上一次的狀態,一個方法是對瀏覽器響應結束之前將狀態信息保存到頁面表單中,下次頁面再向服務器發出請求的時候帶上這些狀態信息,這樣服務器就能根據這些狀態信息還原上次的狀態了,類似於去看病的病歷本。
狀態信息保存在隱藏字段中的缺點:加大網站的流量,降低訪問速度,機密數據放到表單中會有數據欺騙等安全性問題。
Cookie
表單是和頁面相關的,只有瀏覽器提交了這些數據服務器端才能得到。而有時候希望在服務器端任意的地方存取一些和訪問者相關的信息,這時候就不方便將這些信息保存到表單中了,因爲如果那樣的話必須隨時注意在所有頁面表單中都保存這些信息。Cookie是和站點相關的,並且每次向服務請求的時候除了發送表單參數外,還會將和站點相關的所有Cookie都提交給服務器,是強制性的。Cookie也是保存在瀏覽器端的,而且瀏覽器會在每次請求的時候都會把這個站點的相關的Cookie提交到服務器,並且將服務器端返回的Cookie更新回數據庫,因此可以將信息保存在Cookie中,然後在服務器端讀取,修改。服務器返回數據除了普通的Html數據外,還會返回修改的Cookie,瀏覽器把拿到的Cookie值更新本地瀏覽器的Cookie就可以。
互聯網優化案例:圖片服務器和主站域名不一樣,降低Cookie流量的傳輸。
案例:一個頁面設置Cookie,一個頁面讀取Cookie
設置值的頁面:Response.SetCookie(new HttpCookie("color",TextBox1.Text));//在客戶端也能通過$.cookie取到
讀取值的頁面: Label1.Text = Request.Cookies["color"].Value;
Cookie的缺點和表單一樣,而且還不能存儲過多信息。
Session原理
Private int i = 0;////每次請求來了都會New一個新的實現了IHttpHandler接口的類“變量”的實例進行處理,用完了就GC掉,所以不會保持上次的值。(常考)
Cookie不能存儲過多信息。如果想保存大量的數據,可以保存一個Guid到Cookie中,然後在服務器中建立一個以Guid爲Key,複雜數據爲Value全局Dictionary。Static字段對於不同用戶也只有一份,因此用Static實現多用戶去共享數據。
ASP.Net已經內置了Session機制,把上面的例子用ASP.NetSession重寫。不要放太多的對象到Session,Session會有超時銷燬機制。服務器不可能知道瀏覽器是否開着,Cookie和Session都是爲了保存和當前客戶端相關的數據,不同的是Cookie是存在客戶端,用戶可以改變。而Session是存在服務器端,客戶修改無效。
Session不能放的是object型數據,可任意設置,注意在使用時要做類型轉換,不能放太大的數據。
可以看到Session機制並不是Http協議規定的,是ASP.net實現的,現在PHP、JSP等大部分服務端技術都實現了Session,原理都差不多。
建一個名爲SessionMgr的類:
public class SessionMgr
{
private static IDictionary<string,IDictionary<string,object>>data =new Dictionary<string,IDictionary<string,object>>();
publicstatic IDictionary<string,object> GetSession(string sessionId)
{
if (data.ContainsKey(sessionId))
{
return data[sessionId];
}
else
{
IDictionary<string, object> session = new Dictionary<string,object>();
data[sessionId] = session;
return session;
}
}
}
在變量.aspx.cs中使用Session。
public partial class Cookie_變量 :System.Web.UI.Page
{
private int i = 0;//每次請求來了都會New一個新的實現了IHttpHandler接口的類“變量”的實例進行處理,用完了就GC掉,所以不會保持上次的值。(常考)
private static int j = 0;//所有訪問者都訪問同一個J的實例。
protected void Page_Load(object sender, EventArgs e)
{
if (Request.Cookies["MySessionId"] == null)
{
string sessionId = Guid.NewGuid().ToString();
Response.SetCookie(new HttpCookie("MySessionId",sessionId));
}
}
protected void Button1_Click(object sender, EventArgs e)
{
i++;
Label1.Text = i.ToString();
j++;
Label2.Text = j.ToString();
}
protected void Button3_Click(object sender, EventArgs e)
{
string sessionId = Request.Cookies["MySessionId"].Value;
IDictionary<string, object> session =SessionMgr.GetSession(sessionId);
session["服務器端的數據"] = DateTime.Now.ToString();
session["服務器端的另一個數據"] = "我今年24歲了。語速快,激情高,滔滔不絕!";
}
protected void Button2_Click(object sender, EventArgs e)
{
string sessionId = Request.Cookies["MySessionId"].Value;
IDictionary<string, object> session =SessionMgr.GetSession(sessionId);
Button2.Text = Convert.ToString(session["服務器端的數據"])+ session["服務器端的另一個數據"];
}
}
案例:用Session實現驗證碼。注:HttpHandler要能夠操作Session,要實現IRequiresSessionState接口。
以下代碼爲:驗證碼.ashx
<%@ WebHandler Language="C#"Class="驗證碼" %>
using System;
using System.Web;
public class 驗證碼 :IHttpHandler,System.Web.SessionState.IRequiresSessionState{
public void ProcessRequest(HttpContext context)
{
context.Response.ContentType = "image/JPEG";
using (System.Drawing.Bitmap bitmap = new System.Drawing.Bitmap(100,50))
{
using (System.Drawing.Graphics g = System.Drawing.Graphics.FromImage(bitmap))
{
//g.DrawString("computer", new System.Drawing.Font("宋體",20), System.Drawing.Brushes.Blue, new System.Drawing.PointF(0, 0));
//g.DrawEllipse(System.Drawing.Pens.Red, new System.Drawing.Rectangle(10,10, 10, 10));
//System.Drawing.Pen pen =(System.Drawing.Pen)System.Drawing.Pens.Green.Clone();
//pen.Width = 3;
//g.DrawEllipse(pen, newSystem.Drawing.Rectangle(20, 20, 20, 20));
//bitmap.Save(context.Response.OutputStream,System.Drawing.Imaging.ImageFormat.Jpeg);
Random rand = new Random();
int code = rand.Next();
string strCode =code.ToString();
HttpContext.Current.Session["Code"]= strCode;//需在最上面加上System.Web.SessionState.IRequiresSessionState
g.DrawString(strCode, newSystem.Drawing.Font("宋體", 10), System.Drawing.Brushes.Red, newSystem.Drawing.PointF(0, 0));
bitmap.Save(context.Response.OutputStream,System.Drawing.Imaging.ImageFormat.Jpeg);
}
}
}
public bool IsReusable {
get {
return false;
}
}
}
以下代碼爲:驗證碼.aspx(源)
<%@ Page Language="C#"AutoEventWireup="true" CodeFile="驗證碼.aspx.cs"Inherits="驗證碼" %>
<!DOCTYPE html PUBLIC "-//W3C//DTDXHTML 1.0 Transitional//EN""http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<htmlxmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
</head>
<body>
<form id="form1" runat="server">
<div>
<img src ="驗證碼.ashx" />
<asp:TextBox ID="TextBox1"runat="server"></asp:TextBox>
<asp:Button ID="Button1" runat="server" οnclick="Button1_Click"Text="Button" />
</div>
</form>
</body>
</html>
以下代碼爲:驗證碼.aspx.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
public partial class 驗證碼 :System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
}
protected void Button1_Click(object sender, EventArgs e)
{
string right = Convert.ToString(Session["Code"]);
if (right == TextBox1.Text)
{
Response.Write("驗證碼正確");
}
else
{
Response.Write("驗證碼錯誤");
}
}
}
Session的目的是爲了控制一下內存和當前用戶相關的一些數據,但是它存的地方不一樣,Cookie存在客戶端,Session存在服務器端。以數值自增爲例,用Cookie設置自增用戶修改後估在其基礎上再自增,而用Session設置自增則數值不會隨着用戶的修改而改變。
機器自動註冊
建一個WindowsFormAppcation應用程序,彈出一個Form窗體,在Form1窗體中放一個WebBrowser控件,一個Button,雙擊Button編寫如下代碼:
webBrowser1.Document.GetElementById("TextBox1").SetAttribute("Value","地地寺地地地地");
webBrowser1.Document.GetElementById("TextBox2").SetAttribute("Value","woyaozhuuche ");
webBrowser1.Document.GetElementById("Button1").InvokeMember("Click");
用驗證碼防機器人註冊。
Http協議簡介:
Web開發是和Http協議打交道的,必須瞭解Http協議。Http協議版本:Http/0.9、 Http/1.0 、 Http/1.1,現在主流的是Http/1.1版本。
Http協議分析工具:
1、DebugBar,Http(S)標籤內容。免費的,只能分析當前瀏覽器中的內容。
2、Httpwatch,收費的,只能分析當前瀏覽中的內容,內容更詳細,推薦使用。
3、HttpAnalyzer,收費的,能分析計算機上所有的Http請求數據。比如QQ,迅雷等。
Http協議的幾個概念:
1,連接(Connection):瀏覽器和服務器之間傳輸數據的通道,一般請求完就關閉,不會一直保持連接。
2,請求(Requst):瀏覽器向服務器發送的“我要……”的消息,包含請求的類型,請求的數據,瀏覽器的信息(語言、瀏覽器版本等)。
3,響應(Response):服務器對瀏覽器請求的返回的數據,包含是否成功,錯誤碼等。
Http是無狀態的,不會記得上次的請求,所以哪怕是同一個頁面中的JS,CSS,JPG也都要重複提交Accept-language、Accept-Encoding、Cookie等。
Http請求報文:
用httpwatch 查看訪問一個網站(用DiscuzNT測試環境)的響應情況。敲入一個網址後,瀏覽器向服務器發出請求。注意:頁面中的圖片、JS,CSS在單獨的請求中。
GET/HTTP/1.1表示向服務器用GET方式請求首頁,使用HTTP/1.1協議。
Accept.Encoding gzip,deflate表示瀏覽器支持gzip,deflate兩種壓縮方法。
Accept-language zh-cn表示瀏覽器支持的語言,很多進入後自動就是中文界面的國際網站就是通過讀取這個頭的值實現的。
Connection Keep-Alive,則TCP連接在發送後將仍然保持打開狀態,於是瀏覽器可以斷續通過相同的連接發送請求。保持續連接節省了爲每個請求建立新連接所需的時間,還節約網絡帶寬。
Cookie是瀏覽器向服務器發送和當前網站關聯的Cookie,這樣在服務器也能讀取瀏覽器的Cookie了。
User-Agent爲瀏覽器的版本信息,通過這個信息可以讀取瀏覽器是IE還是FireFox,支持的插件,Net版本等。
Http響應碼
瀏覽器向服務器發出請求,服務器處理可騍是成功,可能是失敗,可能沒有權限訪問等原因,服務器會通過響應碼來告訴瀏覽器處理結果。
"200":OK
"301":Moved Permanently永久轉移
"302":Found暫時轉移
"307":Temporary Redirect
"400":Bad Requst錯誤請求
"401":Unalthorized未認證
"403":Forbidden禁止
"404":Not Found未找到
"500":Internal Server Error服務器內部錯誤,比如在程序中拋異常
"503":Service Unavailable。一般是訪問人數過多。
200段是成功,300段需要對請示做進一步的處理。400段表示客戶端請求錯誤。500段是服務器端的錯誤。
服務器返回的報文:
Sever:Cassini/3.5.0.5表示服務器的類型。
Content-Type:text/html;Charset=utf-8表示返回數據的類型。
服務器通過Content-Type告訴客戶端響應的數據的類型,這樣瀏覽器就根據返回數據的類型來進得不同的處理,如果是圖片類型就顯示,如果是文本類型就直接顯示內容,如果用Html類型就用瀏覽器顯示內容,如果是下載類型就彈出下載工具等。
常用Content-Type:Text/HTML、image/GIF,image/jpge,text/plain,text/javascript,application/x-excel,application/octet-stream(二進制文件)
Content-Length:19944表示後續數據消息體的長度,報文頭只是描述,返回的具體數據(比如HTML文本,圖片數據等)在兩個回車之後的內容中。
Http其它
Http是無狀態的,不會記得“上個請求”,所以哪怕是同一個頁面中的js,css,jpg也都要重複提交Accept-Language,Accept-Encoding,Cookie等等。
頁面中如果有圖片,css,js等外部文件的話,圖片,CSS,JS都在單獨的請求中,也就是並不是頁面的所有內容都在一個請求中完成,而是每個資源一個請求。
一般情況下,只有瀏覽器請求服務器端,服務器端纔會給瀏覽器響應數據,不會主動向瀏覽器推送數據,這樣是安全考慮,也是提高服務器的性能考慮。如果要服務器向瀏覽器推送數據,則需要使用SeverPush等額外的技術。
Http是“請求——響應”的工作方式,因此頁面會不斷刷新,如果不希望頁面刷新則要使用Ajax等技術。
斷點續傳的原理,多線程下載基於斷點續傳。
請求響應模型的例子:
按鈕實現表格行刪除效果;使用超鏈接進行刪除。代碼如下:
HTML頁代碼
<body>
<form action="delete.ashx" id="form1"method ="post">
<input type ="hidden" name="Name" id ="Name" />
<table>
<tr><td>姓名</td><td>性別</td><td>年齡</td><td>操作</td></tr>
<tr><td>黃忠</td><td>男</td><td>24</td><td><ahref ="delete.ashx?Name=黃忠" >刪除</a></td></tr>
<tr><td>黃燕</td><td>女</td><td>22</td><td><inputtype ="button" value ="刪除"οnclick="document.getElementById('Name').value='黃燕';document.getElementById('form1').submit();"/></td></tr>
<tr><td>黃興</td><td>男</td><td>26</td><td>刪除</td></tr>
<tr><td>黃江苗</td><td>男</td><td>6</td><td><ahref ="delete.ashx?Name=黃江苗">刪除</a></td></tr>
</table>
</form>
</body>
一般處理程代碼.ashx
public class delete : IHttpHandler {
public void ProcessRequest (HttpContext context) {
context.Response.ContentType = "text/html";
string name = context.Request["Name"];
context.Response.Write(name+"已刪除");
}
public bool IsReusable {
get {
return false;
}
}
}
這就是Asp.net中數據綁定控件中行按鈕和行超鏈拉實現方式的不同,ListView中Button、HyperLink兩種刪除方式。按鈕方式是將行的ID通過表單提交到服務器,行超鏈拉的方式是通過超鏈接的URL通過Get的方式提交給處理頁面,超鏈接的方式由於沒有提交所有的表單信息,因此很多服務器端控件的高級用法用不了。
用aspx重寫,超鏈接的因爲沒有向服務器提交ViewState等隱藏字段,所以處理時IsPostBack爲False,而按鈕的則是提交了表單,所以IsPostBack爲Ture。代碼如下:
用Web窗體重寫delete.aspx
body>
<form id="form1" runat="server">
<asp:TextBox ID="TextBox1"runat="server"></asp:TextBox>
<input type ="hidden"name="Name"id="Name" />
<div>
<table>
<tr><td>姓名</td><td>性別</td><td>年齡</td><td>操作</td></tr>
<tr><td>黃忠</td><td>男</td><td>24</td><td><ahref ="用Web窗體重寫delete.aspx?Name=黃忠" >刪除</a></td></tr>
<tr><td>黃燕</td><td>女</td><td>22</td><td><inputtype ="button" value ="刪除"οnclick="document.getElementById('Name').value='黃燕';document.getElementById('form1').submit();"/></td></tr>
<tr><td>黃興</td><td>男</td><td>26</td><td>刪除</td></tr>
<tr><td>黃江苗</td><td>男</td><td>6</td><td><ahref ="用Web窗體重寫delete.aspx?Name=黃江苗">刪除</a></td></tr>
</table>
</div>
</form>
</body>
用Web窗體重寫delete.aspx.cs
public partial class 請求響應_用Web窗體重寫delete :System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
if (IsPostBack)//這行不要,則超鏈接均works,button NO works
{
string name = Request["Name"];
Response.Write(name + "已刪除");
}
}
}
Web開發的一些基本原則:
最小權限原則。只允許用戶做……而不是“不允許用戶做什麼……
瀏覽器查看的是服務器端代碼的執行輸出的文,除非服務器有漏洞,否則瀏覽者無法查看服務器端的aspx、cs代碼,目標另存爲也是保存的aspx的執行結果,而看不到aspx的源代碼。js、html是被輸出到瀏覽器上執行的,因此無法禁止瀏覽者查看js,html。
能在瀏覽器端完成的事情,就不要到服務器端去做。
客戶端是不可信的。
C#代碼是運行在服務器端的,JS代碼是運行在瀏覽器客戶端的。
按鈕確認提交的實現在Button的OnClientClick中寫<input type="submit" name="Button1"value="delete" οnclick="return confirm("確定要刪除嗎?");"id="Button1" />代碼是運行在瀏覽器端的,和服務器端沒有關係。
在服務器端“彈出消息窗口”
Response.Write("<script type='text/javascript'>alert('你點了我');</script>");並不是真的在服務器端運行的,只是生成了Javascript代碼到瀏覽器端,瀏覽器會在解析文檔時運行alert,不推薦用這種寫法,讀懂即可,推薦用後面講的RegisterClientStartupScript。只是渲染到瀏覽器端,所以並不會行到對話框關閉服務器端的代碼纔會執行下去(在Response.Write("<script type ='text/javascript'>alert('你點了我');</script>");後設置斷點)
對於服務器端的代碼來說,生成一堆HTML代碼就是一堆字符串,沒有任何意義,只有到了瀏覽器端執行纔有意義。
客戶端驗證不能代替服務器端驗證
設置取款金額不能高於100元
客戶端:<form id="form1"runat="server"οnsubmit="if(parseInt(document.getElementById('TextBox1').value,10)>100){alert('最多隻能取100');returnfalse;}">注:出錯啦!!!!!!!!!!!!!!!!!!
服務器端:Label1.Text = "取款金額爲:" + TextBox1.Text;
如果禁用JavaScript(Internet選項——安全——自定義級別——腳本——活動腳本——禁用,用maxthon裏的【內容控制】——【禁用JavaScript】進行控制。那麼客戶端JavaScript校驗就被禁用了,就可以取款多於100元了。
解決方法:在服務器端也進行數據校驗。
客戶端校驗是爲了很好的客戶端體驗,服務器端校驗是最後一次把關,防止惡意請求。後面要講的ASP.NetValidation就是ASP.Net內置的數據校驗技術,會在客戶端和服務器端同時校驗。
對Button來講,onclick是服務器端代碼,OnClientClick是最終生成到客戶端瀏覽器中的onclick代碼。
---------------------- Windows Phone 7手機開發、.Net培訓、期待與您交流! ---------------------- 詳細請查看:http://net.itheima.com/