asp.net core mvc和angular项目的一些问题
最近公司布置任务,用asp.net core mvc和angular改写原来的一个用Silverlight做的项目。从来没搞过,找了两本书看了一天,又看了一天代码,大致心里有底了,就开始动手。没想到一上来就碰到了头痛的问题。
首先是第一次调试后,修改了typescript,却不会自动编译。花了不少功夫才明白,原来不要用缺省的IISExpress,另外建了个调试profile,关键是类型设为Project,这下就方便了。F5调试后,随时修改template或者typescript,马上就自动重新编译。
第二个问题是无法从asp.net core mvc做的web api取到数据。stackoverflow上的一条回答严重误导了我。它说web api和angular不能发布到同一个端口。结果折腾了半天还是不行。用ng serve来加载angular网页,可以从web api取到数据,但以Release模式发布到IIS上就不行了。怀疑是跨域即CORS的问题,但怎么设也不通。折腾了半天,最后用Debug模式发布,可以取到数据了。但是,项目中要求和win form通信。本来win form中使用WebBrowser控件来访问Silverlight,因为WebBrowser控件默认的模式是IE 7.0,而angular不支持IE 7.0,所以无法显示。通过设置注册表,设定为仿真IE 11,但还是无法显示。如果用其它控件,CefSharp可以显示。问题是win form项目需要以Click-once方式部署,而过去和CefSharp这个控件打过交道,Click-once部署时无法将所需dll文件打包进去。查了下资料,现在似乎可以了。但鉴于过去的痛苦经验,不想试。
本来以为很简单的事情,却老是搞不定。最后通过console.log调试,才发现其实是路由问题。以前做过asp.net mvc 1.0,所以知道路由是怎么回事,加了条web api的路由,马上就顺利取到了数据。用WebBrowser控件访问,也成功了。
这下终于明白几点:
1.Debug模式下,缺省是用angular cli来加载angular,运行在和wep api不同的端口,而WebBrowser控件骨子里是IE 7.0,可能不支持CORS,所以访问失败。
2.Release模式下,是用IIS加载静态文件index.html。如果不给web api加路由,所有对/api/。。。路径的访问即调用web api都被转到index.html,所以取不到数据。加一条路由,就能顺利访问/api/ 下面的web api方法。这样,asp.net core mvc做的web api和angular发布到同一端口,和平共处。又因为是同一端口,没有CORS的问题,所以WebBrowser控件可以顺利访问。也就是说,如果通过WebBrowser控件访问angular,必须以Release模式,将web api和angular发布到同一端口,然后为web api加条路由。
第三个问题是如何从angular访问win form里的C#方法。
以前是在C#里,将一个类加上ComVisible(true)属性,然后把这个对象赋给WebBrowser控件的ObjectForScripting属性,就可以在javascript里,通过window.external.<方法名>来调用了。但是在angular里却不行。也花了点时间,在stackoverlow上找到一条回答,有启发。最后发现应该这样做:
1. index.html里的head部分里加一句<script src="winformCaller.js" ></script>
2.这个winformCaller.js里:
1 2 3 4 5 | function testCall(arg) { if ( typeof (window.external.foo) !== "undefined" ) { window.external.foo(arg); } } |
3. angular里,用一个javascript文件(不是typescript),这样调用:
1 2 3 4 5 | export function callWinfom(arg) { if ( typeof (testCall) !== "undefined" ) { testCall(arg); } } |
然后其它的typescript可以通过import这个js文件来调用。
4. 在angular.json文件里,把这个winformCaller.js加到assets一栏。
至于从win form里访问typescript,这样做:
1. webBrowserControl1.InvokeScript("callAngularFromWinform", parameters);
2. 在index.html的body末尾,加一句:
<script src='callAngular.js' ></script>
3.callAngular.js:
1 2 3 4 5 | function callAngularFromWinform(arg) { window.callAngular(arg); } |
4. typescript里:
1 2 3 | window[ "callAngular" ] = (arg) => { //做些事情 }; |
5.同样, 在angular.json文件里,把这个callAngular.js加到assets一栏。
我的理解是因为typescript编译后,函数名字都改了,所以直接InvokeScript不行。
另外值得一提的是这里的 if (typeof(testCall) !== "undefined"),容易误写为if (testCall !== undefined) ,这样写,如果testCall没有参数,倒也行,但这就给人以成功的错误假象。如果testCall有参数,就不正常了。如果不知道这个问题,也要花不少时间调试才能解决。这固然和javascript的设计缺陷有关,或者说这不是javascript的good parts,但必须了解。
解决了部署以及和win form双向通信的问题,剩下的就感觉简单多了,用了一天时间,就改写了全部业务逻辑代码,再花了几天调试界面,就大功告成。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律