如何在ASP.NET Core中使用C#串口方法实现短信发送?
我来帮你梳理下如何把现有SerialPort短信代码集成到ASP.NET Core 2.0应用里,一步步来:
1. 封装短信发送逻辑为可复用服务
首先,把你原来的控制台代码改造成适合ASP.NET Core的服务类,这样既方便复用,也能利用依赖注入的优势。另外,把同步的Thread.Sleep换成异步的Task.Delay,避免阻塞应用的线程池线程:
using System.IO.Ports; using System.Threading.Tasks; public class SmsSender { public async Task SendSmsAsync(string phoneNumber, string message) { // 使用using语句确保串口资源自动释放,避免端口占用问题 using var serialPort = new SerialPort("COM2", 9600); try { serialPort.Open(); await Task.Delay(1000); // 异步等待,替代Thread.Sleep // 设置短信为文本模式 serialPort.Write("AT+CMGF=1\r"); await Task.Delay(1000); // 指定接收号码 serialPort.Write($"AT+CMGS=\"{phoneNumber}\"\r\n"); await Task.Delay(1000); // 发送消息内容+结束符 serialPort.Write(message + "\x1A"); await Task.Delay(1000); } finally { // 确保端口被关闭 if (serialPort.IsOpen) serialPort.Close(); } } }
然后在Startup.cs的ConfigureServices方法里注册这个服务,让ASP.NET Core可以注入它:
public void ConfigureServices(IServiceCollection services) { // 其他服务注册(比如MVC、数据库上下文) services.AddTransient<SmsSender>(); // 也可以用AddScoped,根据你的业务场景选择 }
2. 修改表单与Controller逻辑
你的现有表单只有消息输入框,需要添加电话号码输入项(如果聊天窗口已经关联了接收方号码,也可以从后台获取,不用前端输入)。先更新表单:
<form method="post"> <input asp-for="PhoneNumber" type="text" placeholder="输入接收号码..." class="form-control mb-2" /> <input asp-for="MessageBody" id="textInput" type="text" placeholder="输入消息内容..." class="form-control" /> <button asp-action="SendMessage" id="sendButton" class="btn btn-primary btn-block mt-2" type="submit">发送</button> </form>
创建对应的ViewModel来接收表单数据:
public class SmsMessageViewModel { public string PhoneNumber { get; set; } public string MessageBody { get; set; } }
接下来修改你的SendMessage方法,注入SmsSender,在保存数据库之后调用短信发送逻辑:
using Microsoft.AspNetCore.Mvc; using System.Threading.Tasks; public class ChatController : Controller { private readonly SmsSender _smsSender; private readonly YourDbContext _dbContext; // 你的数据库上下文 // 通过构造函数注入依赖 public ChatController(SmsSender smsSender, YourDbContext dbContext) { _smsSender = smsSender; _dbContext = dbContext; } [HttpPost] public async Task<IActionResult> SendMessage(SmsMessageViewModel model) { if (!ModelState.IsValid) { return View(model); } // 1. 原有逻辑:保存消息到数据库 var chatMessage = new ChatMessage { PhoneNumber = model.PhoneNumber, Content = model.MessageBody, SentTime = DateTime.Now }; _dbContext.ChatMessages.Add(chatMessage); await _dbContext.SaveChangesAsync(); // 2. 新增逻辑:发送短信 try { await _smsSender.SendSmsAsync(model.PhoneNumber, model.MessageBody); TempData["SuccessMsg"] = "短信发送成功!"; } catch (Exception ex) { // 处理异常,比如记录日志、给用户反馈 TempData["ErrorMsg"] = $"短信发送失败:{ex.Message}"; // 可以注入ILogger来记录详细日志,方便排查问题 // _logger.LogError(ex, "发送短信到{PhoneNumber}失败", model.PhoneNumber); } return RedirectToAction("Chat"); // 回到聊天页面 } }
3. 关键优化与注意事项
配置化管理:不要把COM端口、波特率硬编码,建议放到
appsettings.json里,通过配置绑定来读取,方便不同环境切换:"SmsSettings": { "PortName": "COM2", "BaudRate": 9600 }然后创建配置类并绑定:
public class SmsSettings { public string PortName { get; set; } public int BaudRate { get; set; } } // 在Startup.cs里绑定 services.Configure<SmsSettings>(Configuration.GetSection("SmsSettings"));最后在
SmsSender里注入IOptions<SmsSettings>来使用配置。权限问题:如果应用部署在服务器上,ASP.NET Core的运行进程需要有访问串口的权限(Windows下要给IIS应用池用户权限,Linux下要给用户添加dialout组)。
异步优先:全程使用异步方法,避免同步阻塞影响应用的并发能力。
异常处理:一定要捕获串口操作可能出现的异常(比如端口不存在、权限不足、调制解调器无响应等),给用户清晰的反馈,同时记录日志方便排查问题。
内容的提问来源于stack exchange,提问作者Daniel 沤eimo

