先廢話一下
離上次寫MVC文章剛好一年了
這一年裡基本上我都沒機會去使用MVC
剛好這次公司有點數所以去上了課
自己又投資自己去上保哥的MVC5課程
剛好兩邊教法不一樣有些重點也不一樣
趁著還熟著時順手向同事要了個已經快開發成的案子
當然第一次寫要上線應該很難
接下來幾天會針對實作及遇到的問題做整理
一開始我想剛學完基礎的人
基本上跟我一樣不知如何下手
隨便要個舊專案或是拿個不是很重要的案子來寫
首先應該會從會員開始吧
但千萬別從新增會員開始
因為這樣就有點難了
我是以VS2013來開發目前是RTM
1.新增一個專案 > .net版本選4.5 > 選MVC > 建好了網站 > 刪除一些不必要的原件(Controllers Views Models)裡都刪了
只留View裡的Shared
2013範本是Bootstrap 3.0,jQuery 1.10.2。
2.開發分成Code First、DB First、Model First因個人習慣DB First所以先來建資料庫,先求簡單只有三個欄位,ID、登入帳號、密碼,但有一個重點記得設PK,EF必要的就是PK,這次實做簡單登入
所以直街先手動新增一筆假一料
3.建立一個ADO.NET 實體模型資料庫 > 由資料庫產生 > 新增連接 > 依提示操作設定連線資訊 > 測試連接看能不能成功 > 完成後記得build一下
4.在Controller新增一個AccountController 在新增一個View /Account/Login.cshtml
因為在微軟內建的驗證中有一個已經幫我們做好驗正了
app.UseCookieAuthentication(new CookieAuthenticationOptions
{
AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
LoginPath = new PathString("/Account/Login")
});
5.新增一個ViewModels資料夾來存放自己定義的model
加入
using System.ComponentModel.DataAnnotations;
using System.ComponentModel;
定義Model
public class Login
{
[DisplayName("登入帳號")]
[Required(ErrorMessage = "請輸入登入帳號")]
[StringLength(40, ErrorMessage = "登入帳號最多20個字")]
public string AccountName { get; set; }
[DisplayName("登入密碼")]
[Required(ErrorMessage = "請輸入登入密碼")]
[StringLength(40, ErrorMessage = "密碼最多20個字")]
[DataType(DataType.Password)]
public string Password { get; set; }
}
Login的畫面
2013-10-30更新
@using (Html.BeginForm("Login", "Login", new { ReturnUrl = ViewBag.ReturnUrl }, FormMethod.Post))
{
@Html.AntiForgeryToken()
@*@Html.ValidationSummary()*@
<h3>後台登入</h3>
<div class="logintype">
@Html.LabelFor(model => model.AccountName, new { @class = "control-label" })
<div class="controls">
@Html.TextBoxFor(model => model.AccountName, new { @class = "form-control", placeholder = "請輸入登入帳號" })
@Html.ValidationMessageFor(model => model.AccountName, null, new { @class = "help-inline" })
</div>
</div>
<div class="logintype">
@Html.LabelFor(model => model.Password, new { @class = "control-label" })
<div class="controls">
@Html.PasswordFor(model => model.Password, new { @class = "form-control", placeholder = "請輸入登入密碼" })
@Html.ValidationMessageFor(model => model.Password, null, new { @class = "help-inline" })
</div>
</div>
<div class="logintype">
@TempData["Error"]
</div>
<input type="submit" name="button" value="登入">
}
登入的Action
2013-10-30更新
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Login(Login form)
{
if (ModelState.IsValid)
{
//驗證資料庫登入
//這邊請使用自行驗證摟
string Sql = " AccountName == @0 and Password == @1 and IsUsed == @2";
var query = (from u in db.Account.Where(Sql, form.AccountName, form.Password, "true")
select u).ToList();
if (query.Count() != 1)
{
ModelState.AddModelError(string.Empty, "帳號或密碼錯誤登入失敗");
return View("Index",form);
}
try
{
query[0].LoginIP =PublicFunction.GetIpAddress();
query[0].LoginDate = DateTime.Now;
db.SaveChanges();
}
catch (Exception ex)
{
ModelState.AddModelError(string.Empty, ex.Message.ToString());
return View("Index", form);
}
bool isPersistent = false;//如果票證將存放於持續性 Cookie 中 (跨瀏覽器工作階段儲存),則為 true,否則為 false。 如果票證是存放於 URL 中,則忽略這個值。
string userData = "";//可放使用者自訂的內容
string mAccountID = query[0].AccountID.ToString();
//寫cookie
//使用 Cookie 名稱、版本、到期日、核發日期、永續性和使用者特定的資料,初始化 FormsAuthenticationTicket 類別的新執行個體。 此 Cookie 路徑設定為在應用程式的組態檔中建立的預設值。
//使用 Cookie 名稱、版本、目錄路徑、核發日期、到期日期、永續性和使用者定義的資料,初始化 FormsAuthenticationTicket 類別的新執行個體。
FormsAuthenticationTicket ticket = new FormsAuthenticationTicket(1,
mAccountID,//使用者ID
DateTime.Now,//核發日期
DateTime.Now.AddMinutes(1800),//到期日期 30分鐘
isPersistent,//永續性
userData,//使用者定義的資料
FormsAuthentication.FormsCookiePath);
string encTicket = FormsAuthentication.Encrypt(ticket);
Response.Cookies.Add(new HttpCookie(FormsAuthentication.FormsCookieName, encTicket));
//HttpCookie cookie = new HttpCookie(FormsAuthentication.FormsCookieName, encTicket);
//cookie.Expires = ticket.Expiration;
//Response.Cookies.Add(cookie);
//FormsAuthentication.RedirectFromLoginPage(strUsername, isPersistent);
if (form.ReturnUrl != null)
{
return Redirect(form.ReturnUrl.ToString());
}
else
{
return RedirectToAction("Index", "Admin");
}
}
//return RedirectToAction("Index", "Login", null);
return View("Index", form);
}
最後再需要驗證的Class上加[Authorize]
雖然大部份程式碼都是copy來的
但也花了一下午才了解如何登入
看來還真有的學呢
2013-10-26補充
請注意Web.Config裡的設定
<authentication mode="None" />
修改成
<authentication mode="Forms">
<forms loginUrl="/Login" path="/"></forms>
</authentication>
2013-10-30更新
在login頁多加一個returnUrl
這樣使用者登入後可直接到他需要的頁面
上面的View跟Controller都需更新
public ActionResult Index(string returnUrl)
{
ViewBag.ReturnUrl = returnUrl;
return View();
}
2013-11-13更新
MVC5使用範本新增如果加了authentication mode="Forms"
此時自訂的驗證會不正常
修改
public override void ExecuteResult(ControllerContext context)
{
var properties = new AuthenticationProperties() { RedirectUri = RedirectUri };
if (UserId != null)
{
properties.Dictionary[XsrfKey] = UserId;
}
context.HttpContext.GetOwinContext().Authentication.Challenge(properties, LoginProvider);
}
改為
public override void ExecuteResult(ControllerContext context)
{
//多下列這行
context.RequestContext.HttpContext.Response.SuppressFormsAuthenticationRedirect = true;
var properties = new AuthenticationProperties() { RedirectUri = RedirectUri };
if (UserId != null)
{
properties.Dictionary[XsrfKey] = UserId;
}
context.HttpContext.GetOwinContext().Authentication.Challenge(properties, LoginProvider);
}
參考網址
點我前往
點我前往
點我前往
點我前往
點我前往
點我前往