首页 > 其他分享 >记一次Razor Pages无法编译问题及解决

记一次Razor Pages无法编译问题及解决

时间:2024-09-30 12:11:26浏览次数:5  
标签:Razor 配置 编译 404 cshtml Pages 页面

解决方案写在前面:更新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,配置,编译,404,cshtml,Pages,页面
From: https://www.cnblogs.com/hxyes/p/18440717

相关文章

  • java:详解java编译命令和启动命令
    编译命令在Java开发过程中,编译Java源文件(通常以.java为扩展名)是不可或缺的一步。这一步骤是通过javac命令完成的,该命令是Java编译器(JavaCompiler)的命令行工具。编译后的代码会生成字节码文件,这些文件以.class为扩展名,并可在Java虚拟机(JVM)上运行。基本语法......
  • C++学习:模版进阶:非类型模板参数 特化 分离编译
    目录一:非类型模版参数二:模版特化三:函数模版特化四:类模版特化一:全特化(将模板参数列表中所有的参数都确定化)二:偏特化(部分特化或更进一步限制)五:模版分离编译一:非类型模版参数非类型模版参数是在模版参数列表中,跟在模版参数后面的,就是用常量当参数(下面的n就是)templa......
  • C语言 18 条件编译
    再来看看条件编译,还可以根据条件,选择性地对某些内容进行忽略。来认识一下#ifdef、#else、#endif这三种条件编译指令:#include<stdio.h>//ifdef用于判断是否定义了符号PI,如果没有的话则处理以下的指令#ifdefPI#defineM666//如果定义了符号PI,那么就处理这个分支的语......
  • 解决编译安装内核时-lib-modules过大的问题
    原因是编译出来的ko文件里有一些debug信息。安装module的时候加一个strip选项,把这些额外信息去掉就好了。sudomakeINSTALL_MOD_STRIP=1modules_install如果已经安装了,想减少/lib/modules占用的体积,可以直接用strip命令进行裁剪sudobash-c'find.-iname"*.ko"|xargs......
  • 编译安装linux内核
    下载内核https://www.kernel.org/一般下载tarball,也就是.tar.xz格式的源码包。如果/够大,可以直接解压到/usr/src,也可以解压到机械盘上。配置.config里面是一些flag,内核编译的时候会读取这个文件,根据这些flag来配置。常用的有:CONFIG_LOCALVERSION附加在在内核的version......
  • 使得两次编译linux内核产生一样的结果
    exportINSTALL_MOD_STRIP=-sexportKBUILD_BUILD_TIMESTAMP=0exportKBUILD_BUILD_USER=rootexportKBUILD_BUILD_HOST=localhostmakemrpropermakeallnoconfigmake-j4其中makeallnoconfig表示除必须的选项外,其它选项一律不选。然后就可以发现vmlinux和arch/x86/bo......
  • Javascript编译原理
    JavaScript的编译原理是一个复杂但有序的过程,主要涉及分词(词法分析)、解析(语法分析)、代码生成以及执行等阶段。以下是对JavaScript编译原理的详细解析:chrome编译流程 1.分词(词法分析)分词(Tokenizing)或词法分析(Lexing)是编译过程的第一步。在这个阶段,编译器将输入的源代码......
  • apk反编译修改教程系列-----修改apk 去除软件加固状态 实例操作步骤解析_2【二十八】
          今天继续以实例来演示去加固的步骤,app软件有加固就无法直接进行反编译修改操作。那么去加固就是修改软件的前提。作为初学的朋友,去加固后先测试app是都可以正常安装与打开。然后在进行对应的反编译修改操作。通过博文了解1------apk去加固的实例步骤演示......
  • Qt源码编译-Ubuntu平台
    Qt源码编译-Ubuntu平台Qt官网已取消了Qt5.15版本二进制安装包。如果要安装Qt5.15需要下载源码自行编译安装或使用商业授权版本。Qt是一个功能强大的跨平台开发框架,支持从嵌入式系统到桌面应用程序的开发。如果你希望在Ubuntu平台上从源码编译Qt,这篇教程将带你一步步......
  • [转]boost使用之编译库及遇到的问题
    最近因为在学习网络编程相关的东西,准备学习一下boost,毕竟原生的网络编程太麻烦。看了一下其实windows下想使用起来很简单,就是下载库,然后运行脚本,然后运行exe库就出来。在把头文件和库的目录包含进去就可以了。在此详细记录一下:0、预装准备电脑WIN10系统,已经安装了VS2010。1、下......