ASP.NET Core 一步步搭建個人網站(2)_一鍵部署和用戶注冊登錄


俗話說,磨刀不費砍柴工。為了更方便的進行項目管理,我們先將個人網站項目配置一下,滿足以下2個目標:

  • VS2017中支持Git存儲庫,綁定Github項目,實現本地VS程序與線上Github一鍵代碼提交和同步;
  • 搭建服務器FTP站點,VS2017中配置一鍵部署網站文件到服務器;

有了以上的配置,我們可以不用每次拉取和同步我們的程序到Github中,也不用每次在本地發布,拷貝服務器,我們只用在VS2017中簡單的一鍵同步到Github或網站服務器。這樣我們的開發效率有了很大的提高,也方便線上驗證我們的程序代碼。

VS2017支持Github

選擇 工具-->擴展和更新,搜索GitHub,安裝GitHub的VS插件

安裝完插件,打開視圖-->團隊資源管理器,我們可以看到Git插件菜單。通過菜單我們可以新建Git存儲庫,可以提交修改的代碼,並一鍵同步提交后的代碼到自己的GitHub項目中。

        

再打開GitHub,可以看我們的代碼已經同步了,是不是很方便?

VS2017支持FTP遠程發布

要VS支持FTP發布,首先要將網站服務器配置成FTP服務器。

Server2008添加新的角色,選中文件服務並安裝新角色:

再次選中已安裝的IIS服務,增加FTP服務器相關的角色:

接着,在IIS網站右鍵選擇“添加FTP站點”,選擇FTP文件物理路徑和添加站點名稱:

端口默認21,不用選擇SSL證書,身份驗證這里選擇基本驗證(為了一定的安全性,不要勾選匿名),授權訪問里,指定administrator才能訪問FTP站點,並具有讀取和寫入的權限;

完成后,我們建好的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的本地化

目前使用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>

這樣,我們登錄和注冊功能大體完成了,我們看下效果:


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM