1、畫好用戶登陸界面html
同時換下請求的地址。git
獲取用戶信息及判斷代碼插入位置:web
1、畫好用戶登陸界面sql
同時換下請求的地址。數據庫
獲取用戶信息及判斷代碼插入位置:瀏覽器
<%@ WebHandler Language="C#" Class="_06_login" %> using System; using System.Web; public class _06_login : IHttpHandler { public void ProcessRequest (HttpContext context) { context.Response.ContentType = "text/plain"; //在服務其上獲取用戶輸入的用戶名和密碼判斷是否正確。 string name=context.Request.Form["name"]; string pwd=context.Request.Form["pwd"]; if (name=="admin"&&pwd=="admin") { context.Response.Write("登陸成功"); } else { context.Response.Write("登陸失敗"); } } public bool IsReusable { get { return false; } } }
2、登陸演示服務器
若是用戶登陸失敗了,用戶想從新登陸,爲何要把判斷寫到服務器上面呢?JS判斷無法判斷數據庫去,因此只能放到服務器上面。ide
還想在用戶登陸失敗以後,返回登陸頁面怎麼作呢?工具
第一種解決辦法拼html。post
登陸失敗顯示登陸界面代碼插入位置:
<%@ WebHandler Language="C#" Class="_06_login" %> using System; using System.Web; using System.Text; public class _06_login : IHttpHandler { public void ProcessRequest (HttpContext context) { context.Response.ContentType = "text/html"; //拼html StringBuilder sb = new StringBuilder(); sb.Append("<html>"); sb.Append("<body>"); //action就是提交給本身 sb.Append("<form action='06-login.ashx' method='post'>"); //雙引號改爲單引號 sb.Append("用戶名:<input type='text' name='name' />r/>"); sb.Append("密碼:<input type='text' name='pwd'/><br/>"); sb.Append("<input type='submit' value='login'/>"); sb.Append("</form>"); sb.Append("</body>"); sb.Append("</html>"); //在服務其上獲取用戶輸入的用戶名和密碼判斷是否正確。 string name=context.Request.Form["name"]; string pwd=context.Request.Form["pwd"]; if (name=="admin"&&pwd=="admin") { context.Response.Write("登陸成功"); } else { context.Response.Write("登陸失敗"); } //輸出登陸 context.Response.Write(sb.ToString()); } public bool IsReusable { get { return false; } } }
3、登陸失敗提示用戶演示
想下登陸失敗以後怎麼就更省事兒,更方便?
登陸失敗以後就把用戶輸入的用戶名和密碼清空了,這樣很差,用戶就不知道本身輸入的是什麼了。
咱們作個把用戶名顯示出來的界面。
剛纔登陸以後,爲何輸入的信息都沒了呢?
4、爲何文本框裏面沒有值
4、爲何文本框裏面沒有值
5、給文本框返回值的寫法
6、返回值的演示
咱們都是運行html,要是直接運行通常處理程序會直接顯示登陸失敗。
這樣寫特別的不舒服,得不停的拼html字符串。
7、不拼html,直接運行通常處理程序
8、再改下html頁
運行html和通常處理程序,咱們發現都有問題,先看下運行html。只有第一次運行的時候有問題,怎麼解決呢?
只能再ashx裏面來完成,第一次的時候替換成空,何時是第一次呢?
以表單的方式,讀取的時候是空,說明是第一次。第一次請求時get請求。
9、幫咱們判斷是第幾回
10、判斷頁面是不是首次加載
寫完以後,運行通常處理程序就好了。
11、最終效果演示
12、登陸過程圖
爲何用隱藏域呢?若是這不放佔位符,經過JavaScript的方式呢?演示原理的,演示webform裏面的一個內容,這個內容就叫作隱藏域。
十3、第一次是get請求
十4、post請求
如今咱們再按F5
十5、提示信息
十6、這是怎麼回事兒
這樣會給咱們帶來什麼不方便的地方呢?交易的時候post會帶來錯誤的,點擊重試又買了一次。添加的時候,點擊F5提交到數據庫,點擊F5又提交到數據庫一次。怎麼解決呢?跳轉到成功頁面。跳轉的時候是get請求,再按F5就不會出這個問題了。
下面咱們看下作什麼事情的時候用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的表單從新敲地址欄再刷新就不會提示從新提交了,由於從新敲地址就沒有偷偷提交的數據了。Post方式的正確的地址很難直接發給別人。
Get方式URL數據格式。服務端文件名後跟着「?」,因爲客戶端可能向服務器端提交多個鍵值對,鍵值對之間用「&」進行分割,若是URL中有漢字、特殊符號等,則須要對URL進行編碼。
表單域只有設定了name的纔會被提交給服務器(用get方式看的清楚)。若是給submit按鈕設定name,那麼按鈕的value也會被提交給服務器
【刷新】。
十7、對URL進行編碼
下面咱們作個數字自增的練習:
要求:頁面上放一個文本框,一個按鈕,文本框默認是0,點一次按鈕文本框加1.
寫好的html頁面插入位置:
<!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"> <head> <title></title> </head> <body> <form action="07-數值自增.ashx" method="post"> <input type="text" value="@name" /> <input type="submit" value="click" /> </form> </body> </html>
初步寫好的ashx插入位置:
<%@ WebHandler Language="C#" Class="_07_數值自增" %> using System; using System.Web; public class _07_數值自增 : IHttpHandler { //1.定義一個變量 int n = 0; public void ProcessRequest (HttpContext context) { context.Response.ContentType = "text/plain"; //3.把頁面輸出出來 string path = context.Request.MapPath("07-數值自增.htm"); string html=System.IO.File.ReadAllText(path); //2.輸出 n++; context.Response.Write(n); context.Response.Write(html); } public bool IsReusable { get { return false; } } }
這個時候寫成這個樣子,數值不會自增,這是什麼緣由呢?第一次請求是一,服務器不會把值存起來的.怎麼解決呢?
初始化的時候,讓文本框的值等於0,再點按鈕的時候,post回來了,把文本框的值取出來,進行++,從新放回去。每一次執行完成以後,都把上一次的值從新放到文本框裏面來,下一次請求的時候會把值post給服務器,服務器讀取完++再從新放回來。何時給它的值付成0呢?第一次的時候,點按鈕的時候++。因此用到隱藏域。
十8、放個隱藏域
讀取隱藏域並判斷是不是第一次加載
<%@ WebHandler Language="C#" Class="_07_數值自增" %> using System; using System.Web; public class _07_數值自增 : IHttpHandler { public void ProcessRequest (HttpContext context) { context.Response.ContentType = "text/html"; //1.定義一個變量 int n = 0; //3.把頁面輸出出來 string path = context.Request.MapPath("07-數值自增.htm"); string html=System.IO.File.ReadAllText(path); //讀取隱藏域,判斷是不是第一次加載 string viewstate=context.Request.Form["_viewstate"]; if (!string.IsNullOrEmpty(viewstate)) { //post string txt=context.Request.Form["txtNum"]; n = int.Parse(txt); n++; } //給文本框賦值 html = html.Replace("@num", n.ToString()); //2.輸出 context.Response.Write(html); } public bool IsReusable { get { return false; } } }
十9、同時,我還修改了一下html代碼。
二10、數值自增演示
如今咱們作的這個是刷新頁面的數值自增,後面咱們還要帶領你們作無刷新。
下面咱們再作幾個練習:
練習:用ashx實現加法計算器。常見錯誤:type=submit纔會自動提交表單,type=button不會自動提交。從ashx啓動和從html啓動的區別
二11、作好準備工做
計算加法的通常處理程序代碼插入位置:
<%@ WebHandler Language="C#" Class="_08_add" %> using System; using System.Web; public class _08_add : IHttpHandler { public void ProcessRequest (HttpContext context) { context.Response.ContentType = "text/html"; //1.讀取靜態模板 string path = context.Request.MapPath("08-add.htm"); string html = System.IO.File.ReadAllText(path); //2.判斷頁面是不是首次加載 string viewstate=context.Request.Form["_viewstate"]; if (!string.IsNullOrEmpty(viewstate)) { string num1=context.Request.Form["txtNum1"]; string num2=context.Request.Form["txtNum2"]; int num3 = int.Parse(num1) + int.Parse(num2); //把兩個文本框的值從新替換回去,還有計算以後的值也返回去。 html = html.Replace("@num1", num1).Replace("@num2", num2).Replace("@num3", num3.ToString()); } //若是是第一次加載的時候把文本框的值付成空。 else { html = html.Replace("@num1", "").Replace("@num2", "").Replace("@num3", ""); } //3.輸出 context.Response.Write(html); } public bool IsReusable { get { return false; } } }
二12、加法計算演示
若是出問題了,並且在代碼裏面一眼看不出來,這個時候要設個斷點調試.通常處理程序怎麼進行調試呢?
二十3、這樣調試進不去斷點
二十4、調試過程
練習:實現div內文本的自增。由於服務器不記得上次給瀏覽器的值是什麼,並且不像input那樣會將上次的值從新提交回來,所以瀏覽器須要用一個隱藏字段將上一次的值保存下來。代碼見備註
二十5、寫好html頁
二十6、實現div內文本的自增代碼
二十7、div內文本自增演示
http無狀態,每次請求都是由一個新的頁面對象來處理請求。若是把value搞成static能夠實現,可是兩個用戶訪問的話就會串了。而用Input方式的話兩我的各自點各自的,不會互相影響。
非表單元素沒法將客戶端的元素值傳遞給服務器端,即便是表單元素也只能傳遞value值,對於其餘屬性值好比背景顏色、大小等也是沒法傳遞的,所以對於這些值都要存在隱藏字段中。
下面咱們經過以前咱們講解的三層,作個照片列表。
二十8、新建解決方案
這樣作方便管理三層裏面的幾個項目。
二十9、對應生成文件夾
下面建立三層那幾個項目,從下往上建立。
三10、model
三11、再建立DAL
再建立BLL
三12、新建網站
這塊在瀏覽的時候要找對文件夾
三十3、找對文件夾
這個命名空間很差看,中間加個點。這裏學習微軟起個頂級的命名空間。
三十4、屬性
這樣再添加一個model類的時候就有點了。
三十5、把沒用的類都刪掉
下面咱們添加引用:
三十6、添加引用一
三十7、添加引用二
三十8、添加引用三
建好以後先寫model,咱們這裏就不寫了,直接把之前寫好的拷貝過來。
三十9、直接拷貝過來
檢查下命名空間就好了。
先寫dal寫個SQLHelper。這裏咱們用什麼寫什麼,就去作那個照片列表。
四10、別忘了添加引用
建個配置文件,建到UI,運行誰,配置文件就放到哪一個裏面。咱們發現配置文件有了,打開它。
四11、忘了的話打開這兒
四12、寫好配置文件
四十3、寫好SqlHelper
下面咱們操做那個photos表,把表中全部的數據查詢出來,生成一個照片列表。
四十4、再建立一個類操做photo表
拿數據的DAL代碼插入位置:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Data; using MyPhotos.Model; namespace MyPhoto.DAL { public class PhotosDAL { //1.拿到照片數據 public List<Photos> GetAllPhotos() { List<Photos> list = new List<Photos>(); string sql = "select*from photos"; //2.執行 SQLHelper helper = new SQLHelper(); DataTable dt = helper.GetTable(sql); //把關係轉換成對象 foreach (DataRow dr in dt.Rows) { Photos p = RowToPhotos(dr); list.Add(p); } return list; } //3.寫個方法 private Photos RowToPhotos(DataRow dr) { Photos p = new Photos(); p.PClicks = Convert.ToInt32(dr["PClicks"]); p.PDes = dr["PDes"].ToString(); p.PDown = Convert.ToInt32(dr["PDown"]); p.PId = Convert.ToInt32(dr["PId"]); p.PTime = Convert.ToDateTime(dr["PTime"]); p.PTitle = dr["PTitle"].ToString(); p.PTypeId = Convert.ToInt32(dr["PTypeId"]); p.PUp = Convert.ToInt32(dr["PUp"]); p.PUrl = dr["purl"].ToString(); p.PUserId = Convert.ToInt32(dr["PUserId"]); return p; } } }
一句話寫完BLL層。
四十5、寫好BLL
咱們底層的代碼就寫完了,你們能夠參考咱們以前的關於三層的知識進行復習。
咱們主要的任務就是寫UI層的代碼。
添加個通常處理程序:
爲了好看一點再建個模板。
四十6、作好靜態頁
寫好通常處理程序後咱們運行一下,發現報錯了。
四十7、常見的報錯一
編譯一下,就是從新生成解決方案。
四十8、常見的報錯二
四十9、看到照片列表
給表格加個邊框。
五10、加個邊框
在數據庫建題目中表的SQL:
create database MyPhotos go use MyPhotos go create table PhotoType --相冊 ( TypeId int identity(1,1) primary key, TypeName nvarchar(50) not null, TypeDes nvarchar(500) ) go create table Photos ( PId int identity(1,1) primary key, PTypeId int not null, PUserId int not null, --User表的主鍵 PTitle nvarchar(100) not null, PUrl nvarchar(100) not null, --圖片的名稱 PDes nvarchar(1000), --描述 PClicks int, --點擊次數 PTime datetime, --錄入時間 PUp int, --支持 PDown int --反對 ) go create table Comments ( CId int identity(1,1) primary key, CPhotoId int not null, --照片的id CText nvarchar(1000), --評論內容 CTime datetime, --評論時間 CUp int, CDown int ) go create table [User] ( UId int identity(1,1) primary key, UName varchar(8), UPwd varchar(20) ) go create view v_Photo as SELECT dbo.Photos.PId, dbo.Photos.PTypeId, dbo.Photos.PUserId, dbo.Photos.PTitle, dbo.Photos.PUrl, dbo.Photos.PDes, dbo.Photos.PClicks, dbo.Photos.PTime, dbo.Photos.PUp, dbo.Photos.PDown, dbo.PhotoType.TypeId, dbo.PhotoType.TypeName, dbo.PhotoType.TypeDes FROM dbo.Photos INNER JOIN dbo.PhotoType ON dbo.Photos.PTypeId = dbo.PhotoType.TypeId go alter table Photos add constraint DF_pClicks default(0) for pClicks alter table Photos add constraint DF_PUp default(0) for PUp alter table Photos add constraint DF_PDown default(0) for PDown alter table Photos add constraint DF_pTime default(getdate()) for pTime alter table Comments add constraint DF_cTime default(getdate()) for cTime alter table Comments add constraint DF_CUp default(0) for CUp alter table Comments add constraint DF_CDown default(0) for CDown alter table Photos add constraint FK_PTypeId foreign key(PTypeId) references PhotoType(TypeId) alter table Comments add constraint FK_CPhotoId foreign key(CPhotoId) references Photos(PId) use MyPhotos insert into phototype values('人物','人物') insert into phototype values('風景','風景') insert into phototype values('卡通','卡通') insert into phototype values('家庭','家庭') insert into phototype values('自拍','自拍') insert into [user] values('admin','admin') insert into [user] values('zs','00000') insert into [user] values('ls','00000') insert into [user] values('ww','00000') insert into photos(PTypeId,PUserId,ptitle,purl,pdes) values(1,1,'圖片1','01.jpg','圖片one') insert into photos(PTypeId,PUserId,ptitle,purl,pdes) values(1,2,'圖片2','02.jpg','圖片two') insert into photos(PTypeId,PUserId,ptitle,purl,pdes) values(1,2,'圖片3','03.jpg','圖片three') insert into photos(PTypeId,PUserId,ptitle,purl,pdes) values(1,1,'圖片4','04.jpg','圖片four') insert into photos(PTypeId,PUserId,ptitle,purl,pdes) values(1,1,'圖片5','05.jpg','圖片five') insert into photos(PTypeId,PUserId,ptitle,purl,pdes) values(2,1,'圖片6','06.jpg','圖片six') insert into photos(PTypeId,PUserId,ptitle,purl,pdes) values(2,2,'圖片7','07.jpg','圖片seven')
五11、表格樣式
五12、最終美圖
咱們能夠用以前學過的東西加個隔行變色,加個高亮顯示。