俗話說,磨刀不費砍柴工。爲了更方便的進行項目管理,咱們先將我的網站項目配置一下,知足如下2個目標:html
有了以上的配置,咱們能夠不用每次拉取和同步咱們的程序到Github中,也不用每次在本地發佈,拷貝服務器,咱們只用在VS2017中簡單的一鍵同步到Github或網站服務器。這樣咱們的開發效率有了很大的提升,也方便線上驗證咱們的程序代碼。前端
選擇 工具-->擴展和更新,搜索GitHub,安裝GitHub的VS插件git
安裝完插件,打開視圖-->團隊資源管理器,咱們能夠看到Git插件菜單。經過菜單咱們能夠新建Git存儲庫,能夠提交修改的代碼,並一鍵同步提交後的代碼到本身的GitHub項目中。bootstrap
再打開GitHub,能夠看咱們的代碼已經同步了,是否是很方便?瀏覽器
要VS支持FTP發佈,首先要將網站服務器配置成FTP服務器。安全
Server2008添加新的角色,選中文件服務並安裝新角色:前端框架
再次選中已安裝的IIS服務,增長FTP服務器相關的角色:服務器
接着,在IIS網站右鍵選擇「添加FTP站點」,選擇FTP文件物理路徑和添加站點名稱:mvc
端口默認21,不用選擇SSL證書,身份驗證這裏選擇基本驗證(爲了必定的安全性,不要勾選匿名),受權訪問裏,指定administrator才能訪問FTP站點,並具備讀取和寫入的權限;app
完成後,咱們建好的FTP就自動啓動了,這時瀏覽器中輸入ftp://localhost,輸入用戶名和密碼,就能夠訪問對應的文件目錄了。固然,咱們外網仍是沒法訪問,爲何呢?相信你們看過上一篇,應該知道是防火牆的緣由,咱們按照上一篇的配置,增長FTP 21端口的容許入站規則,這樣咱們外網就經過FTP訪問網站發佈目錄。
配置完外網服務器,咱們來配置一下本地VS2017,右鍵項目-->發佈,選擇FTP發佈,選項配置以下:
這樣咱們就已經配置好本地一鍵發佈站點到遠程服務器了。之後直接點發布按鈕,就能夠看到自動將生成的發佈文件,同步到網站服務器:
準備工做作完,瀏覽器輸入網站服務器IP,能夠看到能夠正常訪問,可是.net core mvc幫咱們自動生成的界面,不必定符合咱們的需求,那仍是本身找一個前端的UI框架,替換一下既有界面。這裏我選擇的是 AdminLTE ,這是一個基於 bootstrap 的輕量級後臺模板,相關的資料你們能夠去官網研究一下。
咱們把下載的文件解壓縮到wwwroot/lib目錄下,第一步先重構一下登陸的界面:
1 @model LoginViewModel 2 3 @{ 4 Layout = null; 5 ViewData["Title"] = "登陸"; 6 } 7 8 <!DOCTYPE html> 9 <html> 10 <head> 11 <meta charset="utf-8" /> 12 <meta name="viewport" content="width=device-width, initial-scale=1.0" /> 13 <title>@ViewData["Title"] - LanceL0t</title> 14 15 @await Html.PartialAsync("_SiteCssPartial") 16 </head> 17 <body class="hold-transition login-page"> 18 <div class="login-box"> 19 <div class="login-box-body"> 20 <p class="login-box-msg">歡迎,由此登陸</p> 21 <form asp-route-returnurl="@ViewData["ReturnUrl"]" method="post"> 22 <div asp-validation-summary="All" class="text-danger"></div> 23 <div class="form-group has-feedback"> 24 <input asp-for="Email" class="form-control" placeholder="郵箱"> 25 <span class="glyphicon glyphicon-envelope form-control-feedback"></span> 26 </div> 27 <div class="form-group has-feedback"> 28 <input asp-for="Password" class="form-control" placeholder="密碼"> 29 <span class="glyphicon glyphicon-lock form-control-feedback"></span> 30 </div> 31 <div class="row"> 32 <div class="col-xs-8"> 33 <div class="checkbox icheck"> 34 <label asp-for="RememberMe"> 35 <input asp-for="RememberMe"> @Html.DisplayNameFor(m => m.RememberMe) 36 </label> 37 </div> 38 </div> 39 <div class="col-xs-4"> 40 <button type="submit" class="btn btn-primary btn-block btn-flat">登陸</button> 41 </div> 42 </div> 43 </form> 44 <div class="social-auth-links text-center"> 45 <p>- 或者 -</p> 46 <a href="#" class="btn btn-block btn-social btn-facebook btn-flat"> 47 <i class="fa fa-facebook"></i> Sign in using 48 Facebook 49 </a> 50 <a href="#" class="btn btn-block btn-social btn-google btn-flat"> 51 <i class="fa fa-google-plus"></i> Sign in using 52 Google+ 53 </a> 54 </div> 55 <a asp-action="ForgotPassword">忘記密碼</a><br> 56 <a asp-action="Register" asp-route-returnurl="@ViewData["ReturnUrl"]" class="text-center">當即註冊</a> 57 </div> 58 </div> 59 </body> 60 </html> 61 62 @await Html.PartialAsync("_SiteScriptsPartial") 63 @await Html.PartialAsync("_ValidationScriptsPartial")
接着第二步,優化一下以前的新用戶註冊界面:
1 @model RegisterViewModel 2 3 @{ 4 Layout = null; 5 ViewData["Title"] = "註冊"; 6 } 7 8 <!DOCTYPE html> 9 <html> 10 <head> 11 <meta charset="utf-8" /> 12 <meta name="viewport" content="width=device-width, initial-scale=1.0" /> 13 <title>@ViewData["Title"] - LanceL0t</title> 14 15 @await Html.PartialAsync("_SiteCssPartial") 16 </head> 17 <body class="hold-transition login-page"> 18 <div class="login-box"> 19 <div class="login-box-body"> 20 <p class="login-box-msg">歡迎,註冊新用戶</p> 21 <form asp-route-returnurl="@ViewData["ReturnUrl"]" method="post"> 22 <div asp-validation-summary="All" class="text-danger"></div> 23 <div class="form-group has-feedback"> 24 <input asp-for="Email" class="form-control" placeholder="請輸入郵箱"> 25 <span class="glyphicon glyphicon-envelope form-control-feedback"></span> 26 </div> 27 <div class="form-group has-feedback"> 28 <input asp-for="Password" class="form-control" placeholder="請輸入密碼"> 29 <span class="glyphicon glyphicon-lock form-control-feedback"></span> 30 31 </div> 32 <div class="form-group has-feedback"> 33 <input asp-for="ConfirmPassword" class="form-control" placeholder="請確認密碼"> 34 <span class="glyphicon glyphicon-lock form-control-feedback"></span> 35 </div> 36 <div class="row"> 37 <div class="col-xs-8"> 38 <div class="checkbox icheck"> 39 <label asp-for="IsAgree"> 40 <input asp-for="IsAgree"> 閱讀並接受《<a href="#">用戶協議</a>》 41 </label> 42 </div> 43 </div> 44 <div class="col-xs-4"> 45 <button type="submit" class="btn btn-primary btn-block btn-flat">註冊</button> 46 </div> 47 </div> 48 </form> 49 <div class="social-auth-links text-center"> 50 <p>- 或者 -</p> 51 <a href="#" class="btn btn-block btn-social btn-facebook btn-flat"> 52 <i class="fa fa-facebook"></i> Sign in using 53 Facebook 54 </a> 55 <a href="#" class="btn btn-block btn-social btn-google btn-flat"> 56 <i class="fa fa-google-plus"></i> Sign in using 57 Google+ 58 </a> 59 </div> 60 <a asp-controller="Account" asp-action="Login">已有帳號</a><br> 61 </div> 62 </div> 63 </body> 64 </html> 65 66 @await Html.PartialAsync("_SiteScriptsPartial") 67 @await Html.PartialAsync("_ValidationScriptsPartial")
這裏的知識很簡單,就不在祥述了,不過由於用的是.net core提供的identity用戶管理和驗證,有些我的遇到的問題,我仍是列出來,以避免再走彎路。
好比,新用戶註冊時,要保證用戶已勾選「閱讀並接受用戶協議」。而MVC自己校驗機制沒有提供bool型必須爲true的校驗,這裏咱們本身實現一個服務器端屬性的校驗,須要繼承
ValidationAttribute和IClientModelValidator:
1 /// <summary> 2 /// 複選框必須選中驗證 3 /// </summary> 4 [AttributeUsage(AttributeTargets.Property, AllowMultiple = false, Inherited = false)] 5 public sealed class MustBeTrueAttribute : ValidationAttribute, IClientModelValidator 6 { 7 //服務器端驗證 8 public override bool IsValid(object value) 9 { 10 return value != null && (bool)value; 11 } 12 13 public void AddValidation(ClientModelValidationContext context) 14 { 15 MergeAttribute(context.Attributes, "data-val", "true"); 16 var errorMessage = FormatErrorMessage(context.ModelMetadata.GetDisplayName()); 17 MergeAttribute(context.Attributes, "data-val-mustbetrue", errorMessage); 18 } 19 20 private bool MergeAttribute( 21 IDictionary<string, string> attributes, 22 string key, 23 string value) 24 { 25 if (attributes.ContainsKey(key)) 26 { 27 return false; 28 } 29 attributes.Add(key, value); 30 return true; 31 } 32 }
再加上客戶端的驗證方法:
1 <script> 2 //必須複選框勾選驗證 3 $.validator.addMethod("mustbetrue", 4 function (value, element, parameters) { 5 return value === "true"; 6 }); 7 8 $.validator.unobtrusive.adapters.add("mustbetrue", [], function (options) { 9 options.rules.mustbetrue = {}; 10 options.messages["mustbetrue"] = options.message; 11 }); 12 </script>
目前使用identity默認的錯誤描述是英文,這裏咱們須要顯示成中文,因此新增一個IdentityExtensions類,繼承IdentityErrorDescriber,重寫錯誤描述
1 public class IdentityExtensions : IdentityErrorDescriber 2 { 3 public override IdentityError PasswordRequiresNonAlphanumeric() 4 { 5 return new IdentityError 6 { 7 Code = nameof(PasswordRequiresNonAlphanumeric), 8 Description = "密碼至少包含1位非數字字母的特殊字符" 9 }; 10 } 11 12 public override IdentityError PasswordRequiresDigit() 13 { 14 return new IdentityError 15 { 16 Code = nameof(PasswordRequiresDigit), 17 Description = "密碼至少包含1位數字('0'-'9')" 18 }; 19 } 20 21 public override IdentityError PasswordRequiresLower() 22 { 23 return new IdentityError 24 { 25 Code = nameof(PasswordRequiresLower), 26 Description = "密碼至少包含1位小寫字符 ('a'-'z')" 27 }; 28 } 29 30 public override IdentityError PasswordRequiresUpper() 31 { 32 return new IdentityError 33 { 34 Code = nameof(PasswordRequiresUpper), 35 Description = "密碼至少包含1位大寫寫字符 ('A'-'Z')" 36 }; 37 } 38 }
重寫中文錯誤描述後,咱們還得在Startup.cs文件中的服務配置中註冊:
1 public void ConfigureServices(IServiceCollection services) 2 { 3 services.AddDbContext<ApplicationDbContext>(options => 4 options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection"))); 5 6 services.AddIdentity<ApplicationUser, IdentityRole>() 7 .AddEntityFrameworkStores<ApplicationDbContext>() 8 .AddDefaultTokenProviders() 9 .AddErrorDescriber<IdentityExtensions>(); 10 11 // Add application services. 12 services.AddTransient<IEmailSender, EmailSender>(); 13 14 services.AddMvc(); 15 }
登陸和註冊新用戶沒有問題了,再來改造一下登陸後主頁的佈局,把_Layout佈局視圖分割成頂部區域、左側導航菜單、內容區域、底部區域、右側側邊欄,並用部分視圖分別渲染:
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <meta charset="utf-8" /> 5 <meta name="viewport" content="width=device-width, initial-scale=1.0" /> 6 <title>@ViewData["Title"] - LanceL0t</title> 7 8 @await Html.PartialAsync("_SiteCssPartial") 9 </head> 10 <body class="hold-transition skin-blue sidebar-mini"> 11 <div class="wrapper"> 12 <!-- 頂部區域 --> 13 @await Html.PartialAsync("_LayoutHeaderPartial") 14 <!-- 導航欄 --> 15 @await Html.PartialAsync("_LayoutNavbarPartial") 16 <!-- 內容區域 --> 17 <div class="content-wrapper"> 18 <section class="content-header"> 19 <h1> 20 Dashboard 21 <small>Version 2.0</small> 22 </h1> 23 <ol class="breadcrumb"> 24 <li><a href="#"><i class="fa fa-dashboard"></i> 主頁</a></li> 25 <li class="active">Dashboard</li> 26 </ol> 27 </section> 28 <section class="content"> 29 @RenderBody() 30 </section> 31 </div> 32 <!-- 底部區域 --> 33 @await Html.PartialAsync("_LayoutFooterPartial") 34 <!-- 側邊欄 --> 35 @await Html.PartialAsync("_LayoutSidebarPartial") 36 </div> 37 38 @await Html.PartialAsync("_SiteScriptsPartial") 39 @RenderSection("Scripts", required: false) 40 </body> 41 </html>
這樣,咱們登陸和註冊功能大致完成了,咱們看下效果: