利用MVC架構 實作我的部落格(一)
程式看再多,沒有自己實作,還是不太踏實。
所以我打算花三個月(預計)的時間,自己做一個個人的部落格系統。
雖然到時不一定能上線,不過希望在實作的過程中,了解順便解決問題。
這個分類是紀錄我開發的過程中遇到的問題及解決的辦法,由於屬於練功性質,所以
架構跟程式方面可能會很凌亂,但是,就是學個經驗。
預計要有的功能:
- 頁面:文章分類、文章瀏覽、搜尋、排序、標籤、以文找文。
- 會員:註冊、登入、登出、收藏文章、回覆文章、留言。
- 管理者:發表文章、文章管理、類別管理、會員管理、發送電子報、製作電子報。
第一個階段先把基本的功能弄出來,然後再來切版面,等雛型完成之後,再來做進階的功能。
第一天先做了登入以及註冊的功能…
拉出一個會員的table,然後建立一個 LINQ to SQL的dbml檔,在Model中建立一個資料夾Repository
專門放操作資料庫的類別。
先做了三個Controllers,分別是HomeController、MemberController、BaseController
BaseController是先建出來之後可以擴充用的,繼承Controller
public class BaseController : Controller
{
}
然後將其他的Controller繼承到BaseController
public class HomeController : BaseController
{
}
然後先做了註冊頁面,之前的文章有提到怎麼用Partial Class的方法做Server端的驗證
初學 ASP.NET MVC 學習筆記(七),所以這個部分做起來還滿順的。
大部分欄位都不能為空值
[Required(ErrorMessage = "請輸入信箱")]
像帳號長度不能超過12個字
[StringLength(12,ErrorMessage="長度不能超過12個字元")]
信箱有用規則驗算式
[RegularExpression(@"^([\w-\.]+)@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.)|(([\w-]+\.)+))([a-zA-Z]{2,4})$", ErrorMessage = "請輸入正確的電子郵件位址,如:www@www.com")]
剩下的幾乎都是作苦工,一個屬性一個屬性慢慢設,設完就OK了。
在註冊的View上,生日的部分用JavaScript的套件選:
詳細請參考Demo大的:
JSCalendar超好用的日期選擇器 For ASP.NET MVC
或是看原文:
http://www.dynarch.com/projects/calendar/
而我還沒把它包成Helper,所以目前在View上是這樣用:
<%= Html.TextBoxFor(model => model.生日, new { @id="生日"})%>
<button type="button" id="f_btn1">
小日曆</button><br />
<script type="text/javascript"> //<![CDATA[
var cal = Calendar.setup({
date: 19800101,
onSelect: function(cal) { cal.hide() }
});
cal.manageFields("f_btn1", "生日", "%Y-%m-%d");
//]]>
</script>
然後在註冊頁為了防止用機器人瘋狂註冊,所以先做了一個簡單的驗證碼
做法是在Controller中件一個回傳FileResult的方法,然後用GDI將隨機亂數畫出來:
public FileResult BMP()
{
string[] Code ={ "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M",
"N", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z",
"1", "2", "3", "4", "5", "6", "7", "8", "9" };
string strRd = string.Empty;
Random rd = new Random(); //unchecked((int)DateTime.Now.Ticks)
Bitmap Bmp = new Bitmap(80, 25); //建立實體圖檔並設定大小
Graphics Gpi = Graphics.FromImage(Bmp);
Font Font1 = new Font("Verdana", 14, FontStyle.Italic);
for (int i = 0; i < 5; i++) // 亂數產生驗證文字
{
strRd += Code[rd.Next(34)];
}
Pen PenLine = new Pen(Brushes.Red, 1); //實體化筆刷並設定顏色、大小(畫X,Y軸用)
Gpi.Clear(Color.Black); //設定背景顏色
Gpi.DrawLine(PenLine, 0, rd.Next(80), 90, rd.Next(25));
Gpi.DrawString(strRd, Font1, Brushes.AntiqueWhite, 0, 0);
for (int i = 0; i <= 25; i++) //亂數產生霧點,擾亂機器人辨別
{
int RandPixelX = rd.Next(0, 80);
int RandPixelY = rd.Next(0, 25);
Bmp.SetPixel(RandPixelX, RandPixelY, Color.Pink);
}
Session["ValidateCode"] = strRd; //將驗證碼存入Session以便稍後進行驗證
MemoryStream s = new MemoryStream();
Bmp.Save(s, System.Drawing.Imaging.ImageFormat.Gif);
return File(s.GetBuffer(), "image/gif");
}
之後在View上就可以用
<img src="<%=Url.Action("BMP")%>" id="bmp" />
將產生出來的驗證碼圖片Show在頁面上。
註冊要驗證時,只要將輸入驗證碼的input欄位的值跟存在Session中的亂數比對就行了。
註冊做完之後,就做登入。
登入我以前都是用Session來做登入判斷,跟把登入的會員資料都塞到Session中
但是.net有提供另外一種方便的登入方式,可以參考保哥的
概略解釋 Forms Authentication 的運作
登入的Action這樣寫:
登入密碼 = FormsAuthentication.HashPasswordForStoringInConfigFile(登入密碼, "SHA1");
var m = t會員repository.Gett會員By帳號密碼(登入帳號, 登入密碼);
if (m == null)
return View();
Session.RemoveAll();
FormsAuthenticationTicket ticket = new FormsAuthenticationTicket
(1,
m.ID.ToString(),
DateTime.Now,
DateTime.Now.AddMinutes(30),
false,
"Member",
FormsAuthentication.FormsCookiePath);
string encTicket = FormsAuthentication.Encrypt(ticket);
Response.Cookies.Add(new HttpCookie(FormsAuthentication.FormsCookieName, encTicket));
登出也很簡單,只要一行:
public ActionResult LogOut()
{
FormsAuthentication.SignOut();
return RedirectToAction("Index", "Home");
}
如果某些頁面要登入的使用者才能看的話,只要在Action上加一句:
[Authorize]
就行了。參考:ASP.NET MVC Form 驗證- demo小鋪
最後呢,在登入之後,我希望可以抓出一些使用者的資料,例如姓名,show在View上。
所以在View上這樣寫:
<%if (Request.IsAuthenticated) //判斷使用者是否登入,true代表登入
{ %>
哈囉,<%=SideHelper.Get會員姓名() %> <%=Html.ActionLink("登出","LogOut","Member") %>
<%}
//如果是則用自己建立的Helper抓出使用者的名字
//如果不是就出現登入的input
else{ %>
<%using(Html.BeginForm("LogIn","Member")) {%>
<%=Html.LabelFor(model=>model.登入帳號) %>
<%=Html.TextBox("登入帳號")%>
<%=Html.LabelFor(model=>model.登入密碼) %>
<%=Html.Password("登入密碼")%>
<input type="submit" value="登入" />
<%} %>
<%} %>
而Helper這樣寫:
namespace MyBlog.Helpers
{
public static class SideHelper
{
public static string Get會員姓名()
{
It會員Repository 會員 = new t會員Repository();
return 會員.Get會員姓名(HttpContext.Current.User.Identity.Name);
//HttpContext.Current.User.Identity.Name就是剛剛登入時塞進去的會員ID
}
}
}
Repository中的方法這樣寫:
public string Get會員姓名(string id)
{
if (String.IsNullOrEmpty(id))
return "";
var m = (from p in db.t會員 where p.ID.Equals(id) select p).FirstOrDefault();
if(m!=null){
return m.暱稱;
}
return "";
}
完成之後,未登入時是看到
登入之後就是:
收工。第一天做完這些,大概花了三個鐘頭。