在 ASP.NET MVC4 中创建角色并将用户归入角色
新增一個 ASP.NET MVC4 網際網路應用程式,打開 AccountController 並看看註冊的 action
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public ActionResult Register(RegisterModel model)
{
if (ModelState.IsValid)
{
// 嘗試註冊使用者
try
{
WebSecurity.CreateUserAndAccount(model.UserName, model.Password);
WebSecurity.Login(model.UserName, model.Password);
return RedirectToAction("Index", "Home");
}
catch (MembershipCreateUserException e)
{
ModelState.AddModelError("", ErrorCodeToString(e.StatusCode));
}
}
// 如果執行到這裡,發生某項失敗,則重新顯示表單
return View(model);
}
這裡少了對新的使用者指派腳色設定,在 WebSecurity.CreateUserAndAccount() 後面加入
if (!Roles.RoleExists("user"))
{
Roles.CreateRole("user");
}
Roles.AddUserToRole(model.UserName, "user");
之後可以再 Action 上面加入:
[Authorize(Roles = "admin")]
或是在程式或是 View 裡面判斷
if (Roles.IsUserInRole("admin")){}
取的目前使用者的角色(陣列)
string[] roles = Roles.GetRolesForUser();
判斷角色
bool isAdmin = Roles.IsUserInRole("admin");
可选阅读
當在別的 Controller 裡面的 Action 加入[Authorize(Roles = "admin")] 會出現錯誤 :
建立連接至 SQL Server 時,發生網路相關或執行個體特定的錯誤。找不到或無法存取伺服器。
確認執行個名稱是否正確,以及 SQL Server 是否設定為允許遠端連線。 (provider: SQL Network
Interfaces, error: 26 - 搜尋指定的伺服器/執行個體時發生錯誤)
因為使用 SimpleMembership 的資料庫還未初始化,可以在 Controller 上加入
[InitializeSimpleMembership] 即可(預設只有 AccountController 有加入該屬性);
或是想要在應用程式啟動時就初始化可以在 Global.asax 加入
WebSecurity.InitializeDatabaseConnection(
"DefaultConnection",
"UserProfile",
"UserId",
"UserName",
autoCreateTables: true
);
如果指示發生錯誤在:
// 請確定一個應用程式啟動只起始一次 ASP.NET Simple Membership
LazyInitializer.EnsureInitialized(ref _initializer, ref _isInitialized, ref _initializerLock);
頁面顯示錯誤訊息為:"WebSecurity.InitializeDatabaseConnection" 方法只能呼叫一次。
因為重複初始化,因此將該檔案(Filters/InitializeSimpleMembershipAttribute.cs)內的
WebSecurity.InitializeDatabaseConnection()方法移除。
設定 User 與 Roles 的第一筆種子(seed)資料, 客製化 User 的屬性
(在 MVC4 上使用 SimpleRoleProvider, Entity Framework 5 CodeFirst)
只有網際網路應用程式(Internet Application)有 SimpleRoleProvider, 所以用這份版建立一個專案
即使是隱含存在的, 但是還是顯式的將 providers 加到
裡面, 這樣當我們為了要
migrations 而在套件管理器主控台(Package Manager Console)上執行 update-database 命令時, 我
們可以使用本機的"Roles"API
現在來客製化 User 資料表, 加入 Mobile 欄位到 UserProfile 實體類別
[Table("UserProfile")]
public class UserProfile
{
[Key]
[DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
public int UserId { get; set; }
public string UserName { get; set; }
[Display(Name = "電話")]
public string Mobile { get; set; }
}
在套件管理器主控台(Package Manager Console)啟用 EF5 CodeFirst Migrations
PM> enable-Migrations
執行完後跑出 Migrations 資料夾
在 Migrations/Configuration.cs 修改部分資料, 可執行種入我預備想要的 Roles 和任何 User
internal
DbMigrationsConfiguration
Configuration
sealed
class
:
{
public Configuration()
{
AutomaticMigrationsEnabled = true;
}
protected override void Seed(MvcApplication4.Models.UsersContext context)
{
WebSecurity.InitializeDatabaseConnection(
"DefaultConnection",
"UserProfile",
"UserId",
"UserName", autoCreateTables: true);
if (!Roles.RoleExists("Administrator"))
Roles.CreateRole("Administrator");
if (!WebSecurity.UserExists("ian100"))
WebSecurity.CreateUserAndAccount(
"ian100",
"pw0000",
new { Mobile = "07888999" });
if (!Roles.GetRolesForUser("ian100").Contains("Administrator"))
Roles.AddUsersToRoles(new[] { "ian100" }, new[] { "Administrator" });
}
}
注意到 WebSecurity.InitializeDatabaseConnection()發法被引用, 這方法是告訴 SimpleMembership
哪個資料表我們要使用於 Users, 哪個欄位是用於 UserId 和 UserName, 接著要在註冊頁面加入
新增的客製化欄位
在套件管理器主控台(Package Manager Console)執行
PM> update-database –verbose
(使用-verbose 可以在 Package Manager Console 看到生成的 SQL 碼)
執行最後可以看到正在執行 Seed 方法。
(如果沒有在 Web.Confing 加入 providers 設定, 則會在套件管理器主控台顯示錯誤 : 尚未啟用
角色管理員功能。)
此時 Users 被新增, Roles 被提供
Ian100 被加入到且關聯到 Administrator 角色
現在執行最後一件事, 修改註冊相關頁面與類別(加入新增的欄位 Mobile)
Register View (Register.cshtml):
@Html.LabelFor(m => m.Mobile)
@Html.TextBoxFor(m => m.Mobile)
Register model (AccountModel.cs):
public class RegisterModel
{
// … 省略
[Required]
[DataType(DataType.PhoneNumber)]
[Display(Name = "Mobile")]
public string Mobile { get; set; }
}
Register Action (AccountController.cs):
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public ActionResult Register(RegisterModel model)
{
if (ModelState.IsValid)
{
// Attempt to register the user
try
{
WebSecurity.CreateUserAndAccount(
model.UserName,
model.Password,
new { Mobile = model.Mobile },
false);
WebSecurity.Login(model.UserName, model.Password);
return RedirectToAction("Index", "Home");
}
catch (MembershipCreateUserException e)
{
ModelState.AddModelError("", ErrorCodeToString(e.StatusCode));
}
}
// If we got this far, something failed, redisplay form
return View(model);
}
ASP.NET MVC 使用 AJAX 方式撈取資料
1.可能要撈取的條件不只是一筆資料, 例如使用兩部電影 ID 去撈取各自的資料, 因此在 jQuery
組成 JSON 字串
js
// 撈出頁面資料放到陣列
var $video = $('.video');
var videoIdArr = [];
$video.each(function (index, element) {
videoIdArr.push($(element).attr('data-videoid'));
});
videoIdArr = $.unique(videoIdArr);
var url = '@Url.Action("GetVideos", "Video")';
// 使用 JSON.stringify 將 JavaScript 值轉換成以 JSON 表示的字串
var data = { videoIds: JSON.stringify(videoIdArr) };
// data 為 service 端 return 的 JSON 格式之內容
$.post(url, data, function (data) {
$(data).each(function (index, element) {
$('.video_' + element.VideoID).text(element.Name);
});
});
.
GetVideos()
// MVC 的 Controller Action :
[HttpPost]
public ActionResult GetVideos(string videoIds)
{
var db = new HappyMovieEntities();
var Serializer = new JavaScriptSerializer();
// 將指定的 JSON 字串轉換成 T 型別的物件。
// (此範例是將 videoIds 轉換成 List)
var _videoIds = Serializer.Deserialize>(videoIds);
var query = db.Video.Where(x => _videoIds.Contains(x.VideoID)).Select(x => new
{
x.VideoID,
x.Picture,
x.Name,
ReleaseYear = x.ReleaseDate.Value.Year,
});
return Json(query);
}
* 備註 :
因為 Action 裡面有解序列化的程式, 所以接收的資料一定要是 Json 格式的字串
如果要 client 端發送的只有一筆可以這樣寫:
var vid = '@Model.VideoId';
var data = { videoIds: JSON.stringify([vid]) };
如果不傳入資料:
var data = { videoIds: undefined };
但是 server 端要加入判斷是否接收到的是 null。