-
安装完dotnet后执行dotnet --info报错, 执行dotnet --list 又没问题 ,大概意思libicuil8n..so.50这个文件有问题,但又找不到正常文件cannot get symbol ucol_setMaxVariable_50 from libicui18n error:/lib64/libicuil8n..so.50: undefined symbol:ucol_setMaxVariable_50 Aborted
-
开发是用windows开发的,发版是Linux环境,Windows环境发版没有问题【主库】Next recovery time: 2024/1/15 17:50:50 (ERROR [01000] [unixODBC][Driver Manager]Can't open lib '/usr/lib64/psqlodbcw.so' : file not found)【主库】Next recovery time: 2024/1/15 17:41:38 (ERROR [01000] [unixODBC][Driver Manager]Can't open lib 'PostgreSQL Unicode' : file not found)
-
.net windows 开发好了,都是通的,linux环境发布之后为什么连不上数据库了 ? 装上了linux的驱动 但还是一直找不到文件 是开发的链接字符串也要改嘛
-
.net core 开源跨平台,集成当前各种流行的技术框架;.net 6为长期支持版本,.net core 2/3即将关闭支持;中间模式是非常优秀的设计和特色,next(),可无限的加中间处理过程;模块化是非常好的设计;适合各类网页、iot、桌面、app的运用开发,适合云原生的开发;云原生开发是一个庞大的开发体系,并不是单单的某个开发语言或环境;devops是个大趋势;
-
https://developer.huaweicloud.com/signup/2e4da6016dac4fb18d20e05fa0fd72bc 有邀请活动
-
始活动前,请先报名本期读书会https://developer.huaweicloud.com/activity/reading_11.html--------------------------------------------------------------开发者,你好哟~华为云 · 云享读书会 第11期 它来了 !本期领读书籍为《深入浅出ASP.NET Core》由领读书籍原作者、华为云MVP、微软MVP、华为云云享专家、Microsoft Tech Summit 讲师、52ABP框架作者——梁桐铭老师,带你精读这本深入浅出ASP.NET Core!经过老师的视频领读,如果你有相关知识收获,欢迎在此帖留下你的读书笔记~获奖信息公示(公示期截止7月5日)优秀问答奖云之山zekelove幸运奖Allen2000张辉禄仁恝孙小北仲劲抽奖过程详见附件。恭喜以上开发者获得活动奖励,请点击下方链接填写获奖信息,请于7月20日前完成填写,过期视为弃奖哦~如有任何疑问可以和小助手联系~https://devcloud.huaweicloud.com/expert/open-assessment/qtn?id=3d3d196636fc4df9874cd247e36418bd&utm_source=ASPNetCore活动时间2021.06.20 - 2021.06.2702. 回复内容要求1. 可以提出您在课程学习中产生的任何疑问或者问题,也可以是您产生的深刻思考,我们统统欢迎;2. 禁止抄袭或复制读书笔记帖的任何内容;3. 您也可以参考以下互动话题,与领读专家和其他同学互动交流;4. 回帖时请务必留下你的微信昵称和华为云账号。03. 互动话题请说说您在本次课程中的收获04. 注意事项1. 小助手会在活动结束后按续完成审核,并增加活动积分20活动积分/人,优质回复额外增加50或100活动积分/人;2. 本次活动通过参与专家坐堂Q&A,可获得的积分上限为120分;3. 请务必按照上述要求提交内容,以免影响积分增加;4. 若积分值相同则以完成学习任务的时间先后排序,其中任务完成时间的判定优先级为:读书笔记>自测题>专家Q&A>其他;5. 其他积分获取方式请查看活动社群公告;6. 其他未说明事项请参照 云享读书会《深入浅出ASP.NET Core》05. 参与奖励针对活动时间内提交的有效读书笔记,领读专家将根据回复质量综合评选2位优秀奖获奖者,并奖励提交人 公牛插排魔方 一个同时抽取5位幸运奖获奖者,奖励 手机支架 一个(与优秀奖不兼得)06. 关于云享读书会每期云享读书会活动,会选取一本技术相关的畅销书籍,由原作者/行业专家提炼书籍精华,在读书会的专属微信社群中,每日输出精华知识的领读视频,帮助大家快速积累专业知识。活动期间会设置每日自测题、结业实践任务、提交读书笔记三种积分获取任务,并根据活动结束后的积分排行发放活动奖励。07. 加入学习社群然后添加小助手微信,备注“NET Core”加入学习社群。
-
开始活动前,请先报名本期读书会https://developer.huaweicloud.com/activity/reading_11.html--------------------------------------------------------------开发者,你好哟~华为云 · 云享读书会 第11期 它来了 !本期领读书籍为《深入浅出ASP.NET Core》由领读书籍原作者、华为云MVP、微软MVP、华为云云享专家、Microsoft Tech Summit 讲师、52ABP框架作者——梁桐铭老师,带你精读这本深入浅出ASP.NET Core!经过老师的视频领读,如果你有相关知识收获,欢迎在此帖留下你的读书笔记~获奖信息公示(公示期截止7月5日)最佳读书笔记奖励张辉花溪孙小北积分排名1~5名昵称Day1Day2Day3Day4Day5测试题1测试题2测试题3测试题4测试题5互动答疑总成绩孙小北 100100100100100100100100100100601060RabbitCloud100100100100100100100100100100601060allen2000100100100100100100100100100100601060zekelove100100100100100100100100100100601060夏暖100100100100100100100100100100601060积分排名6~15名张辉100100100100100100100100100100201020禄仁恝100100100100100100100100100100201020iolink1002100100100100100100100100100100201020仲劲100100100100100100100100100100201020AAAI100100100100100100100100100100201020HB168810010010010010010010010010075401015云水不言10010010010010010010010010010001000花溪10010010010010010010010010010001000Ethins10010010010010010010010010010001000yjh879238 10010010010010010010010010010001000恭喜以上开发者获得活动奖励,请点击下方链接填写获奖信息,请于7月20日前完成填写,过期视为弃奖哦~如有任何疑问可以和小助手联系~https://devcloud.huaweicloud.com/expert/open-assessment/qtn?id=3d3d196636fc4df9874cd247e36418bd&utm_source=ASPNetCore征集时间2021.06.15 - 2021.06.27读书笔记要求1. 每篇读书笔记字数要求≥300字;2. 内容要求与每日领读视频、领读书籍或是其他.NET Core技术领域相关;3. 内容原创不可抄袭;4. 回帖时请务必留下你的微信昵称和华为云账号。03. 注意事项1. 读书笔记提交后,小助手会在3个工作日内按续完成审核,并增加活动积分100活动积分/篇;2. 本次活动通过提交读书笔记,可获得的积分上限为500分;3. 请务必按照上述要求提交内容,以免影响积分增加;4. 若积分值相同则以完成学习任务的时间先后排序,其中任务完成时间的判定优先级为:读书笔记>自测题>专家Q&A>其他;5. 其他积分获取方式请查看活动社群公告;6. 其他未说明事项请参照 云享读书会《深入浅出ASP.NET Core》04. 最佳读书笔记奖励针对活动时间内提交的有效读书笔记,领读专家将根据内容质量和完成篇数综合评选3位最佳读书笔记获奖者,并奖励提交人荣耀猎人路由器1个05. 活动排行奖励最终积分排名1~5名 最终积分排名6~15名06. 关于云享读书会每期云享读书会活动,会选取一本技术相关的畅销书籍,由原作者/行业专家提炼书籍精华,在读书会的专属微信社群中,每日输出精华知识的领读视频,帮助大家快速积累专业知识。活动期间会设置每日自测题、结业实践任务、提交读书笔记三种积分获取任务,并根据活动结束后的积分排行发放活动奖励。07. 加入学习社群然后添加小助手微信,备注“NET Core”加入学习社群。
-
1、用VS2013打开解决方案。 2、选中解决方案,点击鼠标“右键”—>从弹出对话框中,选择“清理解决方案”。3、待第2步“清理解决方案”结束后,选中“解决方案”—>点击鼠标“右键”—>在弹出对话框中,选择“重新生成解决方案”。4、待第3步“重新生成解决方案”结束后,选择web运用程序,如下图中“testDemo”—>点击鼠标“右键”—>在弹出对话框中,选择“发布”。5、设置“配置文件”节点,点击“下一步”。6、设置“连接”节点,点击“下一步”。7、设置“设置”节点,点击“下一步”。8、设置“预览”节点,点击“发布”。9、发布后的文件如下图,此时文件发布成功,发布成功后,点开文件夹,所有页面的.cs文件都放进bin里面了。二、IIS安装1、打开“控制面板”—>选择“程序”。2、在弹出对话框中选择“启用或关闭Windows功能”。3、在弹出对话框中,选择“Internet Information Services”(如果初学者,建议全部选择,对于老手,按需选择),点击“确定”。4、点击确定后,系统正在运用所做的更改。5、运用程序更改结束后,选择“立即重新启动”。系统重新启动后,则IIS配置结束。6、重启电脑后,测试IIS配置是否成功。在浏览器栏,输入“http://localhost”,若出现如下界面,则表示IIS安装成功。三、IIS发布网站1、在“我是Cortana,小娜,有问题尽量问我”输入框输入“Internet Information Services”.2、打开IIS主界面。3、选择“网站”—>点击鼠标“右键”,在弹出对话框中,选择“添加网站”。4、在弹出对话框中,设置相关参数。5、此时,IIS主界面,“网站”多了一个站点“www.testWebSite”,即是刚才给站点取得名字。 6、配置运用程序池7、配置默认文档 8、默认文档添加成功后,如下图所示:9、为了防止权限不足,将刚才发布的文件添加成员“everyone”,并赋予权限。右键—>属性—>安全—>编辑—>添加 —>输入“everyone”—>为用户everyone赋权限—>确定。10、注册IIS。在所用程序中找到大写V,选择“Visual Studio 2013”—>选择“Visual Studio Tools”—>以管理员身份选择“VS2013 开发人员命令提示”,进入CMD。输入"aspnet_regiis -i"。11、至此,整个发布结束。12、测试。在浏览器地址栏输入:”http://localhost:8090/sessionDemo.aspx“,访问。
-
Mono 和 Jexus 网站服务器Mono 这个开源项目其实一直伴随着 .NET Framework 成长。Miguel de Icaza 先生早年一直领导者 Gnome 这个开源桌面系统的开发。在2000年微软公布了 C# 语言和 .NET Framework 之后,他非常感兴趣并且希望能把这些新技术带到 Linux 平台,于是一手建立了 Mono 这个项目和社区。现在 Mono 的稳定版本是 6.10,全面兼容.NET 5,是.NET 5统一框架下的2大运行时之一,相对于.NET Framework停留在4.8 版本,Mono一直在进化,在移动开发Xamain、前端Blazor具有一席之地,同时在服务器段也是.NET Core 有益补充。和 .NET Core 另起炉灶相比,Mono 处处都保持着和 .NET Framework 的兼容性。在微软2014年11月完全基于 MIT 协议开放 .NET Framework 参考代码后,Mono 立即开始集成微软的代码 ,非常明显的改善了兼容性。不过 Mono 保持了自己独立开发的 CLR 实现和 C# 编译器,有自己的 AOT 运行环境和 C# Shell。在应用程序框架方面,Mono 提供 WinForms 和 WebForms 支持,也包含了微软早已开源的 MVC 5、Web API 2 和 SignalR 2。在 Mono 这个稳固的基础之上,中国四川的一位微软 C# MVP 刘冰历时多年设计了一款免费的网站服务器,取名 Jexus,最新稳定版本是6.2。作为一款跨平台软件,它支持各种主流 Linux 发布版本和 FreeBSD,特别是国内应用创新领域对于华为的鲲鹏(ARM )和龙芯(MIPS/LoongArch)。从架构等技术特点来看,Jexus 也可以媲美 IIS 等商用服务器。比如它提供了多站点支持,拥有应用程序池来调度管理工作进程,具有良好的稳定性和容错能力。又比如它支持 HTTPS 和 WebSockets,支持 FastCGI 协议和 OWIN 标准。它不仅可以作为一款应用服务器,来托管各种 ASP.NET 4 应用(WebForms、MVC、Web API、SignalR),同样也可以作为一般服务器使用,包含 URL 重写、反向代理、压缩传输等基础功能和 SQL 注入预防等多项内置安全防护。Jexus for linux 有如下特点:支持多种操作系统:Jexus最初的设计目标是“跨平台的ASP.NET WEB服务器”,由于在Windows系统上,IIS已经是ASP.NET的优秀平台,所以,当前的Jexus以支持Linux和FreeBSD等非Windows系统为主要设计目标。正因为这个原因,就Linux/FreeBSD等平台的ASP.NET建设而言,Jexus具有特别重大的意义。高性能:“高性能”是Jexus的重要的设计目标。虽然Jexus基于Mono环境运行,但Jexus并非全部由Mono的.NET组件构成,对于涉及性能的关键代码,Jexus非常巧妙地大量采用了Linux/Unix本身的优秀特性,从代码层保证了Jexus的性能优势。同时,Jexus的框架特征也为高性能提供了基础保证。Jexus不象XSP那样,纯HTML也需要经过ASP.NET处理,更不象Apache和Nginx等服务器,需要通过插件的形式间接地对ASP.NET进行支持,Jexus把HMTL静态文件处理模块、ASP.NET处理模块、静态文件高速缓存机制、epoll/poll数据传输机制等进行了高度集成,从架构本身入手,最大限度地提高WEB服务器的处理能力和传输速度。安全性:Jexus内核含有安全监控机制,绝大多数恶意访问在进入网站前就会被Jexus直接禁止,这是Jexus有别于其它WEB服务器的又一大特色,所以,Jexus特别适合那些对安全要求较高的企业网站或政府网站使用。稳定性:从运行机制而言,Jexus系统中,有专门检测工作进程执行状态的管理单元,任何一个进程退出或者任何一个ASP.NET网站应用程序域退出,被会被管理单元发现并得到重启,从而保证了Jexus能够7*24小时不间断工作;从程序本身而言,Jexus程序代码力求简洁,BUG很少,同时,Jexus的每个版本在正式发布之前,都要经过严格的压力测试,影响稳定性的因素,几乎在正式发布之前即已被全部排除。功能强大:Jexus支持URL重写,支持多目标服务器的反向代理,支持PHP,支持GZIP压缩传输,并且,可以利用不同端口、不同虚拟路径、不同域名设置任意数量的网站,这些功能要素,表明了Jexus是一款功能完整而强劲的WEB服务器。安装、配置、操作极为简单,服务社区化,各种问题能得到快速的处理,有良好的后续服务支撑能力。总体上来说,jexus除其它通用服务器应用的静态处理与反向代理功能外,另外三个特色比较突出:一,真正纯国产;二,入侵检测;三,支持asp.net/core。鲲鹏(ARM)上部署 Jexus 有两种安装方式:1是使用官方自动安装脚本:curl https://jexus.org/release/arm64/install.sh|sudo sh安装完成的目录地址为/usr/jexus 2是使用手动安装,可以自定义目录,我们这里也安装到/usr/lexus/目录下方便理解 wget https://linuxdot.net/down/jexus-6.2.x-arm64.tar.gz tar zxvf jexus-6.2.x-x64.tar.gz Jexus的配置文件cd siteconf/ #进入配置文件目录vim web #新建一个配置文件名为web,并进行编辑####################### Web Site: web ######################################## port=80 # 监听端口:使用域名的话为80root=/ /var/www/default # 运行目录 .NetCore web项目需要把项目目录指向到wwwroot目录,不支持虚拟目录hosts=web.test.com # 服务器绑定域名,在hosts做一个本地域名也可以,也可以是IP地址,这里就不做演示了# User=www-data# AspNet.Workers=2 # Set the number of asp.net worker processes. Defauit is 1.# addr=0.0.0.0# CheckQuery=false# NoLog=true AppHost={ # 新建AppHost配置 cmd=/var/wwww/deault/myWeb; # 进行dotnet 项目名.dll运行操作 root=/var/wwww/deault; # 项目的工作目录 # port=5001 # 可选项。表示这个应用程序的侦听端口,多个端口用英文逗号分隔 #OutLog=/log/out.txt; # OutLog:可选项。表示将这个应用程序的控制台输出重定向到指定的文件(需填写完整路径); #ErrLog=/log/out.txt; # ErrLog:可选项。表示将这个应用程序的异常输出重定向到指定的文件(需填写完整路径),如果不原意输出日志,可以不用OutLog项。这时, jexus会自动关掉控制台输出 }确保配置和项目文件无误后,进入目录运行jexuscd /usr/jexussudo ./jws start ... OK.使用浏览器测试一下:设置开机启动新建 jexus.servicecd /lib/systemd/systemvi jexus.service添加如下配置[Unit]Description=jexusAfter=network.target[Service]Type=forkingExecStart=/usr/jexus/jws startExecReload=/usr/jexus/jws restartExecStop=/usr/jexus/jws stopPrivateTmp=true[Install]WantedBy=multi-user.targetjexus加入服务: systemctl enable jexus.service启动jexus服务: systemctl start jexus.service查看jexus服务状态: systemctl status jexus.service
-
ASP.NET Core应用通过一个进程内的HTTP服务器实例实现运行,这个服务器实例侦听HTTP请求并将请求作为组成HttpContext的一组请求功能集暴露给我们的应用程序。ASP.NET Core搭载两个服务器实现:Kestrel是一个基于libuv的跨平台HTTP服务器,libuv是一个跨平台的异步I/O库WebListener是一个基于HTTP.SYS内核驱动的“Windows专用”HTTP服务器KestrelKestrel是包含在ASP.NET Core新项目模板中默认的web服务器。如果你的应用只接收来自内部网络的请求,你可以只使用Kestrel本身。如果你将你的应用部署在公共网络上,我们建议你使用IIS,Nginx或者Apache作为反向代理服务器。一个反向代理服务器接收来自网络的HTTP请求并且在经过一些初步处理后将请求传递到Kestrel服务器。过程如下图所示。对edge deployments(从公共网络上接触到流量的部署方式)使用反向代理最重要的一个原因就是安全性。因为Kestrel相对较新,对抵御安全攻击至今还没有一个完整的功能补充。安全性处理包括但不限于适当的超时,大小的限制,以及并发连接限制等问题。有关何时使用Kestrel与反向代理的更多信息,请参见Kestrel。IIS with Kestrel当你使用IIS或者IIS Express作为对ASP.NET Core的反向代理时,ASP.NET Core应用将运行在由该IIS工作进程分离出的一个进程中。在该IIS进程中,存在着一个特殊的IIS模块,它被用来协调反向代理的关系。它就是ASP.NET Core模块。ASP.NET Core模块的主要功能包括启动ASP.NET Core应用,当应用崩溃时处理重启,向应用传送HTTP流量。更多的信息,请参考ASP.NET Core Module。Nginx with Kestrel有关如何在Linux使用Nginx作为对Kestrel的反向代理服务器的更多信息,请参考Publish to a Linux Production Environment。Apache with Kestrel有关如何在Linux使用Apache作为对Kestrel的反向代理服务器的更多信息,请参考Using Apache Web Server as a reverse proxy。Jexus with Kestrel有关如何在Linux使用Jexus作为对Kestrel的转发服务器的更多信息,请参考 Jexus 5.8.2 正式发布为Asp.Net Core进入生产环境提供平台支持WebListener如果你在Windows上运行你的ASP.NET Core应用,你可以会遇到以下场景——你既想要在公共网络上部署你的应用,又不能使用IIS,这时,WebListener会是一个可供替代的选择。当你只想要在内网中部署你的应用时,WebListener可以被用来代替Kestrel,特别是当你需要Weblistener服务器支持功能中的某项而Kestrel恰好不支持的时候。对于内部网络场景,为了能达到最好的性能表现,我们通常推荐Kestrel服务器,但是在另一些场景中,你可以想要使用某项仅WebListener支持的功能。关于WebListener功能的更多信息,请参考WebListener。ASP.NET Core 服务器基础组件说明IApplicationBuilder在Startup类中的Configure方法暴露了IFeatureCollection类的ServerFeatures属性。Kestrel和WebListener服务器都只提供了一个单一的功能,IServerAddressesFeature,但是不同的服务器实现可能会显示额外的功能。IServerAddressesFeature可以用来找出哪些服务器实例端口在运行时被绑定。ServerFeatures 的注释为“Gets the set of HTTP features the application's server providers”。自定义服务器你可以创建自定义服务器实现以用来替代Kestrel或者WebListener。Open Web Interface for .NET(OWIN) guide 说明了怎么去实现一个Nowin-based IServer。你可以自由地实现你的应用所需的功能接口,但至少必须支持IHttpRequestFeature和IHttpResponseFeature接口。
-
现在越来越多的人在谈论. NET Core。诚然,.NET Core 是未来, 但是.NET Framework 仍在支持, 因为大量的应用程序无法在短时间内迁移。.NET Core 和 .NET Framework 就像电动汽车和汽油动力汽车。汽油车是成熟的,你可以毫无任何问题驾驶它,但电动车有它们的优势,并正在取代汽油车。所以,不要误会,你应该从今天开始迁移到. NET Core。我已经迁移了几个运行在完整.NET Framework和IIS上的传统ASP.NET/MVC项目到ASP.NET Core 2.x,可以运行在IIS或非IIS环境下。这篇文章针对的是新接触.NET Core,但有.NET Framework经验的开发人员,帮助他们将现有的应用更平滑的过渡到.NET Core上。1、迁移或重写有时候,我更喜欢用“重写“而不是”迁移“这个词,因为在有些情况下,.NET Core和.NET Framework是完全不同的两个东西。根据我的经验,大部分前端代码可以只做少量修改就直接移植到.NET Core,因为它们的本质毕竟是服务器技术无关的,天生跨平台的技术。至于后端代码,迁移成本取决于它们对Windows及IIS的耦合程度。我理解,有些应用会充分利用Windows 及 IIS 的特性,这样开发者就可以避免自己费力去实现一些功能。这些包括计划任务、注册表、活动目录或Windows服务等。这些并不能够直接迁移,因为.NET Core是跨平台的。对于这些部分,你可能需要考虑从重新设计业务逻辑,想一种可以实现相同功能,但不依赖于Windows 或IIS 组件的方法。对于无法迁移的历史遗留代码,你可能需要考虑重新设计整个应用的架构,将这些功能作为REST API暴露出来,可以使用.NET Framework上的ASP.NET Web API来实现。这样的话,你的ASP.NET Core 应用得以继续使用这些API并继续完成业务功能。即使你的应用使用了WCF服务,甚至更老的 ASMX 服务,也是可以搞的。因为.NET Core目前有WCF客户端可以调用WCF。2、NuGet 包管理请确保你需要使用的NuGet包支持 .NET Core 或 .NET Standard。如果不支持,那么你需要研究有没有可以替换的NuGet包,或者你是否能够自己写代码去实现相同的功能。.NET Standard 意味着这个包可以同时使用在.NET Framework 4.6.1+ 以及.NET Core,这是取代老的 Portable Class Library (PCL)的技术。所以,如果你看到一个包的依赖项里有.NET Standard,这意味着你能够将它安装到你的.NET Core工程中。有部分包,比如NLog有专门的.NET Core版本,比如 NLog.Web.AspNetCore,你应该选择使用这样的版本。你依然可以在.NET Core工程里引用一个.NET Framework的包,但是这会让你的应用只能跑在Windows上,不推荐这么做。我列出了一些热门使用的NuGet 包,它们都已经支持.NET Core:NLog.Web.AspNetCoreNewtonsoft.JsonHtmlAgilityPackRestSharpNUnitDapperAutoMapperMoq对于客户端包,比如 jQuery,请不要使用NuGet 将它们安装到.NET Core工程中,参见本文的 “客户端包管理” 章节。如果你使用 Visual Studio Code 做 .NET Core 开发,请注意,安装NuGet包的命令不是 Install-Package,那是给Visual Studio的 PowerShell host用的,在VSCode里,你需要使用dotnet CLI工具,比如:dotnet add package Newtonsoft.Json参见 https://docs.microsoft.com/en-us/dotnet/core/tools/dotnet-add-package3、客户端包管理ASP.NET Core 曾经使用 Bower 去管理客户端包。但在ASP.NET Core 2.1 里,Bower 已经被移除了,因为作者不干了。因此,微软默认使用自家的包管理器 “Library Manager” 也叫 “libman” 去管理前端包。它能够在 Visual Studio 和 Visual Studio Code 中使用,甚至也能用 CLI 在命令行下使用。libman.json 可以直接编辑,也能在UI中更改,都有智能感知支持。我的建议是,如果你的应用不是重客户端的话,使用 libman 去管理前端包,因为其他技术比如NPM 太重量级了。你会希望在你的编译服务器上安装和配置NodeJS以及其他一切东西,仅仅为了拉取一个jQuery 库。更多详情可参见官方文档 https://docs.microsoft.com/en-us/aspnet/core/client-side/libman/?view=aspnetcore-2.14、Html / JavaScript / CSS你可以直接将这些文件复制到.NET Core工程里。但是请确保你已经把文件路径修改正确,比如CSS里的图片文件路径。因为传统ASP.NET / MVC 模板默认使用 “/Content/” 目录,而.NET Core模板使用“/css/”, “/js/”, “/lib/” 等目录,这并不是强制的,只是约定俗成的规范。如果你希望捆绑并压缩CSS 和JS 文件,有许多工具可以办到。我个人喜欢用VS的一款插件,叫做 “Bundler & Minifier” ,你可以从这里获取https://github.com/madskristensen/BundlerMinifier.这款插件可以在开发时生成捆绑及压缩的文件,但非编译或运行时。5、App_Data 文件夹在传统ASP.NET/MVC 应用中,你可以将数据文件保存到一个名为“App_Data”的特殊文件夹中,但这个东西在.NET Core里不复存在了。为了实现类似的功能,你需要自己创建一个名为“App_Data” 的文件夹,但位于“wwwroot”目录之外。然后像这样使用public void Configure(IApplicationBuilder app, IHostingEnvironment env){ // set string baseDir = env.ContentRootPath; AppDomain.CurrentDomain.SetData("DataDirectory", Path.Combine(baseDir, "App_Data")); // use var feedDirectoryPath = $"{AppDomain.CurrentDomain.GetData("DataDirectory")}\\feed";}6、自定义 Http Headers在传统ASP.NET里,你可以在Web.Config 里像这样为每个响应都配置自定义的HTTP Header:<httpProtocol> <customHeaders> <add name="X-Content-Type-Options" value="nosniff" /> </customHeaders></httpProtocol>而在.NET Core里,如果你希望脱离Windows去部署你的应用,不可以使用Web.config文件。因此,你需要一个三方的 NuGet 包来完成这个功能:NetEscapades.AspNetCore.SecurityHeadersapp.UseSecurityHeaders(new HeaderPolicyCollection() .AddCustomHeader("X-UA-Compatible", "IE=edge") .AddCustomHeader("X-Developed-By", "Edi Wang"));详情参考https://github.com/andrewlock/NetEscapades.AspNetCore.SecurityHeaders7、获取客户端IP地址以及 HttpContext在传统ASP.NET 里,我们能够通过 Request.UserHostAddress 来获取客户端IP地址。但这个属性在 ASP.NET Core 2.x 里是不存在的。我们需要通过另一种方式获取HTTP 请求信息。1. 在你的 MVC 控制器里定义一个私有变量private IHttpContextAccessor _accessor;2. 使用构造函数注入初始化它public SomeController(IHttpContextAccessor accessor){ _accessor = accessor;}3. 获取客户端IP地址_accessor.HttpContext.Connection.RemoteIpAddress.ToString()就是如此简单。如果你的 ASP.NET Core 工程是用MVC默认模板创建的,针对HttpContextAcccessor 依赖注入注册应该在Startup.cs 中完成:services.AddHttpContextAccessor();services.TryAddSingleton<IActionContextAccessor, ActionContextAccessor>();RemoteIpAddress 的类型是 IPAddress 并不是string。它包含 IPv4, IPv6 以及其他信息。这和传统ASP.NET不太一样,对我们更加有用一些。如果你希望在Razor 视图(cshtml) 里使用,只需要用 @inject 指令注入到view中:@inject Microsoft.AspNetCore.Http.IHttpContextAccessor HttpContextAccessor使用方法:Client IP: @HttpContextAccessor.HttpContext.Connection.RemoteIpAddress.ToString()8、JsonResult默认情况下,ASP.NET Core 会使用 camelCase 序列化 JsonResult ,而传统 ASP.NET MVC 使用的是PascalCase,这会导致依赖Json结果的 JavaScript 代码爆掉。例如以下代码:public IActionResult JsonTest(){ return Json(new { Foo = 1, Goo = true, Koo = "Test" });}它会返回camelCase 的Json给客户端:如果你有大量JavaScript 代码并不能及时改为使用camelCase,你仍然可以配置 ASP.NET Core 向客户端输出 PascalCase 的Jsonpublic void ConfigureServices(IServiceCollection services){ // Add framework services. services.AddMvc() .AddJsonOptions(options => options.SerializerSettings.ContractResolver = new DefaultContractResolver());}现在,之前的代码会返回PascalCase 的结果:9、HttpModules 和 HttpHandlers这两者在ASP.NET Core中被替换为了 Middleware。但在迁移之前,你可以考虑使用别的方法,在一个普通ASP.NET Core Controller 中实现这些功能。例如,我的老博客系统里有个名为“opml.axd” 的HttpHandler 作用是向客户端输出一个XML文档,这其实完全可以用 Controller 来实现:public async Task<IActionResult> Index(){ var opmlDataFile = $"{AppDomain.CurrentDomain.GetData(Constants.DataDirectory)}\\opml.xml"; if (!System.IO.File.Exists(opmlDataFile)) { Logger.LogInformation($"OPML file not found, writing new file on {opmlDataFile}"); await WriteOpmlFileAsync(HttpContext); if (!System.IO.File.Exists(opmlDataFile)) { Logger.LogInformation($"OPML file still not found, something just went very very wrong..."); return NotFound(); } } string opmlContent = await Utils.ReadTextAsync(opmlDataFile, Encoding.UTF8); if (opmlContent.Length > 0) { return Content(opmlContent, "text/xml"); } return NotFound();}我也曾经使用HttpHandler 完成Open Search,RSS/Atom等功能,它们也能够被 重写为Controller。对于其他一些不能够被重写为MVC Controller的组件,例如处理特殊拓展名的请求。请参见:https://docs.microsoft.com/en-us/aspnet/core/migration/http-modules?view=aspnetcore-2.110、IIS URL Rewrite你依然可以使用和旧应用里完全一样的配置文件,不管你的 .NET Core 应用是否部署在IIS上。例如,在应用根目录底下创建一个名为"UrlRewrite.xml"的文件,内容如下:<rewrite> <rules> <rule name="Redirect Misc Homepage URLs to canonical homepage URL" stopProcessing="false"> <match url="(index|default).(aspx?|htm|s?html|php|pl|jsp|cfm)"/> <conditions logicalGrouping="MatchAll" trackAllCaptures="false"> <add input="{REQUEST_METHOD}" pattern="GET"/> </conditions> <action type="Redirect" url="/"/> </rule> </rules></rewrite>注意:你必须把这个文件设置为always copy到输出目录,不然无效!<ItemGroup> <None Update="UrlRewrite.xml"> <CopyToOutputDirectory>Always</CopyToOutputDirectory> </None></ItemGroup>打开 Startup.cs,在Configure 方法中添加如下代码:public void Configure(IApplicationBuilder app, IHostingEnvironment env){ ... using (var urlRewriteStreamReader = File.OpenText("UrlRewrite.xml")) { var options = new RewriteOptions().AddIISUrlRewrite(urlRewriteStreamReader); app.UseRewriter(options); } ...}这在我之前的文章中提到过https://edi.wang/post/2018/9/18/prevent-image-hotlink-aspnet-core.更多选项和用法可以参考 https://docs.microsoft.com/en-us/aspnet/core/fundamentals/url-rewriting?view=aspnetcore-2.111、Web.configWeb.config 文件并没有完全消亡。在 In .NET Core 里,一个 web.config 文件仍然用于在IIS环境下部署网站。在这种场景下,Web.config 里的配置仅作用于 IIS,和你的应用代码没有任何关系。可以参考 https://docs.microsoft.com/en-us/aspnet/core/host-and-deploy/iis/index?view=aspnetcore-2.1#configuration-of-iis-with-webconfig一个典型的IIS下部署ASP.NET Core应用的web.config 文件如下:<?xml version="1.0" encoding="utf-8"?><configuration> <location path="." inheritInChildApplications="false"> <system.webServer> <handlers> <add name="aspNetCore" path="*" verb="*" modules="AspNetCoreModule" resourceType="Unspecified" /> </handlers> <aspNetCore processPath="dotnet" arguments=".\Moonglade.Web.dll" stdoutLogEnabled="false" stdoutLogFile="\\?\%home%\LogFiles\stdout" /> </system.webServer> </location></configuration>曾经的 AppSettings 节点可迁移到 appsettings.json,在这篇文章中有详解:https://docs.microsoft.com/en-us/aspnet/core/fundamentals/configuration/?view=aspnetcore-2.112、Session 和 CookieASP.NET Core 默认没有开启Session支持,你必须手工添加Session 支持。services.AddDistributedMemoryCache();services.AddSession(options =>{ options.IdleTimeout = TimeSpan.FromMinutes(20); options.Cookie.HttpOnly = true;});以及app.UseSession();设定和获取Session值:HttpContext.Session.SetString("CaptchaCode", result.CaptchaCode);HttpContext.Session.GetString("CaptchaCode");清除值:context.Session.Remove("CaptchaCode");详情参见:https://docs.microsoft.com/en-us/aspnet/core/fundamentals/app-state?view=aspnetcore-2.113、Html.Action我们曾经使用 Html.Action 去调用一个Action ,返回一个Partial View ,然后放在主要的View 中显示,比如layout页。这在Layout页面中的应用非常广泛,比如在一个博客系统中显示分类列表之类的小部件。@Html.Action("GetTreeList", "Category")在ASP.NET Core里,它被替换为了 ViewComponents,参见 https://docs.microsoft.com/en-us/aspnet/core/mvc/views/view-components一个要注意的地方是Invoke方法只能是 async 签名的:async Task<IViewComponentResult> InvokeAsync()但如果你的代码并不是天生异步的,为了不让编译器警报,你可以加入这行代码:await Task.CompletedTask;14、检查运行环境是 Debug 或 Release在我的老系统里,我使用 HttpContext.Current.IsDebuggingEnabled 去检查当前运行环境是否为Debug,并在标题栏上显示 “(Debug)” 字样。@if (HttpContext.Current.IsDebuggingEnabled){ <text>(Debug)</text>}在 ASP.NET Core 里,我们可以使用新的razor tag helper 去完成这件事<environment include="Development"> (Debug)</environment>在下面的章节里,你会看到更多razor tag helper 的用法。15、新的Razor Tag HelpersTag helper 可以帮助你讲老的HTML helper 简化为更加面向HTML可读的代码,例如一个表单,我们曾经要这样写:转换为 Tag Helpers 的结果是这样的:我个人最喜欢的功能是给JS或CSS文件自动增加版本字符串:<script src="~/js/app/ediblog.app.min.js" asp-append-version="true"></script>它的结果是:<script src="/js/app/ediblog.app.min.js?v=lvNJVuWBoD_RVZwyBT15T_i3_ZuEIaV_w0t7zI_UYxY"></script>新的razor 语法能够兼容以前的 HTML helpers,也就是说,你依然能在ASP.NET Core中毫无问题的使用老的 HTML helpers。如果你的应用迁移时间紧迫,你可以尽管先使用老代码,随后再逐步转换到Tag Helpers。完整的介绍和语法列表,可参见https://docs.microsoft.com/en-us/aspnet/core/mvc/views/tag-helpers/intro?view=aspnetcore-2.116、Anti-Forgery TokenAnti-forgery token 有一些改进。首先,你能够自定义cookie 以及字段的名字了。services.AddAntiforgery(options =>{ options.Cookie.Name = "X-CSRF-TOKEN-MOONGLADE"; options.FormFieldName = "CSRF-TOKEN-MOONGLADE-FORM";});第二,你再也不需要手工给每一个表单都增加这行代码了:@Html.AntiForgeryToken()如果你使用新的form tag helper,那么anti-forgery 字段会自动在输出到客户端时自动加上。但你依然需要在后台对应的Action上加上 [ValidateAntiForgeryToken] 属性。然而,有另一种自动给每一个POST请求都验证anti-forgery token 的办法。services.AddMvc(options =>options.Filters.Add(new AutoValidateAntiforgeryTokenAttribute()));或者你可以单独给一个 Controller 加上这个属性。[Authorize][AutoValidateAntiforgeryToken]public class ManageController : Controller17、对非Controller 使用依赖注入ASP.NET Core 有自带的 DI 框架可以用在 Controller 上。我们可以修改一个Controller 的构造函数去注入它运行所依赖的服务。public class HomeController : Controller{ private readonly IDateTime _dateTime; public HomeController(IDateTime dateTime) { _dateTime = dateTime; }}但这不意味着自带的DI框架只能用在Controller 上。对于其他类,你可以使用完全一样的DI,例如,我自定义的类,也可以使用构造函数注入:public class CommentService : MoongladeService{ private readonly EmailService _emailService; public CommentService(MoongladeDbContext context, ILogger<CommentService> logger, IOptions<AppSettings> settings, EmailService emailService) : base(context, logger, settings) { _emailService = emailService; } // ....}方法是,只要你把自定义的类注册到Startup.cs中的 DI 容器里即可。services.AddTransient<CommentService>();更多ASP.NET Core 依赖注入的使用方法参见 https://docs.microsoft.com/en-us/aspnet/core/mvc/controllers/dependency-injection?view=aspnetcore-2.118、API 行为不一致有些来自传统 ASP.NET 的代码可以无错误编译通过,但这不保证运行时能够成功。比如,这段来自ASP.NET (.NET Framework) 的代码在 ASP.NET Core 中会抛出异常:var buffer = new byte[context.Request.Body.Length];context.Request.Body.Read(buffer, 0, buffer.Length);var xml = Encoding.Default.GetString(buffer);它的结果是:System.NotSupportedException: Specified method is not supported.at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpRequestStream.get_Length()在.NET Core里,我们需要用一种不同的方式去实现:var xml = await new StreamReader(context.Request.Body, Encoding.Default).ReadToEndAsync();19、小心GDPR 带来的问题ASP.NET Core 2.1 默认添加了 GDPR 的支持,但也会给我们带来一些问题。关于GDPR可参见 https://docs.microsoft.com/en-us/aspnet/core/security/gdpr?view=aspnetcore-2.1主要问题是,在用户接受GDPR协议之前,Cookie 是不起作用的。你需要检查哪些Cookie是你应用运行所必须的,即时用户没有接受GDPR协议,并且把它们标记为IsEssential这是我博客系统中的一个例子:private void SetPostTrackingCookie(CookieNames cookieName, string id){ var options = new CookieOptions { Expires = DateTime.UtcNow.AddDays(1), SameSite = SameSiteMode.Strict, Secure = Request.IsHttps, // Mark as essential to pass GDPR // https://docs.microsoft.com/en-us/aspnet/core/security/gdpr?view=aspnetcore-2.1 IsEssential = true }; Response.Cookies.Append(cookieName.ToString(), id, options);}另一个问题是,如果你要使用Session,那么用户必须接受GDPR 策略,否则 Session是不工作的。因为 Session 需要依赖 Cookie 在客户端保存 SessionID 。20、热更新 Views在传统 ASP.NET MVC 中,Views 文件夹默认不会编译到 DLL 文件中,所以我们能够不需要编译整个应用就能更新razor页面。这在不需要更新C#代码的情况下仅修改文字或一些layout修改的场景下非常实用。我有时候也利用这个特性直接向生产环境发布一些修改后的页面。然而,ASP.NET Core 2.1 默认情况下会将我们的 Views 编译到DLL 中以提高性能。因此,你无法在服务器上直接修改一个视图,因为文件夹中根本就不存在 Views,只有一个 *.Views.dll:如果你仍然希望在ASP.NET Core中热更新Views,需要手工修改csproj文件:<PropertyGroup> <TargetFramework>netcoreapp2.1</TargetFramework> <RazorCompileOnBuild>false</RazorCompileOnBuild> <RazorCompileOnPublish>false</RazorCompileOnPublish></PropertyGroup>21、编译版本号自增长在传统 .NET 应用程序里,我们可以修改 “AssemblyInfo.cs” 在每次编译时自动增加版本号。这在编译服务器里十分常用。[assembly: AssemblyVersion("9.0.*")]结果是这样:9.0.6836.29475不幸的是,.NET Core 目前还没有一个自带的方法来完成这个操作。只有一个三方解决方案可能有用:https://github.com/BalassaMarton/MSBump总结ASP.NET Core 相对传统 ASP.NET 有了不少区别,目前也有一定的限制。本文仅涵盖了我自己所遇到的问题,也一定还有很多我没有遇到过的情况。本文转载自公众号文章:https://mp.weixin.qq.com/s/SxFAUV5_8xpJY6R8inLSvA
-
华为IoT教程和帮助文档给出的Demo唯独缺少.net的样例,在上次刚刚实现了Asp.net core作为服务对接。使用的Api接口:login/subscriptions/deviceCommands主动调用的接口deviceDataChanged/commandChanged提供给回调的服务调用OceanConnect接口特点header信息app_key为header必须的除了login其他接口的header必须带token请求ContentType分为2种application/x-www-form-urlencoded和application/json 请求必须携带认证证书(证书见附件,密码IoM@1234)基于以上可以总结出通用请求方法/// <summary> /// IoT Post请求 /// </summary> /// <param name="url">完整url</param> /// <param name="content">HttpContent或其子类</param> /// <param name="token">有效token</param> /// <returns></returns> public async Task<string> Post2(string url, HttpContent content, string token) { var handler = new HttpClientHandler { CheckCertificateRevocationList = false, ClientCertificateOptions = ClientCertificateOption.Manual, SslProtocols = SslProtocols.Tls | SslProtocols.Tls11 | SslProtocols.Tls12 }; content.Headers.Add("app_key", AppId); if (content is FormUrlEncodedContent) content.Headers.ContentType = new MediaTypeHeaderValue("application/x-www-form-urlencoded"); else if (content is StringContent) content.Headers.ContentType = new MediaTypeHeaderValue("application/json"); handler.ClientCertificates.Add(new X509Certificate2(CertificateFilePath, CertificatePassword)); handler.ServerCertificateCustomValidationCallback = (message, cert, chain, errors) => { return true; }; using (var client = new HttpClient(handler)) { if (!string.IsNullOrEmpty(token)) { var authValue = new AuthenticationHeaderValue("Bearer", token); client.DefaultRequestHeaders.Authorization = authValue; } HttpResponseMessage response = await client.PostAsync(url, content); response.EnsureSuccessStatusCode(); return await response.Content.ReadAsStringAsync(); } }登陆方法public LoginResult Login() { var url = "https://ip:port/iocm/app/sec/v1.1.0/login"; var dic = new Dictionary<string, string> { { "appId", AppId }, { "secret", Secret } }; var body = new FormUrlEncodedContent(dic); try { var result = helper.Post2(url, body, null).GetAwaiter().GetResult(); var login = JsonConvert.DeserializeObject<LoginResult>(result); Token = login.AccessToken; return login; } catch (Exception ex) { _log.LogError(ex, "Login 异常:"); return null; } }订阅deviceDataChanged消息public string Subscript() { CheckToken(); var url = "https://ip:port/iocm/app/sub/v1.2.0/subscriptions?ownerFlag=true"; var param = new Dictionary<string, string> { { "appId", AppId }, { "notifyType", "deviceDataChanged" }, { "callbackUrl", "http://ip:port/api/clock/DeviceDataChanged" }, { "channel", "http" } }; var body = JsonConvert.SerializeObject(param); try { var html = helper.Post2(url, new StringContent(body), Token).GetAwaiter().GetResult(); var result = JsonConvert.DeserializeObject<IoTSubscriptResult>(html); return html; } catch (Exception ex) { _log.LogError(ex, "Subscript 异常"); return ex.Message; } }一个通用的设备命令方法private bool SendDeviceCommands(IoTCmdReq param) { CheckToken(); var url = $"https://ip:port/iocm/app/cmd/v1.4.0/deviceCommands?appId={AppId}"; var body = JsonConvert.SerializeObject(param, new JsonSerializerSettings() { ContractResolver = new CamelCasePropertyNamesContractResolver() }); try { var html = helper.Post2(url, new StringContent(body), Token).GetAwaiter().GetResult(); var result = JsonConvert.DeserializeObject<IoTCmdResult>(html); var success = new List<IoTCmdStatus> { IoTCmdStatus.DELIVERED, IoTCmdStatus.PENDING, IoTCmdStatus.SENT, IoTCmdStatus.SUCCESSFUL }; return success.Contains(result.Status); } catch (Exception ex) { _log.LogError(ex, "SendDeviceCommands 异常"); return false; } }一个设备命令样例private bool SetCall(string content, string deviceId) { var param = new IoTCmdReq { DeviceId = deviceId, Command = new IoTCmd { ServiceId = "Call", Method = "Set_Call", Paras = new Dictionary<string, object> { { "content", content } } }, CallbackUrl = "http://ip:port/api/clock/CommandChanged", ExpireTime = 10, MaxRetransmit = 2 }; return SendDeviceCommands(param); }接收回调设备数据变化命令/// <summary> /// 订阅数据变化回调入口 /// </summary> [HttpPost] [Route("[action]")] public void DeviceDataChanged() { string inputbody; using (var reader = new System.IO.StreamReader(HttpContext.Request.Body, Encoding.UTF8)) { inputbody = reader.ReadToEnd(); } var reqdata = JsonConvert.DeserializeObject<IoTDataChangedReq>(inputbody); if (reqdata.Service.ServiceId == "Clock") { _service.Welcome(reqdata.Service.Data["card_no"].ToString(), reqdata.DeviceId); } else if (reqdata.Service.ServiceId == "Sensor") { } }
推荐直播
-
华为AI技术发展与挑战:集成需求分析的实战指南
2024/11/26 周二 18:20-20:20
Alex 华为云学堂技术讲师
本期直播将综合讨论华为AI技术的发展现状,技术挑战,并深入探讨华为AI应用开发过程中的需求分析过程,从理论到实践帮助开发者快速掌握华为AI应用集成需求的框架和方法。
去报名 -
华为云DataArts+DWS助力企业数据治理一站式解决方案及应用实践
2024/11/27 周三 16:30-18:00
Walter.chi 华为云数据治理DTSE技术布道师
想知道数据治理项目中,数据主题域如何合理划分?数据标准及主数据标准如何制定?数仓分层模型如何合理规划?华为云DataArts+DWS助力企业数据治理项目一站式解决方案和应用实践告诉您答案!本期将从数据趋势、数据治理方案、数据治理规划及落地,案例分享四个方面来助力企业数据治理项目合理咨询规划及顺利实施。
去报名
热门标签