.NET 4.8 ASP.NET MVC项目中如何将用户输入订单号传入SQL Server存储过程实现扫描状态更新及错误处理
.NET 4.8 ASP.NET MVC项目中如何将用户输入订单号传入SQL Server存储过程实现扫描状态更新及错误处理
兄弟,我看了你这段代码和需求,确实新手容易踩这些坑,咱们一步步来把问题捋清楚、改好。首先你的存储过程本身在数据库能跑,但代码端完全没用到它,而且参数传递、方法设计都有不少问题,咱们一个个解决:
第一步:先修存储过程的小bug
你说存储过程能跑,但仔细看有几处语法和拼写问题,先把这些改了:
Use [testDB] GO SET ANSI_NULL ON GO SET QUOTED_IDENTIFIER ON GO ALTER PROCEDURE [dbo].[UpdateScanStatus] @OrderNumber varchar(8) AS BEGIN SET NOCOUNT ON; -- 加上这个避免返回额外的行数消息,干扰逻辑 IF EXISTS (SELECT 1 FROM Orders WHERE Order_Number = @OrderNumber) Begin DECLARE @ScanStatus BIT; SELECT @ScanStatus = Scan_Status -- 修正列名拼写:原代码写的ScanStatus,数据库列是Scan_Status FROM Orders WHERE Order_Number = @OrderNumber -- 修正参数名:原代码写的@Order_Number,存储过程参数是@OrderNumber IF @ScanStatus = 1 BEGIN RAISERROR('Order is already scanned!', 16, 1); -- Severity用16更合适,23会强制断开数据库连接 END ELSE BEGIN UPDATE Orders SET Scan_Status = 1 WHERE Order_Number = @OrderNumber PRINT 'Successful!'; END END ELSE BEGIN RAISERROR('Order does not exist!', 16, 1); -- 补上逗号:原代码少了逗号导致语法错误 END END;
第二步:重构Controller逻辑,真正调用存储过程
你之前的Controller写了static方法,而且完全没调用存储过程,而是自己写了UPDATE语句,还错误地把XML数据传给了订单号参数,这肯定跑不通。咱们改成标准的MVC Action,处理用户输入、调用存储过程、把结果返回给视图:
using Microsoft.AspNetCore.Mvc; using Microsoft.Data.SqlClient; using System.Data; namespace WebApplication1.Controllers { public class ScanController : Controller { // 建议把连接字符串放到web.config里,这里暂时用你的配置 private readonly string _connectionString = "Data Source=SBSQL;User ID=SpeedPass;Password=********;Connect Timeout=30;Encrypt=False;Trust Server Certificate=False;Application Intent=ReadWrite;Multi Subnet Failover=False"; // 显示订单号输入表单 public IActionResult Index() { return View(); } // 处理扫描提交的POST请求 [HttpPost] public IActionResult SubmitScan(string orderNumber) { // 先校验用户输入 if (string.IsNullOrWhiteSpace(orderNumber) || orderNumber.Length != 8) { ModelState.AddModelError("", "请输入有效的8位订单号"); return View("Index"); } try { using (SqlConnection connection = new SqlConnection(_connectionString)) { using (SqlCommand command = new SqlCommand("[dbo].[UpdateScanStatus]", connection)) { // 关键:指定命令类型是存储过程 command.CommandType = CommandType.StoredProcedure; // 添加存储过程需要的订单号参数 command.Parameters.Add("@OrderNumber", SqlDbType.VarChar, 8).Value = orderNumber.Trim(); connection.Open(); command.ExecuteNonQuery(); // 没有抛出异常就说明执行成功 ViewBag.SuccessMessage = "扫描成功!"; } } } catch (SqlException ex) { // 捕获存储过程抛出的错误信息 string errorMsg = string.Empty; foreach (SqlError error in ex.Errors) { errorMsg += error.Message + " "; } ModelState.AddModelError("", errorMsg.Trim()); return View("Index"); } catch (Exception ex) { ModelState.AddModelError("", $"系统错误:{ex.Message}"); return View("Index"); } return View("Index"); } } }
第三步:添加对应的视图(显示表单和提示)
在Views/Scan文件夹下创建Index.cshtml,用来展示输入表单和错误/成功提示:
@{ ViewBag.Title = "订单扫描"; } <h2>订单扫描</h2> @using (Html.BeginForm("SubmitScan", "Scan", FormMethod.Post)) { <div class="form-group mt-3"> @Html.Label("订单号", new { @class = "form-label" }) @Html.TextBox("orderNumber", null, new { @class = "form-control", placeholder = "请输入8位订单号", maxlength = 8 }) @Html.ValidationMessage("", new { @class = "text-danger mt-1" }) </div> <button type="submit" class="btn btn-primary mt-2">确认扫描</button> } @if (!string.IsNullOrEmpty(ViewBag.SuccessMessage)) { <div class="alert alert-success mt-3">@ViewBag.SuccessMessage</div> }
关键问题说明
为什么之前的代码不行?
- 你没有调用存储过程,而是自己写了UPDATE语句,完全偏离了需求;
- 错误地把XML数据传给了订单号参数,导致数据库根本找不到对应订单;
- static方法无法和MVC的视图、ModelState交互,没法把错误信息返回给用户;
- 异常处理只在控制台输出,用户看不到任何反馈。
存储过程的Severity级别
之前用23会强制断开数据库连接,用16是标准的用户级错误提示,不会中断连接。连接字符串的最佳实践
不要把连接字符串硬编码在代码里,放到web.config的<connectionStrings>节点中,方便后续修改。
备注:内容来源于stack exchange,提问作者CodeHopperComeT
相关产品推荐
相关产品推荐

