ASP.NET 總結

本人錄製技術視頻地址:https://edu.csdn.net/lecturer/1899 歡迎觀看。

一、Socket 就是兩個程序通訊用的

一臺計算機上的端口有65536個(1~65535)http:80端口、FTP:21端口、SMTP:23端口Socket一般應用模式(服務端和客戶端)

服務器端的Socket(至少需要兩個)

1、一個負責接收客戶端的連接請求(不負責與客戶端通信)2、每成功接收到一個客戶端的連接便在服務端上產生一個對應的Socket(負責與客戶端通信)

客戶端的Socket必須指定要連接的服務端地址和端口,連接成功後,負責與服務端的對應的Socket進行通信工作

socket.Sent() 如果有兩個連續的發送,可以認爲是一起發送的,因爲兩者發送的時間間隔很短,只有20ms左右。


二、WebApplication(Web應用程序)和WebSite(網站)的區別

WebSite是爲了兼容從ASP轉過來的開發人員的習慣而存在的,用起來比較簡單,1、不需要命名空間。2、“CS代碼”修改以後不需要重啓就能看到變化,但是不利於工程化開發, 比如代碼出錯不容易發現,代碼不分命名空間。3、生成的dll文件的路徑不是在bin中,但通過反射可以迅速找到其路徑。

(Reponse.Write(this.GetType().Assembly.Location))講簡單基礎知識時用WebSite;講高級技術和做項目的時候用WebApplication 


三、form 提交method (Get, Post 的區別,默認是Get)

1)get是通過url傳遞表單值,post傳遞的表單值是隱藏在http報文中的,url中看不到

2)get傳遞的數據量是有限的,post沒有限制(post可以用來上傳文章type=“file”,傳遞密碼type=“password”,發表大段文章<textarea>)

3)post在刷新時會有提示重新提交表單的問題,確定的話,就相當於再次進行了post提交(但重新敲地址欄就是get提交了) 


四、http響應碼

200:ok

301:Moved Permanently---永久轉移

302:Found---重定向

307:Temporary Redirect

400:Bad Request---錯誤的請求(服務器不認---發出錯誤的不符合http協議的請求)

401:Unauthorized---未認證(一般需要用戶名、密碼才能登陸)

403:Forbidden---禁止訪問(訪問權限等)

404:Not Found---沒有找到

500:Internal Server Error---服務器內部錯誤

503:Service Unavailable---訪問人數過多 


五、報文

【1】http請求報文

1)用httpwatch查看訪問一個網站的響應情況,敲入一個網址後,瀏覽器向服務器發出請求。頁面中的html、圖片、js、css在單獨的請求中。網頁加載時是一一響應的。

2)get .....aspx http1.1表示向服務器用get方式請求首頁,使用http1.1協議。

3)Accept-Encoding gzip,deflate表示瀏覽器支持gzip,deflate兩種壓縮算法。

4)Accept-Language zh-cn表示瀏覽器支持的語言,很多進入後自動就是中文界面的國際網站就是通過讀取這個頭的值實現的。

5)Connection keep-Alive(長連接 服務器響應之後 等待很短的時間,當很短的時間內沒有人連接才斷開) 一般情況下,一旦web服務器向瀏覽器發送了請求數據,它就要關閉TCP連接,然後如果瀏覽器或者服務器在其頭信息加入了Connection keep-Alive,則TCP連接在發送後將任然保持打開狀態,於是,瀏覽器可以繼續通過相同的連接 發送請求。保持連接節省了每個請求建立新連接所需的時間,還節約了網絡帶寬。(短連接 服務器響應之後 立即斷開連接)

6)Cookie是瀏覽器向服務器發送和當前網站關聯的Cookie,這樣在服務端也能讀取瀏覽的Cookie了,一般可以把sessionId放在其中傳遞給服務器,從而取到對應session值。

7)User-Agent爲瀏覽器的版本信息。通過這個信息可以讀取瀏覽器是IE還是FireFox、支持的插件、Net版本等。結構圖如下:

【2】服務器返回的報文
1)Server:Cassini/3.5.0.5表示服務器的類型

2)Content-Type:text/html;charset=utf-8表示返回數據的類型

3)服務器是通過Content-Type告訴客戶端響應的數據的類型,這樣瀏覽器就根據返回數據的類型來進行不同的處理,如果是圖片類型就顯示圖片,如果是文本類型就直接顯示內容,如果用html類型就用瀏覽器顯示內容,如果是下載類型就彈出下載工具等。常用Content-Type:text/HTML,image/JPEG,text/plain,text/javascript,application/x -excel,application/octet-stream(二進制文件)

4)Content-Length表示後續數據消息體的長度,報文頭只是描述,返回的具體數據(比如HTML文本、圖片數據等)在兩個回車之後的內容。
結構圖如下: 

 


六、Web開發的基本原則

1)最小權限原則。只允許用戶做***,而不是不允許用戶做***

2)能在客戶端完成的事情,儘量不要在服務端實現。
3)客戶端驗證不能代替服務端驗證, 客戶端校驗是爲了很好的客戶體驗(避免一校驗就刷新頁面),服務端校驗是最後一次把關,防止惡意破壞瀏覽器查看的是服務端代碼的執行輸出文本,看不到aspx的源代碼。

C#代碼是運行在服務器端,JS是運行在客戶端的。 


七、Response 和 Request

Request的方法:

1、獲得post數據:context.Request.Form["txtName"];

2、獲得get數據: context.Request.QueryString["txtName"];

一般不使用context.Request.Params["txtName"] 和 context.Request["txtName"] 這兩種方法第一種要進行遍歷,第二種使用的是索引,效率不高,用上面兩種形式就可以了。

Response的方法:

Write()響應的緩存輸出:爲了提高服務器的性能,ASP.NET向瀏覽器Write的時候默認並不會每write一次都會立即輸出到瀏覽器,而是會緩存數據,到合適的時機或者響應結束纔會將數據一起發送到瀏覽器。Flush()將緩存區數據立即發送給瀏覽器,這在需要將write出來的數據立即輸出到瀏覽器的場合非常適用。案例:大批量數據的導入,顯示正在導入第幾條,用Thread.Sleep模擬耗時。End()結束輸出(並將緩衝區中的內容輸出到客戶端)
Redirect()重定向 


八、一般處理程序

一般處理程序實現了IHttpHandler接口,而這個接口中包含了
ProcessRequest(HttpContext context)這個方法,HttpContext即指上下文,即對請求和響應都可以在實現的類中完成,只有實現了這個接口的類才能接受瀏覽器的請求!

一般處理程序執行的大致步驟(以數字自增爲例)? 

public void ProcessRequest (HttpContext context) {
	context.Response.ContentType = "text/html"; 
	//1、讀取html中的內容(這裏讀取的永遠是那個模板裏面的值) 
	string html = context.Request.MapPath("div數字自增.htm"); 
	html = System.IO.File.ReadAllText(html);
	//設置初始值爲0
	int i=0;
	string _viewstate = context.Request.Form["_viewstate"]; 
	//3、不是首次進入頁面(點擊按鈕post提交過來的)
	if (!string.IsNullOrEmpty(_viewstate))
	{
		//post是將瀏覽器端輸入的值提交過來的
		string num = context.Request.Form["getnum"]; 
		i = Convert.ToInt32(num)+1;
	} 
	//2、不管是首次進入還是post提交過來的,都進行替換工作 
	html = html.Replace("@value", i.ToString()); 
	//在頁面上顯示最終的結果 
	context.Response.Write(html);
}

模板:

<form action="div數字自增.ashx" method="post">
<input type="hidden" name="_viewstate" value="aa" /> 
<input type="hidden" name="getnum" value="@value" /> 
<div>@value</div>
<input type="submit" name="name" value="提交" />
</form>

1、用戶首次通過敲地址欄訪問,服務端就讀取實現在服務端準備好的模板頁,並將結果返回給客戶端,此時客戶端顯示0
2、客戶端點擊"提交"按鈕進行自增操作,此時是post提交過來的,服務端發現_viewstate的值不爲空,就進行了num數字加1操作,然後將結果1返回給瀏覽器3、當客戶端繼續點擊"提交"按鈕,由於瀏覽器上的數字是服務端響應返回的數值1,因此此時提交的是1,然後進行如2的步驟操作,完成自增操作。

爲什麼要這麼折騰的進行操作?? 是因爲服務端是無狀態的,不會"記住"上次發生了什麼,所以將值保存在隱藏字段中! 



九、其他一些知識點

1. 127.0.0.1是迴環地址(LoopBack),就是表示訪問本機,localhost就是127.0.0.1別名,是無法在外部訪問的,連本機IP也訪問不了。0.0.0.0任意IP(AnyIP),不用寫死綁定的IP了,通過任何一塊網卡都可以訪問網絡程序。

2. http爲什麼是無狀態的?爲什麼要斷開連接?

因爲服務器響應之後,就很快會斷開連接了;減小服務器壓力

3. ASP.NET後臺做的事情:存儲數據、訪問數據庫、複雜的業務邏輯運算、安全性要求高的運算。

如果設置了控件的disabled屬性爲true,即使控件有name及value屬性,也提交不到服務端

Request.UserHostAddress獲得訪問者的IP,通過這個可以限定提交次數。


 十、enctype的說明

<form action="上傳圖片.ashx" method="post" enctype="multipart/form-data"></form>默認情況下enctype的值爲application/x-www-form-urlencoded,可以不寫。這種情況,報文的發送字符串是以"&"連接的,但遇到上傳文件,這樣寫就不合理了,因爲文件編碼後,內部字符串也有可能是以&連接的,就混亂了,此時enctype應該設置爲multipart/form-data,它的實現是隨機生成很多橫線加一數字字符串的格式,這樣各個條件之間就可以分開了。 


十一、全局處理程序(寫在App_Code文件夾中的cs文件)

其受aspnet_filter.dll的保護,客戶端是無法直接訪問的。

使用方法:在使用之前,先在配置文件中的<httpHandlers>節點進行如下的配置工作

<add verb="*" path="images/*.jpg" type="ImageHandler"/>它表示想要進行對images文件夾下的jpg文件進行直接處理,必須先經過ImageHandler.cs的操作。比如:用戶想直接通過輸入網址,直接訪問圖片,而網站的要求是必須先點擊小圖鏈接進來纔可以訪問的,這時候就可以提示用戶不可以訪問。而對於服務端其他的處理程序就可以直接進行對images文件夾下jpg圖片的處理,不需要經過ImageHandler.cs的操作。

aspnet_filter.dll的兩個作用

1 保護目錄(App_Code, App_Data 等,裏面的類不能被直接訪問)

2 在禁用cookie的情況下,從url中獲取sessionId 並且把請求轉向到真實的文件 


十二、關於幾個url

<a href="url.ashx">點擊</a>

設置這個htm文件的路徑爲 http://localhost:1093/asp.net練習/關於url/url.htm

url.ashx這個文件的路徑爲 http://localhost:1093/asp.net練習/關於url/url.ashx

context.Response.Write(context.Request.RawUrl + "<br />");context.Response.Write(context.Request.Url+"<br />");context.Response.Write(context.Request.UrlReferrer + "<br />");三者的輸出結果爲:

RawUrl表示被訪問文件的相對路徑

/asp.net練習/關於url/url.ashx

Url表示被訪問文件的全路徑

http://localhost:1093/asp.net練習/關於url/url.ashx

UrlReferrer表示被訪問文件請求頁面的路徑

http://localhost:1093/asp.net練習/關於url/url.htm 


十三、 圖片水印的問題

當把水印效果的程序發佈到IIS上的時候,是看不出水印效果的,因爲圖片是靜態頁面,客戶端請求的時候,IIS服務器發現其是靜態頁面,直接將圖片返回給瀏覽器,而對圖片進行水印處理的程序還沒有來得及進行處理。爲解決這個問題,應該手動配置一下IIS,即在映射表中增加圖片的映射,即.jpg--aspnet_isapi.dll. 


十四、Application(全局文件global.asax)

UrlReferrer作用:防下載盜鏈、防圖片盜鏈,但是現在可以被僞造了(迅雷就是盜用的)。如果直接訪問本網站的圖片地址或者別的網站用a標籤訪問你圖片的地址,UrlReferrer就是null,如果是嵌入到別的網頁中(本網站中)的請求,UrlReferrer就是頁面的地址。 

void Application_BeginRequest(object sender, EventArgs e) 
{
	Response.ContentType = "image/jpeg"; 
	//請求的是圖片(防盜鏈處理)
	if (Request.RawUrl.ToLower().Contains("images/")) {
		//盜鏈過來的,則輸出防盜鏈圖片
		if (Request.UrlReferrer == null || !CheckTheSame(Request.UrlReferrer, Request.Url)) 
		{
			string path = Request.MapPath("~/盜鏈圖片.png"); Response.WriteFile(path);
			Response.End();
		}
	} 
}
//判斷本次請求與上次請求是否是同一個域名及端口號
bool CheckTheSame(Uri uri1,Uri uri2) 
{
	return Uri.Compare(uri1, uri2, UriComponents.HostAndPort, UriFormat.SafeUnescaped, StringComparison.CurrentCultureIgnoreCase) == 0;
}

十五、html中的相對路徑

/ html中的根路徑 不管有沒有虛擬目錄都返回http://localhost/daolian.jpg, 即看不到虛擬目錄

./ 或者不寫 指當前目錄
../ 上一級目錄
asp.net中的根路徑(要有runat="server")

~/ 如果有虛擬目錄返回http://localhost/Webform/daolian.jpg

如果沒有虛擬目錄返回http://localhost/daolian.jpg 


十六、Server對象

Server.MapPath就是調用Request.MapPathServer的UrlEncode、UrlDecode、HtmlEncode、HtmlDecode方法,以後直接用HttpUtility的這些方法使用就可以了!

因爲有的地方很難拿到Server這個對象。 


十七、在C#代碼中輸出JS腳本的兩種方式

1、腳本輸出的位置 form表單結束標籤之前Page.ClientScript.RegisterStartupScript(this.GetType(),"name","alert('內容')",true);

2、腳本輸出的位置 form表單開始標籤之後Page.ClientScript.RegisterClientScriptBlock(this.GetType(), "name", "alert('內容')", true); 


十八、Response.Redirect()、Server.Transfer()、Server.Execute()之間的區別?

Response.Redirect 是有瀏覽器參與的(瀏覽器經過了多次請求),所以在地址欄中可以看到地址的變化。

Server.Transfer 與Server.Execute()是服務器內部的轉接,瀏覽器請求了一次,瀏覽器不知曉,故地址欄中看不出url的變化,而兩者的區別是: 

Server.Transfer在內部轉接後,直接由最後一個接受的地址,返回數據給瀏覽器,

而 Server.Execute()是最後一個接受的地址處理完畢數據後,依次返回,再由剛開始瀏覽器請求的地址將數據返回給瀏覽器。 


十九、ASP.NET常用的狀態保持方式(前兩種客戶端,後兩種服務端)

ViewState、Cookie、Session、Application

1.  ViewState(就是在頁面的一個隱藏域[它是由服務端生成並輸入到客戶端的]中保存客戶端數據,然後通過這個隱藏域將內容提交給服務端。)

非表單元素無法將客戶端的元素值傳遞給服務器端,即使是表單元素也只能傳遞value值,對於其他屬性值比如顏色、大小等也是無法傳遞的,因此對於這些值都要存在隱藏字段中,這就是ASP.NET中ViewState的實現原理。禁用ViewState的 

方法:設置EnableViewState=“flase”.內網系統,互聯網的後臺可以盡情的用ViewState。Http協議是無狀態的,不會記得上次和網頁“發生了什麼”,狀態信息保存在隱藏字段中的缺點:加大網站的流量、降低訪問速度、機密數據放到表單中會有數據欺騙等安全問題。

ViewState作用:將瀏覽器中的內容提交給服務器,讓服務器記起“上次”在幹什麼,如果禁用則沒有反應了,但在服務端賦值是可以的。它適用於同一個頁面在不關閉的情況下多次與服務器交互。<!--ViewState對於需要PostBack處理的頁面纔可能用,對於新聞展示頁面(不需要用戶交互)完全沒有必要用ViewState。禁用頁面的ViewState並沒有完全去掉ViewState,只要ViewState不是很大就可以了,如果要求一點ViewState都沒有,那麼在頁面中就不能有runat=“server”的form,但禁用,很多的服務端就用不了了,所以不提倡這種做法。-->

例子:(假設Label1.Text初始值爲10)//禁用了ViewState就讀不到上次客戶端的值,也就是在隱藏字段裏面不接受用戶提交過來的值,只讀取服務端的默認值(點提交按鈕,結果永遠是10,50;但如果沒有禁用,首次進來是10,50;但以後提交就永遠是50,50了)

Response.Write("Label1的值是:"+Label1.Text+"<br/>");Label1.Text = "50";//即使禁用ViewState,在請求沒有結束之前,也能讀出來設置的值Response.Write("Label1的值是:"+Label1.Text+"<br/>");

面試舉例:webform下div,input數字自增的區別:div版本的值存到了ViewState中,TextBox版本的不用存,因爲TextBox就屬於input,自己會提交給服務器,不需要隱藏字段。對於div自增,在自增過程中,如數字變爲5的時候,自己將其篡改爲10,再點擊自增按鈕,會顯示6對於input自增,在自增過程中,如數字變爲5的時候,自己將其篡改爲10,再點擊自增按鈕,會顯示11

2.  Cookie:就是存儲在瀏覽器裏的一些數據(以文本信息存儲)。Cookie在服務端和客戶端都可以存在!客戶端向服務器提交時,除了傳遞普通的name字段的值,也會提交Cookie;服務器返回數據除了普通的html數據以外,還會返回修改的Cookie,瀏覽器把拿到的Cookie值更新本地瀏覽器的Cookie就可以。

互聯網優化:圖片服務器和主站域名不一樣,降低Cookie流量的傳輸。

Cookie應用:打開頁面時自動填上用戶名,網頁換膚。

存儲Cookie的方式:

1、存儲在內存中(關閉網頁就沒有了)2、存儲在硬盤中(設置了Expires屬性。關閉網頁,在限定時間內,它被保存在硬盤中)

Cookie的幾個特徵:

1、Cookie是與域名相關的,所以163.com是不能讀取baidu.com記錄的Cookie。

2、一個域名能寫入的Cookie尺寸是有限制的(4k左右),能寫入的Cookie總條數一般是幾十條。

3、Cookie不是寫入以後一定下次能讀出來的,瀏覽器可能會定期清除,用戶也可能手動清除。

Cookie用法(客戶端的操作方式)設置值:$.cookie("名字","值");一般應該設置有效期限:$.cookie("名字","值",{ expires: 10 });讀取值:var v=$.cookie("名字");

Example:網頁換膚

<html xmlns="http://www.w3.org/1999/xhtml"> <head>
<title></title>
<script src="Scripts/jquery-1.4.1.js" type="text/javascript"></script> 
<script src="Scripts/jquery.cookie.js" type="text/javascript"></script> 
<script type="text/javascript">
	$(function () {
		var color = $.cookie('color'); if (color) {
			$('body').css('background', color); 
		}
		$(':button').click(function () { 
			$('body').css('background', $(this).val());
			$.cookie('color', $(this).val(), { expires: 10 }); 
		});
    });
</script>
</head>
<body>
	<input type="button" name="name" value="red" /> 
	<input type="button" name="name" value="green" /> 
	<input type="button" name="name" value="blue" />
</body>
</html>

cookie用法(服務端的操作方式) 

//賦值
protected void Button1_Click(object sender, EventArgs e)
{
	//自定義一個Cookie
	HttpCookie cookie = new HttpCookie("time"); 
	cookie.Value = DateTime.Now.ToLocalTime().ToString(); //注意設置過期時間,不然程序關閉就沒有了 
	cookie.Expires = DateTime.Now.AddDays(1); 
	//將Cookie反饋到瀏覽器(賦值) 
	Response.SetCookie(cookie);
} 
//取值
protected void Button2_Click(object sender, EventArgs e) {
	if (Request.Cookies["time"] == null) 
	{
		Response.Write("沒有您要讀取的Cookie"); 
	}
	else {
	    Response.Write(Request.Cookies["time"].Value);
	}
} 
//清除Cookie
protected void Button3_Click(object sender, EventArgs e) {
	//千萬不能用Request.Cookies.Remove(),因爲這個方法,只是移除了副本,瀏覽器端的Cookie,服務端沒有權利 移除!
	int num = Request.Cookies.Count; for (int i = 0; i < num; i++)
	{
		//自定義一個Cookie
		HttpCookie cookie = new HttpCookie("time"); 
		cookie.Value = DateTime.Now.ToLocalTime().ToString(); //注意設置過期時間,不然程序關閉就沒有了 
		cookie.Expires = DateTime.Now.AddDays(1); 
		//將Cookie反饋到瀏覽器(賦值) 
		Response.SetCookie(cookie);
		HttpCookie hc = Request.Cookies[i];
		//服務端只有權利設置客戶端Cookie過期時間,然後反饋給客戶端,瀏覽器發現Cookie過期了,它就會去刪
		hc.Expires = DateTime.Now.AddDays(-1); 
		//hc.Path="/虛擬目錄名/文件夾名"; //如果設置了這個Path,只有在此文件夾下的頁面纔可以訪問Cookie 
		Response.SetCookie(hc);
	} 
}

3.  Session提供了一種把信息保存在服務器內存中的方式,它能存儲任何數據類型包括自定義的對象。保存和當前客戶端相關聯的數據。不要放太多的對象到Session,Session會有超時銷燬的機制(服務器不知道瀏覽器是否關閉)。 

Session應用:驗證碼(防止暴力破解,暴力註冊)。在ashx中調用Session,這個類一定要實現IRequiresSessionState接口。

Session是與Cookie相關聯的,因爲sessionid就保存在客戶端的Cookie中,所以當用戶關閉瀏覽器後,下次就訪問不到(重新生成一個sessionid)指定的那一個Session了,而那塊區域的Session會超時銷燬。

掌握Session原理代碼的意義。嘗試寫出來(賦值取值和直接調用ASP.NET提供的Session機制寫出賦值取值),寫出Session版本的數字自增
【session原理實現】
自定義session類 

public class SessionMgr {
	//static表示根據不同的sessionid可以創建多個不同的session,第一個string表示sessionId,第二個string表示用 戶傳遞過來的name,object表示value值
	//下面的字典就是在服務端中存放的用戶sessionId及其所對應的信息。
	private static IDictionary<string, IDictionary<string, object>> data = new Dictionary<string,
	IDictionary<string, object>>(); //下面的方法返回的數據就是Session,接受的參數就是由cookie傳遞過來的sessionId 
	public static IDictionary<string, object> GetSession(string sessionId)
	{
		if (data.ContainsKey(sessionId)) {
			return data[sessionId];
			//在內存中分配好一個Session區域,可以讓用戶存放數據。
	    }
		else
		{ 
			//用來判斷擁有此sessionId的用戶以前有沒有記錄,如果沒有,就爲他自動分配一個Session區域。
			IDictionary<string, object> session = new Dictionary<string,object>(); 
			data[sessionId] = session;
			return session;
		} 
	}
}

aspx.cs中的代碼 

protected void Page_Load(object sender, EventArgs e) 
{
	//因爲cookie是與當前用戶使用的特定瀏覽器相關的,所以可以綁定sessionId //下面的if判斷既是首次瀏覽,就自動爲其分配一個sessionId
	if (Request.Cookies["MySessionId"] == null)
	{
		string sessionId = Guid.NewGuid().ToString();
		Response.SetCookie(new HttpCookie("MySessionId", sessionId)); 
	}
} 

//爲指定用戶設置其保留的內容
protected void Button1_Click(object sender, EventArgs e) 
{
	string sessionId = Request.Cookies["MySessionId"].Value; 
	IDictionary<string, object> session = SessionMgr.GetSession(sessionId); 
	session["服務端的數據"] = DateTime.Now.ToString(); 
	session["其他的數據"] = "Fuck you";
} 

//取出指定用戶的保留信息
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 Session是保存在aspnet_wp.exe中的

Session丟失情況:
1、存放Session的電腦重啓

2、InProc模式:aspnet_wp.exe或w3wp.exe在“任務管理器”中或其它情況下導致其進程被終止運行。

3、InProc模式:修改.cs文件後,編譯了兩次(只編譯一次,有時不會丟失)

4、InProc模式:修改了Web.config

5、InProc模式,Windows 2003環境:應用程序池回收、停止後重啓

6、InProc模式:服務器上bin目錄裏的.dll文件被更新

Session分三種:
1.InProc(進程內)-默認就是這種-速度快/但內存小/易丟失

進程外(有兩種):可以在IIS或ASPNET服務意外關閉時繼續保持狀態,注意此時存儲到session中的對象必須支持序列化:

2.StateServer:此時Session存儲在aspnet_state.exe中

1.1修改配置文件<system.web><sessionState mode="StateServer"stateConnectionString="tcpip=localhost:42424"/>設置是否允許遠程使用,直接收索--regedit(打開註冊表)然後找到內容,將 HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\aspnet_state\Parameters的值改爲1並且將localhost改爲運行aspnet_state.exe那臺電腦的ip

1.2默認端口號:424241.3開啓服務:直接收索--services.msc(ASP.NET 狀態服務)

3.SQLServer:此時Session存儲在數據庫中在vs的命令行中輸入:

1.aspnet_regsql.exe -S 127.0.0.1 -U sa -P woshinibaba -ssadd -sstype c -d 數據庫名
2. <sessionState mode="SQLServer" allowCustomSqlDatabase="true" sqlConnectionString="DataSource=.;Initial Catalog=test;uid=sa;pwd=woshinibaba"></sessionState>
3.對象必須可序列化 


二十、.aspx繼承自 .aspx.cs, 他們之間的具體關係看反編譯分析

1  .aspx.cs可以調用.aspx的runat="server"控件的原因?

編譯之後,前臺頁面的runat="server"控件已經作爲變量的方式到父類裏面了

2  .aspx中可以訪問後臺aspx.cs的非私有成員的原因?

.aspx繼承自.aspx.cs

3  瀏覽器請求頁面的aspx時,服務器是通過反射創建了相應的頁面對象來處理的。這個類是前臺類還是後臺類?是調用這個對象的什麼方法來處理請求的?

前臺類、 ProcessRequest()

4 服務器調用頁面類對象返回html代碼的過程?

先由頁面類對象的 __buildControlTree()方法創建控件樹,執行頁面生命週期,然後調用頁面對象的Render方法來循環遍歷控件樹,並分別調用每個控件相應的Render方法來產生每個控件相對應的html代碼,最後組成整個頁面的html代碼。 


二十一、AJAX (Asynchronous JavaScript and XML, 異步JavaScript和XML)

是一種進行頁面局部異步刷新的技術。用AJAX向服務器發送請求和獲得服務器返回的數據並且更新到界面中,不是整個頁面刷新而是在HTML頁面中使用JavaScript創建XMLHTTPRequest對象來向服務器發出請求以及獲得返回的數據,這樣頁面就不刷新了。XMLHTTPRequest是AJAX的核心對象。

原理性代碼(重要): 

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
<script type="text/javascript"> //杜絕中文!!!起名字的時候用英文(get提交的方式)
	function btnClick() { //分辨是不是IE瀏覽器,其他瀏覽器用標準的XMLHttpRequest,而IE用ActiveXObject var xmlhttp;
		if (window.XMLHttpRequest) {
			xmlhttp = new XMLHttpRequest(); 
		}
		else if (window.ActiveXObject) {
			xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
		} 
		//true表示異步傳輸,false表示同步傳輸,後面加一個條件就是爲了防止緩存 
		xmlhttp.open("get", "ShowTime.ashx?id="+new Date(), true); //注意字母的大小寫
		xmlhttp.onreadystatechange = function () {
			//4表示接收數據完畢
			if (xmlhttp.readyState == 4) {
			//200表示服務端返回的報文正確 
				if (xmlhttp.status == 200) {
					document.getElementById("time").innerHTML = xmlhttp.responseText;}
			else {
				 alert("AJAX服務器返回錯誤!");
			} 
		}
	}; //向服務端發送請求 
	xmlhttp.send();
} 
</script>
</head>
<body>
<form id="form1" runat="server">
<div id="time"></div>
<input type="button" name="name" value="顯示" onclick="btnClick();"/> 
</form>
</body>
</html>

readyState屬性指出了XMLHttpRequest對象在發送/接收數據過程中所處的幾個狀態。XMLHttpRequest對象會經歷5種不同的狀態。
0:對象已經創建,但未初始化。

1:已打開。對象已經創建並初始化,但還未調用send方法

2:已發送。已經調用send 方法,但該對象正在等待狀態碼和頭的返回;

3:正在接收。已經接收了部分數據,但還不能使用該對象的屬性和方法,因爲狀態和響應頭不完整;

4:已加載。所有數據接收完畢 


二十二、JSONP (JSON with padding), 可以跨域加載數據,使用JSONP形式調用函數時, 如:"myurl?callback=?", query將自動替換?爲正確的函數名,以執行回調函數。

爲什麼使用JSONP??如果不使用JSONP,當需要從別的網站獲取信息的時候,頁面加載,先去獲取別的網站的信息,然而本網站的數據加載就要等待你獲取完信息後才能加載,使用JSONP,實現了異步的操作,增強了客戶體驗。
例子: 

$(function(){ 
	//獲取別的網站的JSON數據,放入(padding)到data中
	$.getJSON("http://9snow.org/weather/api?city=北京&callback=?",function(data){ //然後就可以在自己的網站利用別人網站的數據了
	}); 
});

二十三、控件的生命週期

1、由_builderControlTree()方法,完成頁面控件樹的創建

2、由LoadAllState()方法加載控件的狀態管理信息,給控件保持狀態(表單元素等除外)

3、ProcessPostData()對生成的控件樹的控件進行一定的處理

4、Load事件,就是完成父類的Page_Load事件

5、ProcessPostData()對在Load事件中有可能動態生產的控件進行再加工

6、觸發控件的事件

1) RaiseChangeEvents() 就是去執行**_**Changed一類的事件

2) RaisePostBackEvent() 就是去執行**_**Click一類的事件.......

Render

Unload

由上述控件的生命週期可以看出:"Load事件"是在"觸發事件"執行之前執行的,因此,當你點擊進行"觸發事件"之後,肯定先要經過"Load事件"的處理,然後再處理"觸發事件"的具體代碼。 


二十四、 服務端控件簡介

Label控件,AssociatedControlID屬性用來關聯一個控件

Literal控件也是展示一段文本,但是Literal控件不會渲染任何額外的標籤,就是將Text屬性的值展示出來而已。

onclick是服務端事件,onClientClick是最終生成到客戶端瀏覽器中的onclick先執行渲染到客戶端的onClientClick,再執行服務端的onclick

ClientID,控件在客戶端的Id,控件在服務端的Id不一定等於客戶端HTML中的Id,比如說在ListView等控件的模板中。在客戶端使用方式:$('#<%=txt1.ClientID%>')

Visible屬性,控件是否可見,如果Visible=False是不會渲染到HTML中的,這和在HTML中給元素style.display='none'效果是不一樣的。

Attributes,用來設置獲取控件的額外屬性,或者在服務端註冊事件,最終渲染後,還是執行的客戶端js腳本。Button1.Attributes[“onmouseover”] = “alert(‘hello’)”; 


二十五、三種控件說明

1、HTML控件,ASP.Net把HTML控件當成普通字符串渲染到瀏覽器不去檢查正確性,並且無法在服務端進行處理。

2、ASP.Net服務端控件,經過ASP.Net高度封裝的控件,使用簡單,運行在服務器端,可以在服務端使用C#代碼進行操作,會渲染到客戶端爲HTML控件,【暴露的屬性一般是C#的屬性】

3、runat="server"的HTML控件。在HTML控件的基礎上添加runat="server"也是運行在服務器端的,可以用C#代碼進行操作,也會渲染到客戶端。不像ASP.Net服務端控件那樣高度封裝,【暴露的屬性大部分是普通HTML屬性】。使用場合:如果控件沒有被ASP.Net服務端控件封裝的時候,用runat=server的HTML控件很方便。如td、div、label等 


二十六、顯示圖片的幾種方式

1、HTML控件:<img src="images/bjxz.png" width="100" height="100"/>

2、runat="server"的HTML控件<img src="~/baodiao/images/bjxz.png" width="100" height="100"runat="server"/>

3、服務端控件<asp:Image ID="Image1" runat="server" ImageUrl="~/baodiao/images/bjxz.png"/>

4、ResolveClientUrl:<img src='<%=ResolveClientUrl("~/baodiao/images/bjxz.png")%>' width="100"height="100"/>

建議用第四種,避免了服務端控件,因爲代碼中如果有太多的runat=“server”會降低系統性能。 


二十七、關於數據綁定控件

關於數據綁定控件(具體代碼參見“E:\傳智終極版_李飛\練習總結\ASP.NET高級部分”)(注:所有的綁定操作都是在Page_Load事件之後進行的,因爲,拖拽的綁定控件是最終Render到aspx頁面的)

I) DropDownList

DropDownList顯示來自於ObjectDataSource的數據,選擇數據源(DataSourceID屬性)爲剛纔的ObjectDataSource,

並且設定顯示字段(DataTextField)和值字段(DataValueField)即可

II) Repeater

Repeater(foreach)用於對綁定數據源中的數據進行遍歷並按格式顯示(自己本身並不輸出),每條數據以什麼格式顯示是由Repeater的<ItemTemplate>來決定的

<%=控件ID.ClientID%>,<%#Eval("UserName")%>,<%#Bind("UserName")%>的區別?

<%=控件ID.ClientID%>是指在進行js操作時,從服務端控件中得到Id,如果直接寫Id,有可能有客戶端生成的Id不一致,所以要用ClientID。<%#Eval("UserName")%>是指從數據庫中取得字段爲UserName的值並顯示在頁面上(只讀)

Eval的其他的用法:
1、<%# Eval("字符串"),"{0:c}" %> 以錢幣的形式顯示
2、<%# Eval("時間字符串"),"{0:yyyy-MM-dd}" %> 以特定格式的日期形式顯示

<%#Bind("UserName")%>是雙向綁定,不但可以進行讀操作,也可以將修改的數據更新到數據庫中。

//Eval()在處理字符時,如果字符格式如:01.jpg,它解析之後的結果爲1.jpg,所以要進行處理,在父類中自定義一個方法進行處理(因爲Eval返回值類型爲object,所以參數也是object類型): 

protected string GetFullPath(object url) 
{
	string urlPath = url.ToString();
	int intName = Convert.ToInt32(Path.GetFileNameWithoutExtension(urlPath)); 
	if (intName < 10)
	{
		urlPath = "0" + urlPath; 
	}
	return urlPath; 
}

然後在頁面中如下調用即可以了
<img src='../images/<%#GetFullPath(Eval("Url")) %>' />

Repeater的兩個事件:ItemDataBound、ItemCommand

ItemDataBound是在控件綁定完成之後觸發,依次對每一行進行判斷。ItemCommand是在綁定完成之後,對其項進行處理(一般是按鈕的事件)。

Repeater可以使用這個 <%# Container.ItemIndex+1%> 方式進行編號 

III) ListView

ObjectDataSource(ListView) 高效分頁操作步驟:
1、查詢共多少條數據GetCount() 返回int
2、查詢第幾頁的數據GetPaged(int startRowIndex,int maximumRows) 返回泛型集合

pageIndex 當前頁碼-1
pageSize 每頁幾條數據
select * from (select *,row_number() over(order by pid desc) as num from photos) as t where num > @startRowIndex and num<= @startRowIndex+@maximumRows order by pid desc作爲ObjectDataSource的數據源

3、選擇ObjectDataSource的SelectMethod屬性 =GetPagedEnablePaging = true
SelectCountMethod = GetCount

4、在頁面上,把ObjectDataSource生成的參數刪除<asp:Parameter Name="startRowIndex" Type="Int32" /><asp:Parameter Name="maximumRows" Type="Int32" />

5、可以設置DataPager的控件PageSize屬性(決定每頁幾條數據)可以設置QueryStringField的值爲pageNumber,就可以get方式提交,看出第幾頁了 


二十八、 母版頁

如果一個子頁面想操作母版頁中的內容(如點擊子頁面中的名字爲Button1的按鈕,將母版頁中的Id爲ButtonMaster按鈕的文本顯示出來),可以用以下方法:

protected void Button1_Click(object sender, EventArgs e)
{
	Button btn = Master.FindControl("ButtonMaster") as Button; 
	Response.Write(btn.Text);
}


二十九、 緩存

什麼時候用緩存?

1. 頁面上的數據不經常變化;

2. 訪問量比較大緩存是一種用空間換時間的技術,存在於計算機中很多的地方,用來將一些慢速設備中的常用數據保存在快速設備中,存取數據的時候直接從快速設備中取。

緩存存在失效的問題:爲了保證從緩存中讀取數據和慢速數據中數據一致,則需要在慢速數據中對應的數據發生變化的時候,清除緩存中相應的數據。

緩存是改進網站性能的第一手段,就像索引是改進數據庫性能的第一手段一樣。ASP.NET緩存主要分爲:頁面緩存、數據源緩存、緩存依賴這三種主要類型(都是緩存在服務端的!)。

緩存實現大致原理代碼:

protected void Page_Load(object sender, EventArgs e)
{
	List<Model.T_Photo> list = new List<Model.T_Photo>(); 
	if (Cache["photo"] == null)
	{
		BLL.T_PhotoBLL bll = new BLL.T_PhotoBLL();
		list = bll.GetAll(); //首次加載,從數據庫獲得數據,並將數據保存在緩存中,以後取數據,就直接從緩存中取了!
		Cache["photo"] = list; 
		//如果寫成下面的形式,大致就是自定義緩存的原理(設置了滑動過期時間): 
		//Cache.Insert("photo",list,null,Cache.NoAbsoluteExpiration,new TimeSpan(0,10,0));
	} else {
		list = Cache["photo"] as List<Model.T_Photo>; 
	}
	foreach (Model.T_Photo photo in list) {
		Response.Write(photo.Title+"<br />"); 
	}
}

1、頁面緩存
使用方法:在頁面頭加如下代碼:

<%@ OutputCache Duration="10" VaryByParam="none" %>可以指定根據哪項進行緩存,如:點擊進入新聞詳細頁面,而每條新聞的newsId是不一樣的,所以可以根據newsId進行緩存,VaryByParam="newsId"(寫在新聞展示頁面),如果有多項,之間有;分割。如果想讓任何不同的查詢字符串都創建不同的緩存,則設置VaryByParam="*",一般情況下設置“*”就足夠。

頁面的局部緩存(最好不要這樣使用,用AJAX更好)大致思路,先設置頁面緩存,然後在不需要進行緩存的地方使用<asp:Substitution ID="Substitution1"MethodName="NoCache" runat="server" />,然後在後臺寫對應的實現的方法,如:

//這裏對應的內容可以不緩存!
public static string NoCache(HttpContext hc){

return DateTime.Now.ToString();}

2、數據源緩存設定ObjectDataSource的CacheDuration(緩存時間:秒),EnableCaching=true。即可。

3、緩存依賴(滑動策略)1) 依賴於文件

//文件的物理全路徑
string path=Request.MapPath("fileName");

CacheDependency dep=new CacheDependency(path);//參數:緩存名,緩存內容,依賴的文件(當文件個數或內容發生變化時,才重新緩存,否則保持原來的緩存內容)

Cache.Insert("photo", list, dep);

2) 依賴於數據庫
I) 輪詢機制:FW主動到數據庫檢查數據是否改變
1、數據庫緩存依賴
-S服務器名稱 -E集成身份驗證 -ed啓動 -d數據庫名稱 -et指定緩衝依賴的表名 -t表名在vs2010的命令提示符中運行(切換到aspnet_regsql.exe(先啓用它)所在的目錄)aspnet_regsql -S . -E -ed -d PhotoShow -et -t Comments

緩存依賴禁用該數據庫
aspnet_regsql -S . -E -dd -d PhotoShow

2、依賴於數據庫的web.config配置 

<system.web>
	<caching>
		<sqlCacheDependency enabled="true">
			<databases>
				<add name="PhotoShow" connectionStringName="連接字符串所對應的名字" pollTime="500"/>
			</databases> 
		</sqlCacheDependency>
	</caching>
</system.web>

II) 通知機制:數據庫通知FW數據是否改變 


三十、錯誤頁

配置錯誤頁,只要在Web.config中的<system.web></system.web>中添加以下代碼 :

<customErrors mode="RemoteOnly" redirectMode="ResponseRewrite" defaultRedirect="~/ErrorPage/ExceptionError.htm"> 
	//處理異常信息
	<error statusCode="403" redirect="NoAccess.htm" />
	<error statusCode="404" redirect="~/ErrorPage/NotFound.htm" />
</customErrors>

mode有三個可選項On(總是顯示定製錯誤頁),Off(直接顯示調用堆棧等異常信息),RemoteOnly(對於本機訪問顯示調用堆棧等異常信息,對於外部用戶顯示錯誤頁面)一般選擇RemoteOnly 


三十一、 IHttpModule就是起一個頁面加載前的過濾作用 (下例就是進行了身份驗證)

/// 注意:要實現IHttpModule這個接口的類,纔可以進行處理 
public class TestRight:IHttpModule
{
   public TestRight()
   {
   }
   public void Dispose() 
   {
   }
    
   public void Init(HttpApplication context) 
   {
		//對於處理Session的問題,不能使用context.BeginRequest註冊事件,因爲BeginRequest處理這個事件之前,還 沒有創建Session呢,AcquireRequestState事件是在Session創建之後才觸發的
		context.AcquireRequestState += new EventHandler(context_AcquireRequestState); 
	}

	void context_AcquireRequestState(object sender, EventArgs e) 
	{
		//在這裏進行權限驗證,只要這裏寫一次,所有的頁面加載的時候都會驗證有沒有登陸,沒有登陸的話,轉向登陸 頁面,讓其先進行登陸工作。其實有的時候,也可以將這裏的代碼寫在全局文件中,不過那樣做的話,全局文件中的代碼 會很多,所以交給HttpModule來完成!
		HttpApplication app = sender as HttpApplication; //在進行處理之前,應該將一些內容屏蔽掉,如登陸頁面、圖片、js、css等 //如下面不屏蔽掉Login頁面,永遠就沒有登陸的機會了,也就死循環了!!!即不是登陸頁面的話,就進行權限
的判斷
		if (!app.Request.RawUrl.ToLower().Contains("login.aspx") && !
		app.Request.RawUrl.ToLower().Contains("/images"))
		{
		//判斷有沒有登陸(注意:在請求照片的時候,根本就沒有Session這一說法,所以在上面if判斷要把照片也
		排除掉)
			if (app.Session["isLogin"] != "true")
			{
				//加url的原因:轉向登陸頁面後,如果登陸成功,直接轉向你登陸之前想要進入的那個頁面
				app.Response.Write("<script>alert('請先登錄');window.location.href='Login.aspx? returnUrl="+app.Request.RawUrl+"'</script>");
			} 
		}
	} 
}

在Login.aspx.cs中的大致代碼:

string url = Request.QueryString["returnUrl"];
//直接進入登陸頁面登陸的,轉向default頁面 if (string.IsNullOrEmpty(url))
{
    Response.Redirect("Default.aspx");
}
//通過別的頁面重定向到登陸頁面登陸的,登陸成功之後,轉向之前你想查看的頁面 
else
{
	Response.Redirect(url); 
}

在配置文件中,對實現IHttpModule的類進行配置 

<system.web>
	<compilation debug="true" targetFramework="4.0"/>
	<httpModules>
		<add name="test" type="TestRight"/>
     </httpModules>
</system.web>

三十二、url重寫

UrlRewrite (僞靜態) ,一般處理動態頁面

1、有利於SEO,帶參數的Url權重較低;2、地址看起來更正規

用IIS做服務器的時候,靜態頁面、圖片、js等不會觸發Application_BeginRequest事件在請求動態頁面的時候,哪怕請求文件不存在,也會經過Application_BeginRequest事件 

//Url重寫大致代碼:
protected void Application_BeginRequest(object sender, EventArgs e) 
{
	//得到請求文件的虛擬路徑 如 ~/AddComment-67.aspx
	string virtualPath = HttpContext.Current.Request.AppRelativeCurrentExecutionFilePath; 
	//如果用戶請求的是http://localhost:1050/AddComment-67.aspx這樣的頁面 //實際在後臺處理的是http://localhost:1050/AddComment.aspx?id=67 //但顯示給用戶的url地址就是請求的頁面地址
	Match match = Regex.Match(virtualPath, @"~/AddComment-(\d+)\.aspx");
	if (match.Success)
	{
		string id=match.Groups[1].Value;
	    HttpContext.Current.RewritePath("~/AddComment.aspx?id="+id);
	}
}

可以使用插件完成此功能:“URLRewriter.dll”步驟:
添加對URLRewriter.dll的引用

1、在<configSections>節點加入 

<section name="RewriterConfig" type="URLRewriter.Config.RewriterConfigSerializerSectionHandler, URLRewriter" />

2、在</configSections>之後加入 

<RewriterConfig> <Rules>
          <RewriterRule>
            <LookFor>~/(\d{4})/(\d{2})/Default\.htm</LookFor>
            <SendTo>~/Default.aspx?ID=$1</SendTo>
          </RewriterRule>
        </Rules>
</RewriterConfig>

3、<httpHandlers>中加入

<add verb="*" path="*.htm" type="URLRewriter.RewriterFactoryHandler, URLRewriter" />


三十三、 關於網站的發佈

1、VS中設置爲Release,將網站發佈出來

2、在IIS部署網站(發佈或者拷貝都可以)。在配置文件中將<compilation debug="true" targetFramework="4.0"/>debug設置爲false,刪掉cs代碼

3、上傳文件夾不給執行權限:在iis管理器中找到上傳文件夾,選擇屬性--執行權限,設置爲“無”。這樣哪怕利用漏洞上傳了可執行代碼到上傳文件夾,也無法執行。

4、取消所有文件夾的瀏覽權限,防止用戶查看網站的文件列表,在iis管理器中找到主站節點→屬性→主目錄→取消“目錄瀏覽”。

5、IIS管理中,Web服務器擴展,只允許asp.net那幾個,其他的CGI、ASP等全部禁止。 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章