博客 (260)

之前已经介绍了百度编辑器在 ASP.NET 环境下的配置,本文继续补充改进其将图片等附件上传到阿里云 OSS。

首先从阿里云控制台下载相关 SDK,并阅读相关的 API 文档。链接:https://promotion.aliyun.com/ntms/act/ossdoclist.html


改造上传代码


打开文件 UploadHandler.cs,在 Process() 方法中找到:

File.WriteAllBytes(localPath, uploadFileBytes);

在其下方插入代码:

client.PutObject(bucketName, "upload/ueditor/" + savePath, localPath);

实现图标按钮上传和 HTML5 拖放上传。

PutObject() 的第 2 个参数是 OSS 中的图片路径,第 3 个参数是图片在网站目录下的磁盘路径。


打开文件 CrawlerHandler.cs,在 Fetch() 方法中找到:

File.WriteAllBytes(savePath, bytes);

在其下方插入代码:

client.PutObject(bucketName, "upload/ueditor/" + ServerUrl, savePath);

实现粘贴板图片上传。

同样注意两个参数变量。


修改路径前缀


上传成功后,编辑器会拼装路径到 HTML 代码中,这个前缀是在 config.json 文件中配置的,具体找到以 UrlPrefix 结尾的属性,如 imageUrlPrefix,进行相应的修改即可:

"imageUrlPrefix": "//oss.xoyozo.net/upload/ueditor/", /* 图片访问路径前缀 */

路径以“//”开头能更好地兼容 https。

xoyozo 7 年前
9,279

传统的 LIKE 模糊查询(前置百分号)无法利用索引,特别是多个关键词 OR,或在多个字段中 LIKE,更是效率低下。本文研究对文章进行分词以提高检索的准确度和查询效率。


根据自己的编程语言选择一款合适的中文分词组件,我在 ASP.NET 平台下选择了 jieba.NET。


设想的步骤:

  1. 分别对文章标题、标签、正文进行分词,保存到一张分词表上。该表把“文章 ID”和“词语”设为联合主键,用 3 个字段记录该词语分别在标题、标签、正文中出现的次数,另外还可以按需要添加文章分类 ID、文章创建时间等字段。

  2. 当用户输入关键词进行检索时,先将关键词分词,在分词表中用 in 语法查询到所有相关的记录;

  3. 使用 group by 语法对查询结果按文章 ID 分组;

  4. 关键在排序上,理想的排序是:

    a. 先按搜索关键词中不同词语的出现量排序,即:若搜索关键词分词后是 3 个词语,那么全部包含这 3 个词的文章优先,只匹配其中 2 个词语的其次;

    b. 再按搜索关键词在文中累计出现的次数排序(考虑权重),即:我们先假定标题和标签的分词权重为 5(意思是一个分词在标题中出现 1 次相当于在正文中出现 5 次),那么累加每个分词在标题、标签、正文的权重次数,得分高的优先;

    c. 再进一步考虑文章的发布时间,即将文章的发布时间距离最早一篇文章的发布时间(或一个较早的固定日期)相隔的天数,乘以一个系数加入到权重中,这个系数按不同文章分类(场景)不同,比如新闻类的大一点,情感类的小一点)。乘以系数时一篇文章只加权一次,不要加权到每个分词。

    d. 根据需求还可以加入文章热度(阅读数)的权重。


根据上述逻辑对一个有 18 万篇文章的内容管理系统进行改造,循环所有文章进行分词统计,得到一张包含 5 千万条记录的分词表(系统中部分文章只有标题、标签和外链,没有正文,否则更多)。

由于查询中包含 in、group by、count、sum、运算等,再若分类是无级限的,即文章分类 ID 也是 in 查询,然后分页,即使创建索引,效率也只能呵呵了。


简化:

不对正文进行分词;

不按权重进行排序;


那么分词表的记录数降到 250 万条,同样用 in 查询分词,先按搜索关键词中不同词语的出现量排序,再按发布时间排序,分页后获得一页的文章 ID 集合,再去文章表中 in 获取详细信息(注意保持一页中的排序)。

添加相关索引后,查询一个包含 3 个分词的关键词仅需十几毫秒。因为 in 的内容比较离散,所以索引的利用率比较高。



xoyozo 7 年前
6,887

前言:

ChatGPT 给了 3 条建议:

  1. 在应用程序中正确释放数据库连接。确保在使用完数据库连接后,将其关闭并将其返回到连接池中。您可以使用 using 语句来确保连接在使用完毕后被正确释放。

  2. 调整连接池的大小。默认情况下,连接池的最大大小为 100。如果您的应用程序需要更多的连接,则可以增加连接池的大小。您可以在连接字符串中设置 Max Pool Size 属性来调整连接池的大小。

  3. 调整连接池的超时时间。默认情况下,连接池中的连接在 30 秒钟内未使用时将被关闭。如果您的应用程序需要更长的连接时间,则可以增加连接池的超时时间。您可以在连接字符串中设置 Connection Lifetime 属性来调整连接池的超时时间。

亲测有效,尤其是第 3 条,原因是 Connection Lifetime 的默认值是 0,即没有超时限制。

—— 2023.5

一般地,我们使用 EF 连接数据库前会先初始化一个数据库上下文:

dbEntities db = new dbEntities();

虽然 ASP.NET 会在查询完毕后自动关闭该连接,但是在什么情况下回收等都是不确定的,所以会导致 MySQL 中出现很多 Sleep 的连接(执行命令 SHOW FULL PROCESSLIST 可见),占用数据库的连接数,除非主动调用 Dispose():

db.Dispose();

官方建议的写法是使用 using 语法:

using (dbEntities db = new dbEntities())
{
}

using 会自动调用 Dispose()。这样对减少连接数是很有效的,但官方提示为了提高下一次连接的速度,并不会完全关闭所有连接。

C# 8 建议写法:

using dbEntities db = new dbEntities();

在实际项目中(该项目有 500+处数据库连接)测试结果,在不执行 Dispose() 时稳定为 140 个左右连接数,使用 using 或 Dispose() 后稳定变为 40 个左右。


如果不小心在 using 外部或 Dispose() 后再次对该上下文执行查询操作会出现异常:

无法完成该操作,因为 DbContext 已释放。

或

此 ObjectContext 实例已释放,不可再用于需要连接的操作。

所以要避免出现这种情况。这里还有一种另类的解决方法(不建议),根据上下文的特性,只要在 using 内查询一次(譬如视图中需要用到的导航属性,即外键关联的表),就可以在外部使用这个属性。


(建议)在 ASP.NET MVC 或 Web API 项目中,如果一个控制器中仅在 Action 外部定义一个 DbContext,那么,只要重写该控制器的 Dispose() 方法即可:

private dbEntities db = new dbEntities();

protected override void Dispose(bool disposing)
{
    if (disposing)
    {
        db.Dispose();
    }
    base.Dispose(disposing);
}

上下文使用 private 修饰即可。


参考:SQL Server 连接池 (ADO.NET)

xoyozo 7 年前
7,663
  • 使用会话状态服务器(StateServer)管理会话状态,可防止网站发布后会话丢失,参 ASP.NET 网站每次发布后丢失 Session 怎么办?

  • 查询数据库时,尽量使用 using 包裹 db 上下文,或者 db.Dispose(),或重写 Dispose(),可以减少数据库连接数(Sleep),参 如何减少 ASP.NET 连接 MySQL 时的 Sleep 查询(即时关闭数据库上下文)

  • 发布时使用预编译功能,参 彻底告别 .NET 网站首次访问速度慢的问题

  • 清理日志不要这样写(先读取再删除):

    db.dt_log.RemoveRange(db.dt_log.Where(c => c.time < dt).OrderBy(c => c.time).Take(count));

    SQL Server 应该:

    db.Database.ExecuteSqlCommand($"DELETE FROM {nameof(db.dt_log)} WHERE {nameof(l.id)} IN (SELECT TOP {count} {nameof(l.id)} FROM {nameof(db.dt_log)} WHERE {nameof(l.time)} < '{dt.ToString("yyyy-MM-dd HH:mm:ss")}' ORDER BY {nameof(l.time)})");

    注意时间可能需要使用 convert 函数转化,给 time 字段添加索引。

    MySQL 应该:

    db.Database.ExecuteSqlCommand($"DELETE FROM {nameof(db.dt_log)} WHERE {nameof(l.time)} < '{dt.ToString("yyyy-MM-dd HH:mm:ss")}' ORDER BY {nameof(l.time)} LIMIT {count}");

    给 time 字段添加索引。

  • 未完待续

xoyozo 7 年前
2,941

无法向会话状态服务器发出会话状态请求。请确保 ASP.NET State Service (ASP.NET 状态服务)已启动,并且客户端端口与服务器端口相同。如果服务器位于远程计算机上,请检查 HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\aspnet_state\Parameters\AllowRemoteConnection 的值,确保服务器接受远程请求。如果服务器位于本地计算机上,并且上面提到的注册表值不存在或者设置为 0,则状态服务器连接字符串必须使用“localhost”或“127.0.0.1”作为服务器名称。

无法连接 StateService 的原因有很多种,我遇到的情况是:

VS 中使用 IISExpress 调试项目,系统没有安装 IIS,

ASP.NET 状态服务是开启状态,

没有对系统作任何修改,无缘无故无法连接。


修改注册表、配置防火墙无效(我没有用到远程连接),

执行 aspnet_regiis -i -enables 无效,

重装 .NET Framework 4.8 Developer Pack 无效,

差点就重装系统了。


最终的解决方法是:

在“启用或关闭 Windows 功能”中勾选安装:Internet Information Services -> 万维网服务 -> 应用程序开发功能 -> ASP.NET 4.8

重启系统。

image.png

xoyozo 7 年前
5,686

场景:每天带笔记本电脑上班,公司使用固定 IP 上网,家里网络的网段又跟公司不一样。


方法 1:两个网络环境分别使用有线连接和无线连接(鉴于笔记本无线网卡不支持 5G(802.11ac),或者有其它需求必须都使用有线连接的不适用此方法)。

方法 2:修改家里路由器的局域网 IP 地址,使其网段与公司相同(虽然仅需要一次修改,但部分路由器不允许修改局域网 IP 地址);

方法 3:使用第三方软件一键切换(有安全隐患,且可能导致电脑网络设置出现错误);

方法 4(推荐):设置电脑网络连接同时使用两个 IP,具体方法如下:


打开“以太网 属性”,双击“Internet 协议版本 4 (TCP/IPv4)”,配置其中一个网络环境的 IP 地址和网关(例如我在公司上网的 IP 是 192.168.1.5,网关是 192.168.1.1)

image.png

点击“高级”,在 IP 地址栏添加另一个网络的 IP(如 192.168.31.5),在“默认网关”处添加这个网络的网关(如 192.168.31.1)

image.png

这样设置后,不管到公司还是回到家,只要网线一插就能上网,不需要每天更换 IP 地址设置了。

image.png

(图中显示了两个网络名称)

xoyozo 7 年前
9,158

Visual Studio 2019 已于本月早些时候正式发布,但 MySQL for Visual Studio 却迟迟未更新,目前的 1.2.8 版本只支持到 VS2017。表现在 VS2019 上会发生:

  • 在“服务器资源管理器”中添加连接时,或在新建“ADO.NET 实体数据模型”时,无法看到数据源“MySQL Database (MySQL Data Provider)”

  • 在实体数据模型设计器(Entity Data Model Designer)中执行“从数据库更新数据模型”时出现错误:尝试从数据库进行更新时,遇到类型为“System.ArgumentException”的异常。异常消息为:“无法将运行时连接字符串转换为设计时等效项。没有为提供程序“MySql.Data.MySqlClient”安装为设计目的(DDEX 提供程序)启用 Visual Studio 以便与数据库进行通信所需的库。 

幸运的是 VS2019 可以与低版本 VS 共存,使用 ASP.NET 连接 MySQL 的开发者们要再等一等才能用上 VS2019 了。

这几天 MySQL 不断有产品更新,相信 MySQL for Visual Studio 2019 也会在不久的将来面世,本站将第一时间更新下载地址。


2019.8.30 Jose Ramirez(来自 MySQL 的 Windows 团队):MySQL for Visual Studio 的当前版本不支持 Visual Studio 2019。正在努力提供支持,但根据公司政策,我无法披露日期或对何时可用提供任何承诺。查看

2019.9.26 MySQL for Visual Studio 迟迟未更新,但是 VS2019 更新到最新版本(v16.3)已经一切正常了。


MySQL for Visual Studio 的 Repair 功能是鸡肋,有问题的话,Remove 后重新安装才能解决。

xoyozo 7 年前
8,966

这是一篇可能解决困扰了 .NET 程序猿多年的文章!

首先,使用 Visual Studio 2019 创建一个 ASP.NET WEB 应用程序,直接选用了 MVC 模板。

直接发布项目,默认的设置如下图:

image.png

对于小型项目,按默认设置发布基本可满足正常运行,首次运行打开第一个页面基本在 5~6 秒(视服务器配置),其它页面的首次打开也基本在 1~2 秒完成,非首次瞬间打开。

一旦项目功能变得复杂,文件增多,会导致发布后首次运行打开第一个页面 30 秒以上,其它页面的首次打开 10 秒左右,非首次瞬间打开。

这是因为项目在发布时没有进行预编译,而是在用户访问网页时动态编译,一旦应用程序池回收,或项目文件改动,都会重新编译,再次经历缓慢的“第一次”,这是不能忍的。

于是咱们来研究一下“预编译”。

在发布页面勾选“在发布期间预编译”,这时发布会在“输出”窗口显示正在执行编译命令(编译时间会比较长):

image.png

该选项对发布后的文件结构和内容影响不大,因此对首次执行效率的提升也不大,重要的在后面。

在“高级预编译设置”窗口中:

image.png

我们针对预编译选项和合并选项分别做测试。

不勾选“允许更新预编译站点”,会致 bin 目录中生成许多 .compiled 文件,而所有 .cshtml 文件的内容都是:

这是预编译工具生成的标记文件,不应删除!

如果是 Web From 网站,.aspx/.ashx 等文件内容同上。

尝试打开网站页面,你会发现,除了项目启动后的第一个页面仍然需要 1~2 秒(无 EF),其余每个页面的首次都是瞬间打开的(EF 的首次慢不在本文讨论范围)。这让我对预编译有一种相见恨晚的感觉!

这里偷偷地告诉你,把 Views 目录删掉也不影响网页正常打开哦~为什么不让删,咱也不敢问,咱也不敢删。

目的达到了,有一些后遗症需要解决,比如 bin 目录内杂乱无章。

选“不合并。为每个页面和控件创建单独的程序集”,结果是 bin 多出许多 App_Web_*.dll 文件。

选“将所有输出合并到单个程序集”,填写程序集名称。这时会发现“输出”窗口执行了命令:

image.png

如果程序集名称跟已有名称冲突,会发生错误:

合并程序集时出错: ILMerge.Merge: The target assembly '******' lists itself as an external reference.

查看 bin 目录,.compiled 文件还在,但 App_Web_*.dll 合并成了一个程序集。FTP 的“不合并”也是把所有 App_Web_*.dll 上传一遍,所以不存在相对于“合并”的增量发布优势。

是不是勾了“视为库组件删除(AppCode.compiled 文件)”.compiled 文件就会不见?意外之外,情理之中,bin 没有什么变化。

继续选择“将各个文件夹输出合并到其自己的程序集”,呃,bin 中文件数不降反增。

最后选择“将所有页和控件输出合并到单个程序集”,同样程序集名称不能冲突。结局令人失望,bin 中仍然一大堆 .compiled 和 App_Web_*.dll。


整理成表格:

1
允许更新预编译站点

aspnet_compiler.exe -v / -p \Source -u \TempBuildDir 

重复发布后 bin 目录文件数:不会增多(页面不进行预编译)

2

不允许更新预编译站点,不合并

aspnet_compiler.exe -v / -p \Source \TempBuildDir 

重复发布后 bin 目录文件数:.compiled 不会增多,App_Web_*.dll 增多

3

不允许更新预编译站点,不合并。为每个页面和控件创建单独的程序集

aspnet_compiler.exe -v / -p \Source -c -fixednames \TempBuildDir 

重复发布后 bin 目录文件数:不会增多(编译后的文件名固定,FTP 方式的部分 App_Web_*.dll 文件可能实现增量上传)

4

不允许更新预编译站点,将所有输出合并到单个程序集,不勾选“视为库组件”

aspnet_compiler.exe -v / -p \Source -c \TempBuildDir 

aspnet_merge.exe \TempBuildDir -o 程序集名称 -copyattrs AssemblyInfo.dll -a

重复发布后 bin 目录文件数:不会增多(.compiled 固定名称,App_Web_*.dll 合并为一个)

5

不允许更新预编译站点,将所有输出合并到单个程序集,勾选“视为库组件”

aspnet_compiler.exe -v / -p \Source \TempBuildDir 

aspnet_merge.exe \TempBuildDir -o 程序集名称 -copyattrs AssemblyInfo.dll -a -r 

重复发布后 bin 目录文件数:不会增多(.compiled 固定名称,App_Web_*.dll 合并为一个)

6

不允许更新预编译站点,将每个文件夹输出合并到其自己的程序集,前缀

aspnet_compiler.exe -v / -p \Source -c \TempBuildDir 

aspnet_merge.exe \TempBuildDir -prefix 前缀 -copyattrs AssemblyInfo.dll -a  

重复发布后 bin 目录文件数:.compiled 不会增多,App_Web_*.dll 增多

7

不允许更新预编译站点,将所有页和控件输出合并到单个程序集

aspnet_compiler.exe -v / -p \Source -c \TempBuildDir 

aspnet_merge.exe \TempBuildDir -w 程序集名称 -copyattrs AssemblyInfo.dll -a  

重复发布后 bin 目录文件数:.compiled 不会增多,App_Web_*.dll 增多

bin 目录下,页面的程序集文件(App_Web_*.dll)增多的原因是编译后的文件名不固定,发布到会导致残留许多无用的程序集文件。

相比较,如果第 3 种能实现 FTP 稳定的增量上传的话是比较完美的(还有一个缺点是:如果页面有删除,目标 bin 内对应该页面的 .compiled 和 .dll 不会删除,这跟“允许更新预编译站点”是一个情况),那么第 4 种 或第 5 种也是不错的选择(同样有缺点:执行合并比较慢)。

测试一个有 300 个页面的项目,compiler 用时约 2 分钟,merge 用时约 5 分钟,发布用时约 4 分钟。

这里有个槽点,执行预编译和合并是佛系的,CPU 和磁盘使用率永远保持在最低水平。

所以如果是要经常修改的项目,那么建议选择“不合并”的第 3 种发布方式:

微信图片_20190715160035.png

“视为库组件(删除 AppCode.compiled 文件)”:移除主代码程序集(App_Code 文件夹中的代码)的 .compiled 文件。 如果应用程序包含对主代码程序集的显式类型引用,则不要使用此选项。


补充:

  • 不允许更新预编译站点发布后,因为前端页面没有内容,因此无法单独修改发布(单独发布一个页面后,在访问时不会生效!),只能全站发布,耗时较长;bin 目录有变动将导致使用 InProc 方式存储的 Session 丢失。

  • 预编译的另一个优点是可以检查 .aspx / .cshtml 页面 C# 部分的错误(特别是命名空间和路径引用)。

  • 改为预编译发布后,可以将服务器上残留的 .master / .ascx / .asax 删除,但不能删除 .aspx / .ashx /.config 等。

  • VS 发布到 FTP 经常会遗漏一些页面文件,不合并时会遗漏独立文件,合并后也会遗漏合并后的 .dll 的文件,合并的好处就是方便检查是否完全上传发布。

  • 慎选“在发布前删除所有现有文件”!一旦勾选发布,世界就清静了,所有网友上传的图片附件以及网站运行产生的其它文件,消失得无影无踪。不管发布到文件系统还是发布到 FTP 都一样。当然,如果是先发布到文件系统,再通过 FileZilla 等 FTP 软件上传到服务器的,建议勾选此项。

  • .NET Core 应用程序部署:https://docs.microsoft.com/zh-cn/dotnet/core/deploying/index

  • 由于上传文件时 bin 目录文件较多,理论上 bin 目录内的文件有任何改动都会重启应用池,而且 VS 是单线程上传的,导致期间网站访问缓慢,服务器 CPU 升高,我的做法是:发布到文件系统,再使用专用 FTP 工具上传,上传用时约半分钟(如果大小不同或源文件较新则覆盖文件)。还嫌慢?那就打包上传,解压覆盖。

  • 关于本文研究对象的官方解释:高级预编译设置对话框

  • 出现“未能加载文件或程序集“***”或它的某一个依赖项。试图加载格式不正确的程序。”的问题时,先用改用 Debug 方式发布会报详细错误,一般是 .aspx 等客户端页面有 C# 语法问题,注意提示报错的是 /obj/ 目录下的克隆文件,应更改原文件。排除错误后关闭所有页面,再使用 Release 方式发布。

  • 2025年9月补充:因预编译发布后生成的文件时间都是系统最新时间,通过 FTP 上传到服务器时都会覆盖文件,可能导致杀毒软件进程 MsMpEng.exe 占用 CPU 过高。尝试选择不进行预编译,即取消“发布期间预编译”前的勾,这样发布的的文件时间都是文件本身的最后修改时间,重复发布不会更新这个时间,而且 bin 目录中也不会出现大量编译后的文件。这样通过 FTP 上传时只要设置“大小不同且文件较新则覆盖”就不会重复上传文件了,杀毒软件的工作量就能大大减少。缺点就是本文开头说的,每个页面的第一次打开会比较慢,而是非常慢。所以仍然需要勾选“发布期间预编译”,同时勾上“允许更新预编译站点”,这样 bin 目录中不会发现很多文件(合并不合并都一样),打开每个页面的第一次耗时也能在接受范围内。

xoyozo 7 年前
14,412

前提:

若需获取用户 unionid,则小程序必须已绑定到微信开放平台。


  1. 小程序调用 wx.login(),将 code 发送到开发者服务器

  2. 开发者服务器请求微信接口 code2Session,获得 session_key、openid,有机会获得 unionid(参 UnionID 机制说明)。因此无需任何用户授权即可获取 openid

  3. 访问须要已获取用户信息的页面时,可通过小程序端使用 button + getUserInfo 的方式请求用户授权

  4. 访问须要已获取手机号码的页面时,可通过小程序端使用 button + getPhoneNumber 的方式请求用户授权

  5. code2session、getUserInfo、getPhoneNumber 等接口返回数据存入数据库 dt_weapp_user

  6. 服务端的任何接口均返回口令状态包(含自定义会话口令等信息),小程序端应保存于 storage

  7. 请求 getUserInfo 后应判断 detail.errMsg 是否为 getUserInfo:ok,请求 getPhoneNumber 后应判断 detail.errMsg 是否为 getPhoneNumber:ok

  8. 授权窗口的弹出情况参此文

  9. 口令状态包是用来传递到客户端用来标识用户唯一凭证的,包含字段:会话口令(自定义用户凭证)、会话口令有效时间(秒)、是否已获取 unionid 或昵称(视业务需求)、是否已获取手机号码、uid(可选),以及其他用来标识业务身份字段。服务端可根据会话口令从数据库中获取该用户的所有已知信息。

    一般情况下,当已获取手机号码时,uid 必有值,否则,uid 必为空。因此 uid 不是必须传递到客户端的。

    通过 code2Session 获得的 session_key、以及 openid、unionid、手机号码等机密信息不允许包含在口令状态包中并缓存在客户端,客户端需要用到手机号码时单独调用接口获取。

  10. 若业务不要求以手机号码作为用户唯一标识,那么口令状态包中不需要包含是否已获取手机号码,仅 uid 即可。在客户端访问须要业务用户登录的页面时,也仅判断 uid 有值即可。


流程图:


微信小程序授权登录获取 unionid、用户信息流程.png


为更好地适应 2017.7.19 发布的《小程序内用户帐号登录规范调整和优化建议》,开发者服务器提供的所有业务逻辑接口的返回值中都应包含口令状态包,约定有以下相关的返回值和处理动作(返回值按个人喜好来定):

口令状态接口返回ASP.NET Web API 语句处理动作
access_token 空或失效401 状态码return Unauthorized();login() + code2Session,获取 openid,生成 access_token
access_token 有效,但未获取 uniond 或用户信息401 状态码,http 头 WWW-Authenticate 中标注 getUserInforeturn Unauthorized(new AuthenticationHeaderValue("getUserInfo"));getUserInfo()
access_token 有效,但未获取手机号码(即未找到业务用户)401 状态码,http 头 WWW-Authenticate 中标注 getPhoneNumberreturn Unauthorized(new AuthenticationHeaderValue("getPhoneNumber"));getPhoneNumber()
xoyozo 7 年前
13,517

HTTP Error 502.5 - ANCM Out-Of-Process Startup Failure

Common causes of this issue:

  • The application process failed to start

  • The application process started but then stopped

  • The application process started but failed to listen on the configured port

Troubleshooting steps:

  • Check the system event log for error messages

  • Enable logging the application process' stdout messages

  • Attach a debugger to the application process and inspect

For more information visit: https://go.microsoft.com/fwlink/?LinkID=808681


发现装错了东西,服务器上应该安装 dotnet-hosting-*.*.*-win.exe,而非 dotnet-runtime-*.*.*-win-x64.exe

xoyozo 8 年前
6,973