俗话说,磨刀不费砍柴工。为了更方便的进行项目管理,我们先将个人网站项目配置一下,满足以下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目录下,第一步先重构一下登录的界面:

 @model LoginViewModel

 @{
Layout = null;
ViewData["Title"] = "登录";
} <!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>@ViewData["Title"] - LanceL0t</title> @await Html.PartialAsync("_SiteCssPartial")
</head>
<body class="hold-transition login-page">
<div class="login-box">
<div class="login-box-body">
<p class="login-box-msg">欢迎,由此登录</p>
<form asp-route-returnurl="@ViewData["ReturnUrl"]" method="post">
<div asp-validation-summary="All" class="text-danger"></div>
<div class="form-group has-feedback">
<input asp-for="Email" class="form-control" placeholder="邮箱">
<span class="glyphicon glyphicon-envelope form-control-feedback"></span>
</div>
<div class="form-group has-feedback">
<input asp-for="Password" class="form-control" placeholder="密码">
<span class="glyphicon glyphicon-lock form-control-feedback"></span>
</div>
<div class="row">
<div class="col-xs-8">
<div class="checkbox icheck">
<label asp-for="RememberMe">
<input asp-for="RememberMe"> @Html.DisplayNameFor(m => m.RememberMe)
</label>
</div>
</div>
<div class="col-xs-4">
<button type="submit" class="btn btn-primary btn-block btn-flat">登录</button>
</div>
</div>
</form>
<div class="social-auth-links text-center">
<p>- 或者 -</p>
<a href="#" class="btn btn-block btn-social btn-facebook btn-flat">
<i class="fa fa-facebook"></i> Sign in using
Facebook
</a>
<a href="#" class="btn btn-block btn-social btn-google btn-flat">
<i class="fa fa-google-plus"></i> Sign in using
Google+
</a>
</div>
<a asp-action="ForgotPassword">忘记密码</a><br>
<a asp-action="Register" asp-route-returnurl="@ViewData["ReturnUrl"]" class="text-center">立即注册</a>
</div>
</div>
</body>
</html> @await Html.PartialAsync("_SiteScriptsPartial")
@await Html.PartialAsync("_ValidationScriptsPartial")

接着第二步,优化一下之前的新用户注册界面:

 @model RegisterViewModel

 @{
Layout = null;
ViewData["Title"] = "注册";
} <!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>@ViewData["Title"] - LanceL0t</title> @await Html.PartialAsync("_SiteCssPartial")
</head>
<body class="hold-transition login-page">
<div class="login-box">
<div class="login-box-body">
<p class="login-box-msg">欢迎,注册新用户</p>
<form asp-route-returnurl="@ViewData["ReturnUrl"]" method="post">
<div asp-validation-summary="All" class="text-danger"></div>
<div class="form-group has-feedback">
<input asp-for="Email" class="form-control" placeholder="请输入邮箱">
<span class="glyphicon glyphicon-envelope form-control-feedback"></span>
</div>
<div class="form-group has-feedback">
<input asp-for="Password" class="form-control" placeholder="请输入密码">
<span class="glyphicon glyphicon-lock form-control-feedback"></span> </div>
<div class="form-group has-feedback">
<input asp-for="ConfirmPassword" class="form-control" placeholder="请确认密码">
<span class="glyphicon glyphicon-lock form-control-feedback"></span>
</div>
<div class="row">
<div class="col-xs-8">
<div class="checkbox icheck">
<label asp-for="IsAgree">
<input asp-for="IsAgree"> 阅读并接受《<a href="#">用户协议</a>》
</label>
</div>
</div>
<div class="col-xs-4">
<button type="submit" class="btn btn-primary btn-block btn-flat">注册</button>
</div>
</div>
</form>
<div class="social-auth-links text-center">
<p>- 或者 -</p>
<a href="#" class="btn btn-block btn-social btn-facebook btn-flat">
<i class="fa fa-facebook"></i> Sign in using
Facebook
</a>
<a href="#" class="btn btn-block btn-social btn-google btn-flat">
<i class="fa fa-google-plus"></i> Sign in using
Google+
</a>
</div>
<a asp-controller="Account" asp-action="Login">已有账号</a><br>
</div>
</div>
</body>
</html> @await Html.PartialAsync("_SiteScriptsPartial")
@await Html.PartialAsync("_ValidationScriptsPartial")

这里的知识很简单,就不在祥述了,不过因为用的是.net core提供的identity用户管理和验证,有些个人遇到的问题,我还是列出来,以免再走弯路。

自定义的服务器端和客户单的验证

比如,新用户注册时,要保证用户已勾选“阅读并接受用户协议”。而MVC本身校验机制没有提供bool型必须为true的校验,这里我们自己实现一个服务器端属性的校验,需要继承

ValidationAttribute和IClientModelValidator:

 /// <summary>
/// 复选框必须选中验证
/// </summary>
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false, Inherited = false)]
public sealed class MustBeTrueAttribute : ValidationAttribute, IClientModelValidator
{
//服务器端验证
public override bool IsValid(object value)
{
return value != null && (bool)value;
} public void AddValidation(ClientModelValidationContext context)
{
MergeAttribute(context.Attributes, "data-val", "true");
var errorMessage = FormatErrorMessage(context.ModelMetadata.GetDisplayName());
MergeAttribute(context.Attributes, "data-val-mustbetrue", errorMessage);
} private bool MergeAttribute(
IDictionary<string, string> attributes,
string key,
string value)
{
if (attributes.ContainsKey(key))
{
return false;
}
attributes.Add(key, value);
return true;
}
}

再加上客户端的验证方法:

 <script>
//必须复选框勾选验证
$.validator.addMethod("mustbetrue",
function (value, element, parameters) {
return value === "true";
}); $.validator.unobtrusive.adapters.add("mustbetrue", [], function (options) {
options.rules.mustbetrue = {};
options.messages["mustbetrue"] = options.message;
});
</script>

identity的本地化

目前使用identity默认的错误描述是英文,这里我们需要显示成中文,所以新增一个IdentityExtensions类,继承IdentityErrorDescriber,重写错误描述

 public class IdentityExtensions : IdentityErrorDescriber
{
public override IdentityError PasswordRequiresNonAlphanumeric()
{
return new IdentityError
{
Code = nameof(PasswordRequiresNonAlphanumeric),
Description = "密码至少包含1位非数字字母的特殊字符"
};
} public override IdentityError PasswordRequiresDigit()
{
return new IdentityError
{
Code = nameof(PasswordRequiresDigit),
Description = "密码至少包含1位数字('0'-'9')"
};
} public override IdentityError PasswordRequiresLower()
{
return new IdentityError
{
Code = nameof(PasswordRequiresLower),
Description = "密码至少包含1位小写字符 ('a'-'z')"
};
} public override IdentityError PasswordRequiresUpper()
{
return new IdentityError
{
Code = nameof(PasswordRequiresUpper),
Description = "密码至少包含1位大写写字符 ('A'-'Z')"
};
}
}

重写中文错误描述后,我们还得在Startup.cs文件中的服务配置中注册:

 public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection"))); services.AddIdentity<ApplicationUser, IdentityRole>()
.AddEntityFrameworkStores<ApplicationDbContext>()
.AddDefaultTokenProviders()
.AddErrorDescriber<IdentityExtensions>(); // Add application services.
services.AddTransient<IEmailSender, EmailSender>(); services.AddMvc();
}

登录和注册新用户没有问题了,再来改造一下登录后主页的布局,把_Layout布局视图分割成顶部区域、左侧导航菜单、内容区域、底部区域、右侧侧边栏,并用部分视图分别渲染:

 <!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>@ViewData["Title"] - LanceL0t</title> @await Html.PartialAsync("_SiteCssPartial")
</head>
<body class="hold-transition skin-blue sidebar-mini">
<div class="wrapper">
<!-- 顶部区域 -->
@await Html.PartialAsync("_LayoutHeaderPartial")
<!-- 导航栏 -->
@await Html.PartialAsync("_LayoutNavbarPartial")
<!-- 内容区域 -->
<div class="content-wrapper">
<section class="content-header">
<h1>
Dashboard
<small>Version 2.0</small>
</h1>
<ol class="breadcrumb">
<li><a href="#"><i class="fa fa-dashboard"></i> 主页</a></li>
<li class="active">Dashboard</li>
</ol>
</section>
<section class="content">
@RenderBody()
</section>
</div>
<!-- 底部区域 -->
@await Html.PartialAsync("_LayoutFooterPartial")
<!-- 侧边栏 -->
@await Html.PartialAsync("_LayoutSidebarPartial")
</div> @await Html.PartialAsync("_SiteScriptsPartial")
@RenderSection("Scripts", required: false)
</body>
</html>

这样,我们登录和注册功能大体完成了,我们看下效果:

ASP.NET Core 一步步搭建个人网站(2)_一键部署和用户注册登录的更多相关文章

  1. ASP.NET Core 一步步搭建个人网站(持续更新中~~~)

    摘要 ASP.NET Core2.0发布有一阵子了,这是.NET 开源跨平台的一个重大里程碑, 也意味着比1.0版本要更加成熟.目前.net core具有开源.跨平台.灵活部署.模块化架构等等特性,吸 ...

  2. ASP.NET Core 一步步搭建个人网站(1)_环境搭建

    ASP.NET Core2.0发布有一阵子了,这是.NET 开源跨平台的一个重大里程碑, 也意味着比1.0版本要更加成熟.目前.net core具有开源.跨平台.灵活部署.模块化架构等等特性,吸引着一 ...

  3. ASP.NET Core 一步步搭建个人网站(7)_Linux系统移植

    摘要 考虑我们为什么要选择.NET Core? 因为它面向的是高性能服务器开发,抛却了 AspNet 的臃肿组件,非常轻量,加上微软的跨平台战略,对 Docker 的亲和性,对于开发人员也非常友好,所 ...

  4. ASP.NET Core 一步步搭建个人网站(4)_主页和登录验证

    上章节我们已经定制好动态配置的菜单,用户登录网站的第一步就是进入首页内容,那我们先搭建一下我们的首页内容.想着自己的网站内容主要是个人博客类型,所以,首页就展示博主本人的一些基本信息吧,哈哈.当然,做 ...

  5. ASP.NET Core 一步步搭建个人网站(3)_菜单管理

    上一章,我们实现了用户的注册和登录,登录之后展示的是我们的主页,页面的左侧是多级的导航菜单,定位并展示用户需要访问的不同页面.目前导航菜单是写死的,考虑以后菜单管理的便捷性,我们这节实现下可视化配置菜 ...

  6. ASP.NET Core 一步步搭建个人网站(5)_Api模拟和网站分析

    前言 经过前面几章,我们的网站已经最基本的功能,接下来就是继续拓展其他的功能,这期一起来实现一个该网站流量分析的工具,统计出这个网站每天用户相关数据,不仅要满足了我们对流量统计数字的基本要求,并且用更 ...

  7. ASP.NET Core 一步步搭建个人网站(6)_单页模式和优化

    前言 HI,有段时间没有更新了,主要因为第一年前事情比较多,有些事得忙着张罗下:第二呢,对个人网站进行了一次大范围的优化,主要是申请的云服务器资源有限,1m的网络带宽,带上图片展示的话,打开网站的平均 ...

  8. Asp.net Core + Log4net + ELK 搭建日志中心

    原文:Asp.net Core + Log4net + ELK 搭建日志中心 Docker中一键安装ELK 对于这种工具类的东西,第一步就直接到docker的hub中查找了,很幸运,不仅有Elasti ...

  9. 项目开发中的一些注意事项以及技巧总结 基于Repository模式设计项目架构—你可以参考的项目架构设计 Asp.Net Core中使用RSA加密 EF Core中的多对多映射如何实现? asp.net core下的如何给网站做安全设置 获取服务端https证书 Js异常捕获

    项目开发中的一些注意事项以及技巧总结   1.jquery采用ajax向后端请求时,MVC框架并不能返回View的数据,也就是一般我们使用View().PartialView()等,只能返回json以 ...

随机推荐

  1. SpringMVC Spring MyBatis整合配置文件

    1.spring管理SqlSessionFactory.mapper 1)在classpath下创建mybatis/sqlMapConfig.xml <?xml version="1. ...

  2. LeetCode 90. Subsets II (子集合之二)

    Given a collection of integers that might contain duplicates, nums, return all possible subsets. Not ...

  3. 汇总一些知名的 JavaScript 开发开源项目

    汇总一些知名的 JavaScript 开发开源项目   转自:CTOLib , www.ctolib.com/topics-107352.html ggraph - 图形可视化的凌乱数据 这是一个建立 ...

  4. Java 数据结构与算法分析学习

    由于之前面试android的时候考到了很多关于java的知识,所以这次重温数据结构知识就打算用java来学习,毕竟android是以java为基础的,而且我现在学习的j2ee架构也是以java为基础的 ...

  5. struts2(二)之配置文件详解与结果视图

    前言 前面介绍了struts2的一个程序的大概流程,还有它的配置文件. 一.struts.xml文件元素详解 1.1.package元素 1)作用 在struts2的配置文件中引入了面向对象思想,使用 ...

  6. 用ajax的同步请求解决登陆注册需要根据服务器返回数据判断是否能提交的问题

    最近在写www.doubilaile.com的登陆注册.需要用ajax请求服务器判断用户名是否存在,用户名和密码是否匹配,进而提交数据.碰到的问题是异步请求都能成功返回数据,但是该数据不能作为紧接着的 ...

  7. Red and Black

    Problem Description There is a rectangular room, covered with square tiles. Each tile is colored eit ...

  8. css基础语法一(选择器与css导入方式)

    页面中,所有的CSS代码,需要写入到<style></style>标签中.style标签的type属性应该选择text/css,但是type属性可以省略. CSS修改页面中的所 ...

  9. setup 命令中防火墙配置选项无法打开

    故障提示 1.1 如何让setup 命令中防火墙配置生效 1.1.1 CentOS系统找不到setup命令工具的解决方法 yum -y install setuptool #安装setup命令工具 y ...

  10. jquery getScript动态加载JS方法改进详解[转载]

    转载自http://www.jb51.net/article/31973.htm 有许多朋友需要使用getScript方法动态加载JS,本文将详细介绍此功能的实现方法     $.getScript( ...