这个事情就是一个坑,耽误了两周时间,之前并没有做过ActiveX这玩意,现在客户需求如此,只能说是在网上看着教程做了。
事情是这样的,有一台海康威视的摄像头,客户需要一个ActiveX控件嵌入到网页中,通过点击按钮开始录制和结束录制来进行视频的录制和保存,关于海康摄像头的二次开发在此就不多说了,可以参考SDK中的说明。
直接上流程:
1.开发环境:
VS2010,这个打包方便,之前用VS2013打包的,总是调用不了,不知道原因是什么;SDK是32位的,用64位的在Winform中可以正常使用,在网页中使用控件时会报错。
2.新建项目:
新建一个类库项目,如下:
右键点击项目,添加“用户控件”,如下:
界面拖控件,如下:
控件代码如下,其中Guid是“工具”->“创建GUID”自动生成的,#region->#endregion折叠部分是实现的IObjectSafety接口
using System; namespace VideoHelper { [System.Security.SecuritySafeCritical] public class Videos { private bool m_initSDK = false; /// <summary> /// 正在录制 /// </summary> private bool m_Record = false; private uint LastErr = 0; private Int32 m_RealHandle = -1; private Int32 m_lUserID = -1; public IntPtr handle { get; set; } public bool Initialize(string ip = "192.168.1.64", int port = 8000, string username = "admin", string password = "8910jqk#") { try { m_initSDK = CHCNetSDK.NET_DVR_Init(); if (m_initSDK) { CHCNetSDK.NET_DVR_SetLogToFile(3, "C:\\SdkLog\\", true); //设备参数结构体 CHCNetSDK.NET_DVR_DEVICEINFO_V30 DeviceInfo = new CHCNetSDK.NET_DVR_DEVICEINFO_V30(); //注册设备 m_lUserID = CHCNetSDK.NET_DVR_Login_V30(ip, port, username, password, ref DeviceInfo); return m_lUserID >= 0; } return false; } catch (Exception ex) { System.Windows.Forms.MessageBox.Show("Initialize:" + ex.Message); return false; } } public bool Start(IntPtr handle, string filename) { try { CHCNetSDK.NET_DVR_PREVIEWINFO lpPreviewInfo = new CHCNetSDK.NET_DVR_PREVIEWINFO(); lpPreviewInfo.lChannel = 1; lpPreviewInfo.dwLinkMode = 0; lpPreviewInfo.dwStreamType = 0; lpPreviewInfo.bBlocked = true; lpPreviewInfo.dwDisplayBufNum = 15; lpPreviewInfo.hPlayWnd = handle; IntPtr pUser = IntPtr.Zero;//new IntPtr(); //获取实时视频流 m_RealHandle = CHCNetSDK.NET_DVR_RealPlay_V40(m_lUserID, ref lpPreviewInfo, null, pUser); if (m_Record == false) { CHCNetSDK.NET_DVR_MakeKeyFrame(m_lUserID, 1); if (!CHCNetSDK.NET_DVR_SaveRealData(m_RealHandle, filename)) { LastErr = CHCNetSDK.NET_DVR_GetLastError(); return false; } else { m_Record = true; return true; } } else { return false; } } catch { return false; } } public bool End() { if (m_Record) { if (!CHCNetSDK.NET_DVR_StopSaveRealData(m_RealHandle)) { LastErr = CHCNetSDK.NET_DVR_GetLastError(); return false; } m_Record = false; m_RealHandle = -1; return true; } else { return false; } } public void Dispose() { try { if (m_lUserID >= 0) { CHCNetSDK.NET_DVR_Logout_V30(m_lUserID); m_lUserID = -1; } if (m_RealHandle >= 0) { CHCNetSDK.NET_DVR_StopRealPlay(m_RealHandle); m_RealHandle = -1; } CHCNetSDK.NET_DVR_Cleanup(); } catch { } } } } 录制视频操作类
录制视频操作类
using System; using System.Runtime.InteropServices; namespace VideoHelper { [ComImport, GuidAttribute("CB5BDC81-93C1-11CF-8F20-00805F2CD064")] [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)] public interface IObjectSafety { [PreserveSig] int GetInterfaceSafetyOptions(ref Guid riid, [MarshalAs(UnmanagedType.U4)] ref int pdwSupportedOptions, [MarshalAs(UnmanagedType.U4)] ref int pdwEnabledOptions); [PreserveSig()] int SetInterfaceSafetyOptions(ref Guid riid, [MarshalAs(UnmanagedType.U4)] int dwOptionSetMask, [MarshalAs(UnmanagedType.U4)] int dwEnabledOptions); } } 接口代码
using System; using System.Windows.Forms; using System.IO; using System.Runtime.InteropServices; namespace VideoHelper { [System.Security.SecuritySafeCritical] [Guid("79629620-3C0C-4D47-B93B-2D36AEF8EF31")] public partial class VideoControl : UserControl,IObjectSafety { public VideoControl() { InitializeComponent(); } string videopath = Environment.CurrentDirectory; Videos video; IntPtr handle; private void btnLogin_Click(object sender, EventArgs e) { if (btnLogin.Text == "登录") { try { if (string.IsNullOrWhiteSpace(this.txtIP.Text)) { MessageBox.Show("IP地址不能为空!"); return; } if (string.IsNullOrWhiteSpace(this.txtUserID.Text)) { MessageBox.Show("用户名不能为空!"); return; } if (string.IsNullOrWhiteSpace(this.txtPwd.Text)) { MessageBox.Show("密码不能为空!"); return; } video = new Videos(); if (video.Initialize(this.txtIP.Text, Convert.ToInt32(this.numericUpDown1.Value), this.txtUserID.Text, this.txtPwd.Text)) { this.btnLogin.Text = "注销"; MessageBox.Show("登录成功!"); this.btnStart.Enabled = true; this.btnSave.Enabled = true; } else { MessageBox.Show("登录失败!"); } } catch (Exception ee) { MessageBox.Show("登录异常:" + ee.Message); } } else if (btnLogin.Text == "注销") { try { video.Dispose(); this.btnLogin.Text = "登录"; this.btnStart.Enabled = false; this.btnSave.Enabled = false; } catch (Exception ee) { MessageBox.Show("注销异常:" + ee.Message); } } } private void btnStart_Click(object sender, EventArgs e) { try { string filename = txtFile.Text.Trim(); if (filename.IndexOfAny(Path.GetInvalidFileNameChars()) >= 0 || string.IsNullOrWhiteSpace(filename)) { MessageBox.Show("文件名含有非法字符或空格,请重新输入"); txtFile.Focus(); return; } video.Start(handle, filename + comboBox1.SelectedItem.ToString()); this.btnStart.Enabled = false; this.btnSave.Enabled = true; } catch (Exception ee) { MessageBox.Show("异常:" + ee.Message); } } private void btnSave_Click(object sender, EventArgs e) { try { if (video.End()) { MessageBox.Show("视频已保存!"); this.btnStart.Enabled = true; this.btnSave.Enabled = false; } else { MessageBox.Show("保存失败!"); this.btnStart.Enabled = true; this.btnSave.Enabled = true; } } catch (Exception ee) { MessageBox.Show("异常:" + ee.Message); } } private void button1_Click(object sender, EventArgs e) { try { System.Diagnostics.Process.Start(videopath); } catch { } } private void VideoControl_Load(object sender, EventArgs e) { this.comboBox1.SelectedItem = ".mp4"; this.handle = pictureBox1.Handle; this.btnStart.Enabled = false; this.btnSave.Enabled = false; } #region IObjectSafety 成员 private const string _IID_IDispatch = "{00020400-0000-0000-C000-000000000046}"; private const string _IID_IDispatchEx = "{a6ef9860-c720-11d0-9337-00a0c90dcaa9}"; private const string _IID_IPersistStorage = "{0000010A-0000-0000-C000-000000000046}"; private const string _IID_IPersistStream = "{00000109-0000-0000-C000-000000000046}"; private const string _IID_IPersistPropertyBag = "{37D84F60-42CB-11CE-8135-00AA004BB851}"; private const int INTERFACESAFE_FOR_UNTRUSTED_CALLER = 0x00000001; private const int INTERFACESAFE_FOR_UNTRUSTED_DATA = 0x00000002; private const int S_OK = 0; private const int E_FAIL = unchecked((int)0x80004005); private const int E_NOINTERFACE = unchecked((int)0x80004002); private bool _fSafeForScripting = true; private bool _fSafeForInitializing = true; public int GetInterfaceSafetyOptions(ref Guid riid, ref int pdwSupportedOptions, ref int pdwEnabledOptions) { int Rslt = E_FAIL; string strGUID = riid.ToString("B"); pdwSupportedOptions = INTERFACESAFE_FOR_UNTRUSTED_CALLER | INTERFACESAFE_FOR_UNTRUSTED_DATA; switch (strGUID) { case _IID_IDispatch: case _IID_IDispatchEx: Rslt = S_OK; pdwEnabledOptions = 0; if (_fSafeForScripting == true) pdwEnabledOptions = INTERFACESAFE_FOR_UNTRUSTED_CALLER; break; case _IID_IPersistStorage: case _IID_IPersistStream: case _IID_IPersistPropertyBag: Rslt = S_OK; pdwEnabledOptions = 0; if (_fSafeForInitializing == true) pdwEnabledOptions = INTERFACESAFE_FOR_UNTRUSTED_DATA; break; default: Rslt = E_NOINTERFACE; break; } return Rslt; } public int SetInterfaceSafetyOptions(ref Guid riid, int dwOptionSetMask, int dwEnabledOptions) { int Rslt = E_FAIL; string strGUID = riid.ToString("B"); switch (strGUID) { case _IID_IDispatch: case _IID_IDispatchEx: if (((dwEnabledOptions & dwOptionSetMask) == INTERFACESAFE_FOR_UNTRUSTED_CALLER) && (_fSafeForScripting == true)) Rslt = S_OK; break; case _IID_IPersistStorage: case _IID_IPersistStream: case _IID_IPersistPropertyBag: if (((dwEnabledOptions & dwOptionSetMask) == INTERFACESAFE_FOR_UNTRUSTED_DATA) && (_fSafeForInitializing == true)) Rslt = S_OK; break; default: Rslt = E_NOINTERFACE; break; } return Rslt; } #endregion } } 控件代码
namespace VideoHelper { partial class VideoControl { /// <summary> /// 必需的设计器变量。 /// </summary> private System.ComponentModel.IContainer components = null; /// <summary> /// 清理所有正在使用的资源。 /// </summary> /// <param name="disposing">如果应释放托管资源,为 true;否则为 false。</param> protected override void Dispose(bool disposing) { if (disposing && (components != null)) { components.Dispose(); } base.Dispose(disposing); } #region 组件设计器生成的代码 /// <summary> /// 设计器支持所需的方法 - 不要 /// 使用代码编辑器修改此方法的内容。 /// </summary> private void InitializeComponent() { this.button1 = new System.Windows.Forms.Button(); this.comboBox1 = new System.Windows.Forms.ComboBox(); this.label4 = new System.Windows.Forms.Label(); this.txtFile = new System.Windows.Forms.TextBox(); this.btnSave = new System.Windows.Forms.Button(); this.btnStart = new System.Windows.Forms.Button(); this.btnLogin = new System.Windows.Forms.Button(); this.label3 = new System.Windows.Forms.Label(); this.txtPwd = new System.Windows.Forms.TextBox(); this.label2 = new System.Windows.Forms.Label(); this.txtUserID = new System.Windows.Forms.TextBox(); this.label1 = new System.Windows.Forms.Label(); this.numericUpDown1 = new System.Windows.Forms.NumericUpDown(); this.IP = new System.Windows.Forms.Label(); this.txtIP = new System.Windows.Forms.TextBox(); this.pictureBox1 = new System.Windows.Forms.PictureBox(); ((System.ComponentModel.ISupportInitialize)(this.numericUpDown1)).BeginInit(); ((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).BeginInit(); this.SuspendLayout(); // // button1 // this.button1.Cursor = System.Windows.Forms.Cursors.Hand; this.button1.Font = new System.Drawing.Font("微软雅黑", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134))); this.button1.Location = new System.Drawing.Point(377, 360); this.button1.Name = "button1"; this.button1.Size = new System.Drawing.Size(138, 22); this.button1.TabIndex = 58; this.button1.Text = "打开视频存放位置"; this.button1.UseVisualStyleBackColor = true; this.button1.Click += new System.EventHandler(this.button1_Click); // // comboBox1 // this.comboBox1.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; this.comboBox1.FlatStyle = System.Windows.Forms.FlatStyle.Flat; this.comboBox1.Font = new System.Drawing.Font("微软雅黑", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134))); this.comboBox1.FormattingEnabled = true; this.comboBox1.Items.AddRange(new object[] { ".mp4", ".avi", ".wmv", ".3gp", ".flv"}); this.comboBox1.Location = new System.Drawing.Point(303, 361); this.comboBox1.Name = "comboBox1"; this.comboBox1.Size = new System.Drawing.Size(55, 25); this.comboBox1.TabIndex = 57; // // label4 // this.label4.AutoSize = true; this.label4.Font = new System.Drawing.Font("微软雅黑", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134))); this.label4.Location = new System.Drawing.Point(14, 360); this.label4.Name = "label4"; this.label4.Size = new System.Drawing.Size(116, 17); this.label4.TabIndex = 56; this.label4.Text = "请输入视频文件名:"; // // txtFile // this.txtFile.Location = new System.Drawing.Point(136, 360); this.txtFile.Name = "txtFile"; this.txtFile.Size = new System.Drawing.Size(161, 21); this.txtFile.TabIndex = 55; // // btnSave // this.btnSave.Cursor = System.Windows.Forms.Cursors.Hand; this.btnSave.Font = new System.Drawing.Font("微软雅黑", 10.5F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134))); this.btnSave.Location = new System.Drawing.Point(490, 298); this.btnSave.Name = "btnSave"; this.btnSave.Size = new System.Drawing.Size(57, 45); this.btnSave.TabIndex = 54; this.btnSave.Text = "保存"; this.btnSave.UseVisualStyleBackColor = true; this.btnSave.Click += new System.EventHandler(this.btnSave_Click); // // btnStart // this.btnStart.Cursor = System.Windows.Forms.Cursors.Hand; this.btnStart.Font = new System.Drawing.Font("微软雅黑", 10.5F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134))); this.btnStart.Location = new System.Drawing.Point(421, 298); this.btnStart.Name = "btnStart"; this.btnStart.Size = new System.Drawing.Size(57, 45); this.btnStart.TabIndex = 53; this.btnStart.Text = "录制"; this.btnStart.UseVisualStyleBackColor = true; this.btnStart.Click += new System.EventHandler(this.btnStart_Click); // // btnLogin // this.btnLogin.Cursor = System.Windows.Forms.Cursors.Hand; this.btnLogin.Font = new System.Drawing.Font("微软雅黑", 10.5F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134))); this.btnLogin.Location = new System.Drawing.Point(352, 298); this.btnLogin.Name = "btnLogin"; this.btnLogin.Size = new System.Drawing.Size(57, 45); this.btnLogin.TabIndex = 52; this.btnLogin.Text = "登录"; this.btnLogin.UseVisualStyleBackColor = true; this.btnLogin.Click += new System.EventHandler(this.btnLogin_Click); // // label3 // this.label3.AutoSize = true; this.label3.Font = new System.Drawing.Font("微软雅黑", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134))); this.label3.Location = new System.Drawing.Point(172, 325); this.label3.Name = "label3"; this.label3.Size = new System.Drawing.Size(44, 17); this.label3.TabIndex = 51; this.label3.Text = "密码:"; // // txtPwd // this.txtPwd.Location = new System.Drawing.Point(221, 322); this.txtPwd.Name = "txtPwd"; this.txtPwd.PasswordChar = '*'; this.txtPwd.Size = new System.Drawing.Size(115, 21); this.txtPwd.TabIndex = 50; this.txtPwd.Text = "8910jqk#"; this.txtPwd.UseSystemPasswordChar = true; // // label2 // this.label2.AutoSize = true; this.label2.Font = new System.Drawing.Font("微软雅黑", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134))); this.label2.Location = new System.Drawing.Point(8, 322); this.label2.Name = "label2"; this.label2.Size = new System.Drawing.Size(44, 17); this.label2.TabIndex = 49; this.label2.Text = "用户名"; // // txtUserID // this.txtUserID.Location = new System.Drawing.Point(66, 322); this.txtUserID.Name = "txtUserID"; this.txtUserID.Size = new System.Drawing.Size(100, 21); this.txtUserID.TabIndex = 48; this.txtUserID.Text = "admin"; // // label1 // this.label1.AutoSize = true; this.label1.Font = new System.Drawing.Font("微软雅黑", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134))); this.label1.Location = new System.Drawing.Point(172, 295); this.label1.Name = "label1"; this.label1.Size = new System.Drawing.Size(44, 17); this.label1.TabIndex = 47; this.label1.Text = "端口:"; // // numericUpDown1 // this.numericUpDown1.Location = new System.Drawing.Point(222, 295); this.numericUpDown1.Maximum = new decimal(new int[] { 65535, 0, 0, 0}); this.numericUpDown1.Minimum = new decimal(new int[] { 1, 0, 0, 0}); this.numericUpDown1.Name = "numericUpDown1"; this.numericUpDown1.Size = new System.Drawing.Size(114, 21); this.numericUpDown1.TabIndex = 46; this.numericUpDown1.Value = new decimal(new int[] { 8000, 0, 0, 0}); // // IP // this.IP.AutoSize = true; this.IP.Font = new System.Drawing.Font("微软雅黑", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134))); this.IP.Location = new System.Drawing.Point(20, 295); this.IP.Name = "IP"; this.IP.Size = new System.Drawing.Size(19, 17); this.IP.TabIndex = 45; this.IP.Text = "IP"; // // txtIP // this.txtIP.Location = new System.Drawing.Point(66, 295); this.txtIP.Name = "txtIP"; this.txtIP.Size = new System.Drawing.Size(100, 21); this.txtIP.TabIndex = 44; this.txtIP.Text = "192.168.1.64"; // // pictureBox1 // this.pictureBox1.Location = new System.Drawing.Point(5, 5); this.pictureBox1.Name = "pictureBox1"; this.pictureBox1.Size = new System.Drawing.Size(542, 269); this.pictureBox1.TabIndex = 43; this.pictureBox1.TabStop = false; // // VideoControl // this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; this.Controls.Add(this.button1); this.Controls.Add(this.comboBox1); this.Controls.Add(this.label4); this.Controls.Add(this.txtFile); this.Controls.Add(this.btnSave); this.Controls.Add(this.btnStart); this.Controls.Add(this.btnLogin); this.Controls.Add(this.label3); this.Controls.Add(this.txtPwd); this.Controls.Add(this.label2); this.Controls.Add(this.txtUserID); this.Controls.Add(this.label1); this.Controls.Add(this.numericUpDown1); this.Controls.Add(this.IP); this.Controls.Add(this.txtIP); this.Controls.Add(this.pictureBox1); this.Name = "VideoControl"; this.Size = new System.Drawing.Size(556, 398); this.Load += new System.EventHandler(this.VideoControl_Load); ((System.ComponentModel.ISupportInitialize)(this.numericUpDown1)).EndInit(); ((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).EndInit(); this.ResumeLayout(false); this.PerformLayout(); } #endregion private System.Windows.Forms.Button button1; private System.Windows.Forms.ComboBox comboBox1; private System.Windows.Forms.Label label4; private System.Windows.Forms.TextBox txtFile; private System.Windows.Forms.Button btnSave; private System.Windows.Forms.Button btnStart; private System.Windows.Forms.Button btnLogin; private System.Windows.Forms.Label label3; private System.Windows.Forms.TextBox txtPwd; private System.Windows.Forms.Label label2; private System.Windows.Forms.TextBox txtUserID; private System.Windows.Forms.Label label1; private System.Windows.Forms.NumericUpDown numericUpDown1; private System.Windows.Forms.Label IP; private System.Windows.Forms.TextBox txtIP; private System.Windows.Forms.PictureBox pictureBox1; } } 控件设计器代码
控件设计器代码
至此,此项目结束。
右键点击解决方案,添加新项目,如下,至于为什么建立两个项目,我一会儿在下面解释,
在HkHelper项目中添加类CHCNetSDK.cs,此类是海康提供的,可以在官网找到
接下来,最重要的,项目属性设置如下,两个项目都要设置:
至此,自定义控件已经完成,接下来就是打包,新建一个安装项目:
右键点击安装项目,“添加”->“项目输出”,并选择自定义控件的项目,然后确定
然后添加海康提供的SDK的库文件文件夹下的所有文件和文件夹到项目中,如下:
然后生成项目,会生成setup.exe和SetupVideo.msi两个文件,然后用打包文件,把这两个文件打包称cab文件就OK了
打包文件一共三个cabarc.exe、build.bat、install.inf
build.bat文件:
"cabarc.exe" n VideoSetup.cab SetupVideo.msi install.inf
install.inf文件:
[version] signature="$CHICAGO$"AdvancedINF=2.0[Setup Hooks] hook1=hook1 [hook1] run=msiexec.exe /i "%EXTRACT_DIR%\SetupVideo.msi" /qn
cabarc.exe是微软提供的工具
最后说一下为什么要分为两个项目去实现控件,那是因为如果在一个项目中的话,调用海康动态库的类CHCNetSDK.cs不能进行COM注册
以上是C#制作ActiveX控件中如何调用海康SDK的问题解决的详细内容。更多信息请关注PHP中文网其他相关文章!

c#.netissutableforenterprise-levelapplications withemofrosoftecosystemdueToItsStrongTyping,richlibraries,androbustperraries,androbustperformance.however,itmaynotbeidealfoross-platement forment forment forment forvepentment offependment dovelopment toveloperment toveloperment whenrawspeedsportor whenrawspeedseedpolitical politionalitable,

C#在.NET中的编程过程包括以下步骤:1)编写C#代码,2)编译为中间语言(IL),3)由.NET运行时(CLR)执行。C#在.NET中的优势在于其现代化语法、强大的类型系统和与.NET框架的紧密集成,适用于从桌面应用到Web服务的各种开发场景。

C#是一种现代、面向对象的编程语言,由微软开发并作为.NET框架的一部分。1.C#支持面向对象编程(OOP),包括封装、继承和多态。2.C#中的异步编程通过async和await关键字实现,提高应用的响应性。3.使用LINQ可以简洁地处理数据集合。4.常见错误包括空引用异常和索引超出范围异常,调试技巧包括使用调试器和异常处理。5.性能优化包括使用StringBuilder和避免不必要的装箱和拆箱。

C#.NET应用的测试策略包括单元测试、集成测试和端到端测试。1.单元测试确保代码的最小单元独立工作,使用MSTest、NUnit或xUnit框架。2.集成测试验证多个单元组合的功能,常用模拟数据和外部服务。3.端到端测试模拟用户完整操作流程,通常使用Selenium进行自动化测试。

C#高级开发者面试需要掌握异步编程、LINQ、.NET框架内部工作原理等核心知识。1.异步编程通过async和await简化操作,提升应用响应性。2.LINQ以SQL风格操作数据,需注意性能。3..NET框架的CLR管理内存,垃圾回收需谨慎使用。

C#.NET面试问题和答案包括基础知识、核心概念和高级用法。1)基础知识:C#是微软开发的面向对象语言,主要用于.NET框架。2)核心概念:委托和事件允许动态绑定方法,LINQ提供强大查询功能。3)高级用法:异步编程提高响应性,表达式树用于动态代码构建。

C#.NET是构建微服务的热门选择,因为其生态系统强大且支持丰富。1)使用ASP.NETCore创建RESTfulAPI,处理订单创建和查询。2)利用gRPC实现微服务间的高效通信,定义和实现订单服务。3)通过Docker容器化微服务,简化部署和管理。

C#和.NET的安全最佳实践包括输入验证、输出编码、异常处理、以及身份验证和授权。1)使用正则表达式或内置方法验证输入,防止恶意数据进入系统。2)输出编码防止XSS攻击,使用HttpUtility.HtmlEncode方法。3)异常处理避免信息泄露,记录错误但不返回详细信息给用户。4)使用ASP.NETIdentity和Claims-based授权保护应用免受未授权访问。


热AI工具

Undresser.AI Undress
人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover
用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool
免费脱衣服图片

Clothoff.io
AI脱衣机

AI Hentai Generator
免费生成ai无尽的。

热门文章

热工具

螳螂BT
Mantis是一个易于部署的基于Web的缺陷跟踪工具,用于帮助产品缺陷跟踪。它需要PHP、MySQL和一个Web服务器。请查看我们的演示和托管服务。

记事本++7.3.1
好用且免费的代码编辑器

MinGW - 适用于 Windows 的极简 GNU
这个项目正在迁移到osdn.net/projects/mingw的过程中,你可以继续在那里关注我们。MinGW:GNU编译器集合(GCC)的本地Windows移植版本,可自由分发的导入库和用于构建本地Windows应用程序的头文件;包括对MSVC运行时的扩展,以支持C99功能。MinGW的所有软件都可以在64位Windows平台上运行。

PhpStorm Mac 版本
最新(2018.2.1 )专业的PHP集成开发工具

SublimeText3汉化版
中文版,非常好用