首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> .NET 網頁程式設計 >> 關於.NET

ASP.NET MVC 校友錄實戰(六):Code First 遷移與班級模組核心實作

     編輯:關於.NET

承接前文,本篇深入探討 Entity Framework Code First 的資料庫遷移策略,並完整呈現班級模組的核心功能:使用者登入驗證(含 MD5 雜湊)、Cookie 記住我、班級建立與圖片上傳、AJAX 動態新增學校。

一、使用者登入與密碼雜湊

前端登入表單

@model AlumniBook.Models.LoginViewModel
@using (Html.BeginForm("ToLogin", "Log"))
{
    @Html.AntiForgeryToken()
    @Html.ValidationSummary(true)
    <div class="login-form">
        @Html.TextBoxFor(m => m.UserName, new { @class = "form-control" })
        @Html.PasswordFor(m => m.Password, new { @class = "form-control" })
        @Html.CheckBoxFor(m => m.RememberMe) @Html.LabelFor(m => m.RememberMe)
        <button type="submit">登入</button>
        @if (!string.IsNullOrEmpty(ViewBag.Error)) 
        { <span class="error">@ViewBag.Error</span> }
    </div>
}

後端驗證邏輯

[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult ToLogin(LoginViewModel model)
{
    using (var db = new AlumniBookContext())
    {
        string hashedPwd = CryptoHelper.GetMD5(model.Password);
        var user = db.Users.FirstOrDefault(u => 
            u.UserName == model.UserName && u.Password == hashedPwd);
        
        if (user != null)
        {
            // 登入成功,處理 Cookie
            if (model.RememberMe)
            {
                var cookie = new HttpCookie("UserName", user.UserName)
                {
                    Expires = DateTime.Now.AddDays(30)
                };
                Response.Cookies.Add(cookie);
            }
            else
            {
                // 移除舊 Cookie
                if (Request.Cookies["UserName"] != null)
                {
                    var c = new HttpCookie("UserName") { Expires = DateTime.Now.AddDays(-1) };
                    Response.Cookies.Add(c);
                }
            }
            FormsAuthentication.SetAuthCookie(user.UserName, model.RememberMe);
            return RedirectToAction("Index", "Home");
        }
    }
    ViewBag.Error = "帳號或密碼錯誤,請重試";
    return View("Login");
}

關鍵點:

  • 使用 `ViewModel` 隔離資料庫實體與前端綁定模型
  • 密碼以 MD5 雜湊儲存(生產環境建議改用 BCrypt/Argon2)
  • Cookie 管理:記住我時寫入 30 天效期,取消時設定過期刪除

二、班級建立與圖片上傳整合

[HttpPost]
public ActionResult ToCreate(CreateClassViewModel model)
{
    using (var db = new AlumniBookContext())
    {
        // 檢查班級名稱唯一性
        if (db.Classes.Any(c => c.ClassName == model.ClassName))
        {
            ViewBag.Title = "錯誤";
            ViewBag.Message = "班級名稱已存在";
            return View("Error");
        }

        var newClass = new Class
        {
            ClassName = model.ClassName,
            SchoolName = model.SchoolName,
            CreatorId = User.Identity.Name,
            CreateTime = DateTime.Now
        };

        // 處理封面圖片上傳
        HttpPostedFileBase file = Request.Files[0];
        if (file != null && file.ContentLength > 0)
        {
            newClass.ClassCoverPath = FileHelper.SaveFile(file);
        }

        db.Classes.Add(newClass);
        db.SaveChanges();
        return RedirectToAction("Index", new { className = newClass.ClassName });
    }
}

三、AJAX 動態新增學校

前端 jQuery UI Dialog + AJAX

<div id="newSchoolBox" title="新增學校" style="display:none;">
    <input type="text" id="newSchoolName" placeholder="學校名稱" />
</div>

<script>
$("#createNewSchool").button().click(function() {
    $("#newSchoolBox").dialog("open");
});

$("#newSchoolBox").dialog({
    autoOpen: false,
    width: 400,
    height: 180,
    modal: true,
    buttons: {
        "確定": function() {
            $.ajax({
                type: "POST",
                url: "/Class/ToCreateNewSchool",
                data: { newSchoolName: $("#newSchoolName").val() },
                dataType: "json",
                success: function(data) {
                    if (data.result === true) {
                        alert("學校新增成功");
                        location.reload(); // 重新載入以更新下拉選單
                    } else if (data.result === false) {
                        alert("學校已存在,請直接選擇");
                        $("#newSchoolBox").dialog("close");
                    } else {
                        alert(data.result);
                    }
                }
            });
        },
        "取消": function() { $(this).dialog("close"); }
    }
});
</script>

後端處理

[HttpPost]
public JsonResult ToCreateNewSchool(string newSchoolName)
{
    using (var db = new AlumniBookContext())
    {
        if (db.Schools.Any(s => s.Name == newSchoolName))
        {
            return Json(new { result = false });
        }
        db.Schools.Add(new School { Name = newSchoolName });
        db.SaveChanges();
        return Json(new { result = true });
    }
}

四、Code First 遷移策略補充

專案中遇到模型變更需更新資料庫時,採用以下流程:

  1. 套件管理器主控台執行 `Add-Migration MigrationName`
  2. 檢查生成的遷移類別,必要時手動調整 `Up()`/`Down()` 方法
  3. 執行 `Update-Database` 套用至資料庫

遷移歷程會記錄在 `__MigrationHistory` 資料表,團隊協作時請將遷移檔案納入版控。

五、本篇小結

本篇完整示範從使用者認證、Cookie 管理、檔案上傳到 AJAX 非同步互動的核心模組實作。下一篇將介紹權限過濾器與 `web.config` 關鍵設定。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved