2020年5月30日,AddTrust External CA Root 过期,虽然不影响客户端浏览器访问网站,但服务器端调用接口(file_get_contents)会出现问题,原因是证书链中根证书过期(必须使用检测工具检查服务端的证书链,而不是查看客户端浏览器上的证书信息,因为客户端浏览器上看到的的根证书是客户端系统上的根证书,是随着系统自动更新的)。
这里,Windows Server 的 IIS 与 CentOS 中的 nginx 又有所区别,咱们分开来讲:
如何更新 Windows Server 的 IIS 中的网站的根证书?
Windows Server 本身相当于一个客户端,会自动更新根证书,只不过 IIS 中的网站证书未同步更新。
打开 IIS,进入对应网站的“绑定”界面,重新绑定即可生效。简单的方法是简单修改主机名,确定,再改回原主机名,确定。
如何更新 CentOS 的 nginx 中的网站的根证书?
nginx 中使用的域名证书(pem 文件),即 conf 文件中设置的 ssl_certificate 路径对应的证书文件,是包含根证书信息的:
因此保留第一段域名证书信息,用新的根证书信息替换掉除第一段的其它内容即可。

前端引用 jquery、jquery-ui(或 jquery.ui.widget),以及 jquery.fileupload.js
$('#xxx').fileupload({
url: 'FileUpload',
add: function (e, data) {
console.log('add', data);
data.submit();
},
success: function (response, status) {
console.log('success', response);
toastr.success('上传成功!文件名:' + response);
},
error: function (error) {
console.log('error', error);
toastr.error("上传失败:" + error.responseText);
}
});
服务端接收文件:
[HttpPost]
public ActionResult FileUpload([FromForm(Name = "files[]")] IFormFile file)
{
try
{
return Ok(file.FileName);
}
catch(Exception ex)
{
return BadRequest(ex.Message);
}
}
此处 Name = "files[]" 值是由 <input type="file" name="这里定的" />
如果 input 没有指定 name,那么一般为 file[],或者在 Chrome 的开发者工具中,切换到 Network 标签页,选中 post 的目标请求,在 Headers 的 Form Data 中可以看到 name="xxx"。

ASP.NET MVC 使用 Authorize 过滤器验证用户登录。Authorize 过滤器首先运行在任何其它过滤器或动作方法之前,主要用来做登录验证或者权限验证。
示例:使用 Authorize 过滤器实现简单的用户登录验证。
1、创建登录控制器 LoginController
/// <summary>
/// 登录控制器
/// </summary>
[AllowAnonymous]
public class LoginController : Controller
{
/// <summary>
/// 登录页面
/// </summary>
public ActionResult Index()
{
return View();
}
/// <summary>
/// 登录
/// </summary>
[HttpPost]
public ActionResult Login(string loginName, string loginPwd)
{
if (loginName == "admin" && loginPwd == "123456")
{
// 登录成功
Session["LoginName"] = loginName;
return RedirectToAction("Index", "Home");
}
else
{
// 登录失败
return RedirectToAction("Index", "Login");
}
}
/// <summary>
/// 注销
/// </summary>
public ActionResult Logout()
{
Session.Abandon();
return RedirectToAction("Index", "Login");
}
}
注意:在登录控制器 LoginController 上添加 AllowAnonymous 特性,该特性用于标记在授权期间要跳过 AuthorizeAttribute 的控制器和操作。
2、创建登录页面
@{
ViewBag.Title = "登录页面";
Layout = null;
}
<h2>登录页面</h2>
<form action='@Url.Action("Login","Login")' id="form1" method="post">
用户:<input type="text" name="loginName" /><br />
密码:<input type="password" name="loginPwd" /><br />
<input type="submit" value="登录">
</form>
效果图:
3、创建主页控制器 LoginController
public class HomeController : Controller
{
public ActionResult Index()
{
// 获取当前登录用户
string loginName = Session["LoginName"].ToString();
ViewBag.Message = "当前登录用户:" + loginName;
return View();
}
}
4、创建主页页面
@{
ViewBag.Title = "Index";
Layout = null;
}
<h2>Index</h2>
<h3>@ViewBag.Message</h3>
<a href="@Url.Action("Logout","Login")">注销</a>
效果图:
5、创建授权过滤器 LoginAuthorizeAttribute 类
创建 Filter 目录,在该目录下创建授权过滤器 LoginAuthorizeAttribute 类,继承 AuthorizeAttribute。
using System.Web.Mvc;
namespace MvcApp.Filter
{
/// <summary>
/// 授权过滤器
/// </summary>
public class LoginAuthorizeAttribute : AuthorizeAttribute
{
public override void OnAuthorization(AuthorizationContext filterContext)
{
// 判断是否跳过授权过滤器
if (filterContext.ActionDescriptor.IsDefined(typeof(AllowAnonymousAttribute), true)
|| filterContext.ActionDescriptor.ControllerDescriptor.IsDefined(typeof(AllowAnonymousAttribute), true))
{
return;
}
// 判断登录情况
if (filterContext.HttpContext.Session["LoginName"] == null || filterContext.HttpContext.Session["LoginName"].ToString()=="")
{
//HttpContext.Current.Response.Write("认证不通过");
//HttpContext.Current.Response.End();
filterContext.Result = new RedirectResult("/Login/Index");
}
}
}
}
通常 Authorize 过滤器也是在全局过滤器上面的,在 App_Start 目录下的 FilterConfig 类的 RegisterGlobalFilters 方法中添加:
using System.Web;
using System.Web.Mvc;
using MvcApp.Filter;
namespace MvcApp
{
public class FilterConfig
{
public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
filters.Add(new HandleErrorAttribute());
// 添加全局授权过滤器
filters.Add(new LoginAuthorizeAttribute());
}
}
}
Global.asax 下的代码:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Optimization;
using System.Web.Routing;
namespace MvcApp
{
public class MvcApplication : System.Web.HttpApplication
{
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
}
}
}
xoyozo:暂时没有按区域(Area)来统一配置的方法,建议加在 Controller 上。https://stackoverflow.com/questions/2319157/how-can-we-set-authorization-for-a-whole-area-in-asp-net-mvc

在升级 kernel 后若无法启动系统,网站无法打开,SSH 无法连接,无法 ping 通。
使用 VNC 进入操作界面:
一种界面是可选择次新的内核版本:
应该能正常启动。
另一种界面提示:
Give root password for maintenance
输入密码后可启动。
阿里云工程师的建议:
1、当前默认是以最新内核启动的,由于新版内核文件存在异常无法正常运行,在手动选择低内核版本启动后,可以先更改下默认内核引导顺序,配置默认使用低版本内核运行,避免重启再次出现问题。 修改内核引导顺序 https://help.aliyun.com/knowledge_detail/41463.html 2、升级内核本身属于高危操作,建议操作前先做好快照备份,同时更新时可以参考下文档方案 避免Linux实例升级内核系统无法启动的方法 https://help.aliyun.com/knowledge_detail/59360.html

// 控制组件
map.addControl(new T.Control.MapType());
// 切换到“地图”视图
map.setMapType(TMAP_NORMAL_MAP);
// 切换到“卫星”视图
map.setMapType(TMAP_SATELLITE_MAP);
// 切换到“卫星混合”视图
map.setMapType(TMAP_HYBRID_MAP);

form 提交 checkbox
<form method="get" asp-action="Index">
<input type="checkbox" name="a" value="1" /> 一
<input type="checkbox" name="a" value="2" /> 二
</form>
get 方式的 url 中会出现多个相同名称的参数
/abc?a=1&a=2
C# 使用数组类型接收参数
public IActionResult Index(string[] a)
{
}

Unify Template 提供三种文件上传样式(如上图),“Plain File Input”和“File input”使用传统 <form /> 提交,“Advanced File input”调用组件实现。
ASP.NET Core 实现传统 <form /> 提交(以“Plain File Input”为例):
<form class="g-brd-around g-brd-gray-light-v4 g-pa-30 g-mb-30" id="form_avatar_upload" asp-action="AvatarUpload" enctype="multipart/form-data" method="post">
<!-- Plain File Input -->
<div class="form-group mb-0">
<p>Plain File Input</p>
<label class="u-file-attach-v2 g-color-gray-dark-v5 mb-0">
<input id="fileAttachment" name="Avatar" type="file" onchange="form_avatar_upload.submit()">
<i class="icon-cloud-upload g-font-size-16 g-pos-rel g-top-2 g-mr-5"></i>
<span class="js-value">Attach file</span>
</label>
</div>
<!-- End Plain File Input -->
</form>
public class AvatarUploadModel
{
public IFormFile Avatar { get; set; }
}
[HttpPost]
public IActionResult AvatarUpload(AvatarUploadModel Item)
{
return RedirectToAction("");
}
ASP.NET Core 调用 HSFileAttachment 组件实现:
<div class="form-group mb-20">
<label class="g-mb-10">上传作品文件(包)</label>
<input class="js-file-attachment_project" type="file" name="" id="file_project">
<div style="display: none;" id="file_project_tip">
<div class="u-file-attach-v3 g-mb-15" id="file_project_tip_content">
<h3 class="g-font-size-16 g-color-gray-dark-v2 mb-0">拖曳文件到此处或者 <span class="g-color-primary">浏览你的电脑</span></h3>
<p class="g-font-size-14 g-color-gray-light-v2 mb-0">
如果您的作品包含多个文件,请添加到压缩包再上传
</p>
<p class="g-font-size-14 g-color-gray-light-v2 mb-0">
支持的文件格式:
<code>zip</code>
<code>rar</code>
<code>7z</code>
<code>psd</code>
<code>ai</code>
<code>cdr</code>
<code>jpg</code>
<code>png</code>
<code>gif</code>
<code>tif</code>
<code>webp</code>
</p>
<p class="g-font-size-14 g-color-gray-light-v2 mb-0">文件(包)的大小不能超过 <span>@options.Value.MaxSizeOfSigleFile_MB</span> MB</p>
</div>
</div>
<small class="form-control-feedback">请上传作品文件</small>
</div>
<!-- JS Implementing Plugins -->
<script src="//cdn.***.com/unify/unify-v2.6.2/html/assets/vendor/jquery.filer/js/jquery.filer.min.js"></script>
<!-- JS Unify -->
<script src="//cdn.***.com/unify/unify-v2.6.2/html/assets/js/helpers/hs.focus-state.js"></script>
<script src="//cdn.***.com/unify/unify-v2.6.2/html/assets/js/components/hs.file-attachement.js"></script>
<!-- JS Plugins Init. -->
<script>
$(document).on('ready', function () {
// initialization of forms
$.HSCore.components.HSFileAttachment.init('.js-file-attachment_project', {
changeInput: $('#file_project_tip').html(),
uploadFile: {
url: url_UploadFile,
data: { type: 'project' },
success: function (data, element) {
console.log(data);
if (!data.success) {
var parent = element.find(".u-progress-bar-v1").parent();
element.find(".u-progress-bar-v1").fadeOut("slow", function () {
$("<div class=\"text-error g-px-10\"><i class=\"fa fa-minus-circle\"></i> Error</div>").hide().appendTo(parent).fadeIn("slow");
});
alert(data.err_msg);
} else {
var parent = element.find(".u-progress-bar-v1").parent();
element.find(".u-progress-bar-v1").fadeOut("slow", function () {
$("<div class=\"text-success g-px-10\"><i class=\"fa fa-check-circle\"></i> Success</div>").hide().appendTo(parent).fadeIn("slow");
});
$('#file_project_tip_content').slideUp();
upload_project_id = data.id;
}
}
}
});
$.HSCore.helpers.HSFocusState.init();
});
</script>
public IActionResult UploadFile([FromForm(Name = "[]")]IFormFile file, string type)
{
return Ok(new { id = 1 });
}

---------------------------
Microsoft Visual Studio
---------------------------
无法加载“*.edmx”: 无法将类型为“MySql.Data.MySqlClient.MySqlProviderServices”的对象强制转换为类型“System.Data.Common.DbProviderServices”。
---------------------------
解决方法:
检查 Web.config <providers> 标签是否为重复的 MySql.Data.MySqlClient。
本例中发现一个为 Version=8.0.19,一个为 Version=8.0.19.0,实践保留 Version=8.0.19.0 的 <provider> 即可。

显示一行,省略号
white-space: nowrap;
text-overflow: ellipsis;
overflow: hidden;
word-break: break-all;
显示两行,省略号
text-overflow: -o-ellipsis-lastline;
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-line-clamp: 2;
line-clamp: 2;
-webkit-box-orient: vertical;
同理可改为多行。