HTTP中Get與Post、ViewState 原理

來源:互聯網
上載者:User

標籤:web   產生   屬性   之間   請求   方式   box   value   system   

Http是請求,響應的模型,伺服器不會來讀取瀏覽器的網頁,只能夠得到用戶端提交過來的資料
當使用者點擊提交,伺服器就知道"提交回來了"(PostBack)

Get與Post


設定form的method屬性指定表單提交方式,get(預設值)是通過URL傳遞值,傳遞的資料量是有限的
post傳遞的表單值是隱藏到http報文中,URL中看不到,會有瀏覽器提示重新提交表單的問題,get沒有
Get方式URL資料格式,服務端檔案名稱跟著"?",由於用戶端可能向伺服器端提交多個索引值對,
索引值對之間用"&"進行分割,如果URL中有漢字,特殊符號等,則需要對URL進行編碼
表單域只有設定了name的才會被提交給伺服器

網頁只有設定了name的input,textarea,select的value屬性值才會被提交給伺服器
非表單元素無法將值傳遞給伺服器的
如:要設定DIV的值,直接是不行的,可以通過隱藏欄位實現,將隱藏欄位的value與DIV的內容設定成一樣
然後當使用者提交資訊,伺服器獲得隱藏欄位的值,並把值 替換掉網頁所有的 value

如果指定from 表單method屬性為get,那麼在 action=1.ashx?a=123的參數就會被刪除
如如果指定為post,那麼action中的參數就會被提交到伺服器來

ViewState 原理 (對於上面問題的解決辦法)

Label版本的值存到了ViewState中,TextBox版本的不用存,因為TextBox就是Input,自己就會提交給伺服器,不需要隱藏欄位.
用於asp.net重寫DIV文本自增(還要同時遞增Label的寬度,注意Width的單位)
Label1.Text = (Convert.ToInt32(Label1.Text)+1).ToString();
Label1.Width = new Unit(Label1.Width.Value + 10);
查看產生的原始碼,ASP.net將所有隱藏內容統一放到了名字為__VIEWSTATE的隱藏欄位中,使用序列化
演算法將所有隱藏的內容放到一個字串中,點擊幾次在使用ViewStateDecoder這個工具查看ViewState
內容,發現確實將這些改變的內容放到了ViewState中

禁用ViewState的方法:在頁面最上面 Page標籤 加入 EnableViewstate="false",禁用ViewState以後
TextBox版本不受影響,DIV版本受影響,因為input的value不依靠ViewState(可以禁用單個控制項)
禁用ViewState後並不是完全去掉ViewState,還會有一小段代碼,如果想在頁面中完全沒有ViewState
那麼在頁面中就不能有 runat=server的form,如果Button等服務端控制項沒有放到runat=server的form
中,那麼則是不用的

回答ViewState原理的時候說:input版本(TextBox)自增和DIV版本(Label)的不同

--------- ViewState 使用:

     // 在後台為 ViewState 賦值          this.ViewState["key"] = "004";          this.ViewState.Add("key2", 360);     // 調用 ViewState    Label1.Text = this.ViewState["key"].ToString();

只要有runat=server的form就會產生 _VIEWSTATE等,所以去掉form的runat=server,這樣除了Repeater等少數控制項之外服務端控制項都沒法使用,只能使用html標籤。
這是為什麼說"要求高的互連網項目不用服務端控制項"

無狀態HTTP

1.HTTP協議是無狀態的,不會記得上次和網頁"發生了什麼",如果要知道上一次的狀態,
一個方法就是在對瀏覽器響應結束之前將狀態資訊儲存到頁面表單中,下次頁面再向伺服器發出請求的
時候帶上這些狀態資訊,這樣伺服器就能根據這些狀態資訊還原上次的狀態了
2.狀態資訊儲存在隱藏欄位中的缺點:加大網站的流量,降低訪問速度,機密資料放到表單中會有資料欺騙等安全問題

原因:HTTP是用的TCP協議,為了降低伺服器的消耗,當伺服器響應完用戶端後,就立馬段掉,所以無狀態

ASP.NET儲存狀態有以下幾種:

Application 當前應用程式(所有使用者使用一個Application)
Session當前會話(每個使用者一個會話)
Cookie儲存在用戶端的
ViewState針對當前頁面(每個頁面有一個ViewState)

一、Application 對象

Application是全域的,儲存與操作都放在伺服器端,任何人都能訪問

使用 object 儲存
this.Application["t1"] = TextBox1.Text;
Application.Lock();//鎖定
Application.UnLock();//解鎖

可以在 Global.asax 中對網頁的訪問量,點擊量 做一些統計

二、Cookie的使用

Cookie存在用戶端
Cookie是和網站相關的,並且每次向伺服器請求的時候除了發送表單參數外,還會將和網站相關的所有
Cookie都提交給伺服器,是強制性的,Cookie也是儲存在瀏覽器端的,而且瀏覽器會在每次請求的時候都
會把和這個網站相關的Cookie提交到伺服器,並將服務端返回的Cookie更新回資料庫,因此可以將資訊
儲存Cookie中,然後在伺服器端讀取,修改.
伺服器返回資料除了普通的html資料以外,還會返回修改後的Cookie,瀏覽器把拿到的Cookie值更新本地
瀏覽器的Cookie就可以

設定:

Response.SetCookie(new HttpCookie("Color",TextBox1.Text));

Response.Cookies.Add(new HttpCookie("Size","22"));

讀取:

Lable1.Text = Request.Cookies["Color"].Value;

擴充使用:

HttpCookie h1 = new HttpCookie("Color", TextBox1.Text);    //建立一個Cookie對象 h1.Expires = DateTime.Now.AddHours(1);    //設定到期時間,只能用DateTime格式h1.HttpOnly = true;    //設定用戶端是否能夠訪問指令碼Response.SetCookie(h1);    //設定CookieResponse.AppendCookie();    //追加Cookie

Cookie的缺點和表單一樣,不能儲存過多的資訊.

網站最佳化案例:
網站的圖片伺服器要與主站網域名稱不一樣,降低Cookie流量的傳輸
注意:圖片,CSS,JS等靜態檔案,都是單獨請求中

如果一個網站有 多個圖的話,本地又有那個網站的 cookie 的話,
那麼訪問時,請求HTML 有傳一次 Cookie, 請求每張圖片都要再傳 cookie ,這樣就浪費了。。
如果設定 圖片伺服器的網域名稱和 主站的不一樣的話,當下載圖片的時候就不會傳 cookie 了,
因為 cookie 是不可以跨域的!!

三、Session原理

Session存放在伺服器端,存放的是object類型
private int i = 0; //每次請求來了都會new一個新的實現了IHttpHandler介面的類"變數"的執行個體,
進行處理,用完了就GC掉,所以不會保持上次的值,所以不會自增
private static int j = 0; // static不會被執行個體化,所有訪問者都訪問同一個J的執行個體,
仍然儲存上次的值,所以會自增
Cookie不能儲存過多資訊,如果想儲存大量的資料,可以儲存一個Guid到Cookie中,然後在伺服器中建立一個以Guid為Key,複雜資料為Value全域Dictionary,static 欄位對於不同使用者也只有一份,

因此用static實現多使用者共用資料,代碼如下:

public class sessionMgr        //session管理頁面{    private static IDictionary<string,IDictionary<string, object>> data = new Dictionary<string,IDictionary<string,object>>();    public static 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;        //為data增加value ,sessionId為KEY,session為value            return session;        }    }   }    protected void Page_Load(object sender, EventArgs e)  //載入事件    {        if (Request.Cookies["MySessionId"] == null)    //判斷是否有MySessionId,沒則增加        {            string sessionId = Guid.NewGuid().ToString();            Response.SetCookie(new HttpCookie("MySessionId", sessionId));        }    }    protected void btus_Click(object sender, EventArgs e) //設定Session單擊事件    {        string sessionId = Request.Cookies["MySessionId"].Value;        IDictionary<string, object> session = sessionMgr.GetSession(sessionId);        session["服務端的資料"] = DateTime.Now;  //添加索引值    }    protected void butd_Click(object sender, EventArgs e)  //讀取Session單擊事件    {        string sessionId = Request.Cookies["MySessionId"].Value;        IDictionary<string, object> session = sessionMgr.GetSession(sessionId);        butd.Text = Convert.ToString(session["服務端的資料"]);    }

ASP.net已經內建了Session機制,把上面的例子用ASP.NetSession重寫,
注意:不要放太多的對象到Session,Session會有逾時銷毀的機制
可以看到Session機制並不是HTTP協議規定的,是ASP.NET實現的,現在PHP,JSP等大部分服務端技術都
實現了Session,原理都差不多
如果當使用者禁用了 Session ,可以在 Web.conf 中的 <system.web>裡面增加屬性,使得將SeesionID儲存到 URL 中,<sessionState cookieless="UseUri" />

ASP.NET內建的 Session

Session["one"] = DateTime.Now;            //設值Label1.Text =Convert.ToString(Session["one"]);    //取值

 

HTTP中Get與Post、ViewState 原理

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.