解决方案写在前面:更新Visual Studio及相关组件,本人版本自17.8.0更新至17.11.4

缘起于公司的一个业务接口,在有一些信息需要在应用内嵌的webview中展示,信息不少,涉及的前端技术不复杂,但是拼字符串太罗嗦,所以想到了添加一个Razor页面,所以,常规逻辑,在服务上注册'''AddRazorPages''',构建后使用映射方法'''MapRazorPages''',然后调试。这次调试没有问题,页面也能正常显示。因为是微信的小程序,并且是在手机上演示,网站地址要在配置的业务域名上,所以基本写完了页面,第一时间就把应用部署到了iis的测试端口上。然后问题就发生了————配置的首页返回404,访问业务所在的url也返回404。

因为几乎是第一次正式用Razor,所以尝试了检查url,补全index甚至补全.cshtml,都是一样的404。再后来检查了应用的日志,发现除了页面访问的w3cLog记录,没有任何其他的记录,但页面使用了Ef core 对SQl Server 的查询,而查询的日志项并没有在日志过滤规则之外,所以基本确定了页面并没有被执行。

本地调试可以执行,部署后不能执行,第一时间就是想到的环境不一致,Development和Production,对应开发环境和生产环境。在Visual Studio使用调试时ASPNETCORE_ENVIRONMENT这个变量要被设置成"Development"的,但直接执行,该环境变量没有定义,应用默认的状态是Production。

在Debug文件夹运行可执行文件,结果发现依然404。注意到Pages 文件夹没有,第一时间考虑有两种可能:一、项目设置错误,没有在生成时把文件复制到文件夹;二、考虑cshtml文件被编译到dll中了(实际上就是这样的,但当时的我并不能确认)。

先考虑第一种可能,这个实操不难,只需要在项目配置中添加

    <Content Update="Pages\*.cshtml">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>

再生成一次,第一遍不配置ASPNETCORE_ENVIRONMENT变量,结果是相关页面依旧404,第二遍,配置ASPNETCORE_ENVIRONMENT为Development,终于,页面正常展示了。但奇怪的是,进一步发布->运行时,依然需要将ASPNETCORE_ENVIRONMENT变量设置为Development??这不应该!(此时的我依然没觉得复制Pages/*.cshtml有什么问题,就是觉得配置被搞出问题了)设置为开发环境显然不合理,很多配置都是针对开发环境的,SwaggerUI也会展示,总不能在发布到服务器前再改一次代码吧?

不过,由于第二天要演示,而且由于微信小程序的各种**门槛,不得不部署,这时候IIS又闹情绪,照网上的办法,又是配置,又是配置的,运行起来的服务始终是生产环境,总不能改系统的环境变量,毕竟上面的陈年老项目认到这个变量指不定激动的抽过去了也不一定。不过,办法总比困难多,Environment.SetEnvironmentVariable方法解决这个问题,其实也是一开始就想到它了,但为了不动现有的代码,一直没舍得用,遵循下老祖宗的开闭原则嘛。但第二天的演示更要紧,不得不做一个违背老祖宗的决定~

演示结束,立马回到这个问题,首先想到的就是新建一个项目。这下可不得了了,不论改环境变量还是复制文件,都成了404了。明明就是默认的Razor Pages模板,去MSDN上给的代码也都一样,但就是跑不起来。无头苍蝇一样搜了各种办法,但都没有针对我的问题,寻找文心一言和chatGPT的解答,也都是不合我意。

不过,最终在各种关键词搜索中,找到了杨中科老师在百家号上的一篇回答《如何让asp.net core mvc发布时候不编译cshtml视图》,虽然和我的想法相反,但这总算是相关的了。文章中介绍了让cshtml文件在运行时编译的方法,感觉能找到点苗头,于是按他说的一试,页面不再是404了。

或许到这,也就该结束了,毕竟用这方法不在考虑修改环境变量,也不用修改其他代码,问题算是圆满的解决了。。。吗?当然可以不再进一步探索,但是这篇反方向的解决方案让我有了一个新的灵感————:

文章满篇都在提要在运行时编译要做的额外配置,那要是不做呢?默认情况下它到底以何种方式运行。杨中科老师的文章中提到的两个属性标签已经让答案呼之欲出了:MvcRazorCompileOnPublish被置为了false,RazorCompileOnBuild同样被置为了false,也就是说,默认情况下,生成时和发布时Razor文件可能是被编译的。至于编译的形式,有可能就是jsp那样!(至于为什么先知道的jsp,学校给教的,大概在2020~2021年,哈哈:),现在估计依然在教。也是完成作业的过程中偶尔接触到的jsp文件编译后的反编译代码)

要探究编译后的文件,自然是少不了ILSpy,以往用它来分析过线上代码的问题,所以想到反编译就想到了它。对发布后的dll(没有使用运行时编译配置)进行分析,发现相关的命名空间下只有Model文件的编译,页面内容相关的代码一点没有。

但现在,在当前的环境下,我也是穷途末路了,新项目都这样,就算又有配置问题,找出来也不异于大海捞针,况且如此的绝望,在第一天下班后的尝试中就已经发生在了自己的电脑上。只有用本办法了————虚拟机。在一台Windows10环境的虚拟机上,我又重新搭建了一套Visual Studio,创建了新的Razor模板,运行。但这次,成功了,用了各种姿势都是。我不知道该说是意料之中还是意料之外。但总算是有成功的样本给我研究了。

拿到虚拟机上发布后的dll,丢到ILSpy中,这次能清楚的看到被编译到dll当中的页面内容,也不出意外,整体形式和jsp差不多。

但为什么?这一遭让我知道了cshtml在不特殊设置的情况下确实要被编译到dll中去的,相应的,把cshtml复制到构建文件夹并无必要。我一开始考虑的配置问题似乎就不存在……

剩下的就是对项目无尽的蹂躏了。当我在一次次的生成、调试或是发布时,我注意到一条警告:

CS9057 分析器程序集“C:\Program Files\dotnet\sdk\8.0.201\Sdks\Microsoft.NET.Sdk.Razor\source-generators\Microsoft.CodeAnalysis.Razor.Compiler.SourceGenerators.dll”引用了编译器的版本“4.9.0.0”,该版本高于当前正在运行的版本“4.8.0.0”

要放在平时,我根本不会在意,毕竟满屏的“属性未在构造器中赋值”中,它并不起眼,况且,就算偶然注意到它,也已经在多次偶然中与它相熟了。往常也没有奇怪的异常与它相关。但这次显眼Compiler和SourceGenerators让我无法再忽视它的存在。cshtml不就是在编译时没有生成成相应的代码嘛。

在前面蹂躏的过程中,也试了使用dotnet publish,结果是成功的,换了不同的sdk版本,都是成功。但自从注意到这条警告,我就试图在dotnet 的生成和发布中找到它,始终无果。

VS编译器版本不兼容了?怎么更新一下?vs编译用的不是我安装的sdk?

此时,自然就想到了更新Visual Studio,找到 vs installer 发现确实有新版本,发现版本号差的并不是很大,所以一开始并没有报太大希望,但更新后再编译,一切问题都消失了……

困扰我这么久的问题,竟然一次更新就解决了,完全就没有幻想中力挽狂澜的澎湃啊啊啊啊啊~~~

记一次Razor Pages无法编译问题及解决的更多相关文章

  1. 【翻译】介绍 ASP.NET Core 中的 Razor Pages

    介绍 ASP.NET Core 中的 Razor Pages 原文地址:Introduction to Razor Pages in ASP.NET Core         译文地址:介绍 asp. ...

  2. ASP.NET Core 快速入门(Razor Pages + Entity Framework Core)

    引子 自从 2009 年开始在博客园写文章,这是目前我写的最长的一篇文章了. 前前后后,我总共花了 5 天的时间,每天超过 3 小时不间断写作和代码调试.总共有 8 篇文章,每篇 5~6 个小结,总截 ...

  3. .NET MVC Razor模板预编译(二)

    在前面一片文章:<.NET MVC4 Razor视图预编译(一)> 里面我采用的是PrecompiledMvcViewEngineContrib组件进行预编译视图的虚拟地址注册,但是这个组 ...

  4. .NET MVC4 Razor视图预编译(一)

    在平时使用.NET MVC中不乏有类似的需求:某些razor视图,特别是系统后台的视图,不想让用户自行更改,需要通过某种方法把视图模板编译到项目的dll中去. 但是VS并不提供razor的预编译,如果 ...

  5. [译]ASP.NET Core揭秘 - Razor Pages

    原文 什么是Razor Pages? Razor pages是ASP.NET Core 2.0的新特性,它被设计用来更快的开发页面,比传统的MVC模式更便捷. 创建项目 为了使用Razor Pages ...

  6. 学习 razor pages 指南

    这是一个系列,我打算把此人的系列翻译一下,学习技术的同时,顺便提高一下英文水平. 原文地址:https://www.learnrazorpages.com/ 前言 欢迎来学习 razor pages ...

  7. asp.net core 的 razor pages 如何使用ajax调用后台方法

    Razor 是一种允许您向网页中嵌入基于服务器的代码(Visual Basic 和 C#)的标记语法. 当网页被写入浏览器时,基于服务器的代码能够创建动态内容. 在网页加载时,服务器在向浏览器返回页面 ...

  8. Razor Pages with ASP.NET Core 2

    With ASP.NET Core 2 we get another way of building web applications. It’s one of those new things th ...

  9. ASP.NET Core Razor Pages

    Razor 页面是Asp.Net Core2.0新增的一个功能.Razor 页面是 ASP.NET Core MVC 的一个新特性,它可以使基于页面的编码方式更简单高效. 环境:vs2017 .net ...

  10. Introduction to Razor Pages in ASP.NET Core

    https://docs.microsoft.com/en-us/aspnet/core/mvc/razor-pages/ 从ASP.NET Core 2.0.0版本之后,添加了新的特性Razor p ...

随机推荐

  1. C语言指针知识总结

    指针 定义 指针是一个变量,存储另一个变量的内存地址,它允许直接访问和操作内存中的数据,使得程序能够以更灵活和高效的方式处理数据和内存. 获取变量地址:使用取地址符 &. 访问地址上的数据:使 ...

  2. Diffutoon下载介绍:真人视频转动漫工具,轻松获得上千点赞

    最近在刷短视频的时候,偶尔能看到一些真人转动漫风的作品,看起来给人一种新鲜感,流量都还不错,简简单单跳个舞,就能获得上千个点赞~ 那么,这种视频是怎么制作的? 本期给大家介绍一款AI转绘工具Diffu ...

  3. P5665 [CSP-S2019] 划分

    思路: 首先求出 \(a\) 的前缀和数组 \(s\). 考虑动态规划,令 \(dp_{i,j}\) 表示以 \(i\) 结尾,末尾有 \(j\) 个为一组的最小答案,则状态转移方程为: \[dp_{ ...

  4. 强化学习:一种新的并行算法下的参数同步更新方式——半异步更新方式——( 同步、异步 -> 半异步 )

    Abstract: 并行算法下的参数同步方式一般有同步更新和异步更新两种方式,本文在此基础之上提出了一种新的参数同步方式--半异步更新方式. Introduction: 这里用神经网络举例子,也就是神 ...

  5. tensorflow1.x——如何在python多线程中调用同一个session会话

    如何在python多线程中调用同一个session会话? 这个问题源于我在看的一个强化学习代码: https://gitee.com/devilmaycry812839668/scalable_age ...

  6. 常用的php方法

    /* * http 封装网络请求方法 */ /* * get method */ function get($url, $param=array()){ if(!is_array($param)){ ...

  7. [ZJOI2010] 基站选址 题解

    前言 题目链接:洛谷. 题意简述 [ZJOI2010] 基站选址. 有 \(N\) 个村庄坐落在一条直线上,第 \(i\) 个村庄距离第 \(1\) 个村庄的距离为 \(D_i\).需要在这些村庄中建 ...

  8. Maven经验分享(一)安装部署 转

    Maven安装部署 1.安装 在安装Maven之前,首先要确认你已经正确安装了JDK.Maven可以运行在JDK 1.4及以上的版本上.本书的所有样例都基于JDK 5及以上版本 目录下的安装包,直接a ...

  9. 【CMake系列】03-cmake 注释、常用指令 message、set、file、for_each、流程控制if

    本文给出了 cmake 中的 一些常用的 指令,可以快速了解,为后面的内容深入 打点基础. 本专栏的详细实践代码全部放在 github 上,欢迎 star !!! 如有问题,欢迎留言.或加群[3927 ...

  10. [计算机网络] IPv6

    1 IPv6 概述 引言 近期突发奇想,能不能用 IPv6 的公网地址,给家里的 NAS 做 内网穿透. 技术上是可行的.只是必须确保是 IPv6 的公网地址. 大学学的 IPv6 的知识,早就抛到九 ...