You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ASP.NET MVC部署IIS后输入字符串格式错误排查与优化

ASP.NET MVC部署IIS后「输入字符串格式不正确」问题排查与解决

开发ASP.NET MVC应用时,本地运行正常,但部署到IIS后出现FormatException(输入字符串格式不正确),无法确定触发原因和具体代码行,以下是针对性的排查、优化与修复方案:

一、错误原因排查

  1. Session值类型不匹配:代码中直接调用Convert.ToInt32(Session[SessionKeys.UserCode]),若Session存储的不是可转换为int的内容,或IIS会话配置导致Session值异常,会触发格式错误。
  2. 可空类型的不安全操作:LineManager是int?类型,代码中多次直接调用ToString()或Convert.ToInt32(),未判断是否为null,可能引发转换异常。
  3. 模型属性缺失:Action中频繁使用resignationRequester.DirectManager,但ResignationRequester模型未定义该属性,导致其值为null,调用Convert.ToInt32(null)会抛出FormatException。
  4. 前端输入未校验:自动补全组件在无匹配结果时,返回用户输入的原始文本作为value,若用户提交非数字内容,会导致模型绑定或转换失败。
  5. 环境差异:本地与IIS的区域设置、Session存储模式不同,可能导致值的格式或有效性差异。

二、优化代码以显示清晰错误信息&避免错误

  1. 捕获详细异常信息:在catch块中返回堆栈跟踪,同时记录日志:
catch (FormatException ex)
{
    responseData.success = false;
    responseData.message = $"格式错误:{ex.Message},错误位置:{ex.StackTrace}";
    // 写入日志文件(生产环境建议用专业日志框架)
    System.IO.File.AppendAllText(Server.MapPath("~/Logs/error.log"), 
        $"{DateTime.Now:yyyy-MM-dd HH:mm:ss} - 错误详情:{ex.ToString()}\n");
}
  1. 使用安全转换方法:替换Convert.ToInt32为int.TryParse,提前处理无效值:
if (!int.TryParse(Session[SessionKeys.UserCode]?.ToString(), out int empId))
{
    responseData.message = "用户ID格式无效,请重新登录";
    return Json(responseData);
}
resignationRequester.EmpID = empId;
  1. 安全访问可空类型:通过HasValue判断后再操作,避免空引用或转换错误:
if (resignationRequester.LineManager.HasValue)
{
    string lineManagerStr = resignationRequester.LineManager.Value.ToString();
    if (lineManagerStr.Length < 6)
    {
        responseData.message = "Line Manager编号长度必须≥6";
        return Json(responseData);
    }
}
  1. 提前检查ModelState:在修改模型属性前验证绑定有效性,返回具体绑定错误:
if (!ModelState.IsValid)
{
    var errors = ModelState.Values
        .SelectMany(v => v.Errors)
        .Select(e => string.IsNullOrEmpty(e.ErrorMessage) ? e.Exception.Message : e.ErrorMessage);
    responseData.message = string.Join(";", errors);
    return Json(responseData);
}

三、定位触发错误的代码行

  1. 输出异常堆栈:在catch块中返回ex.StackTrace,直接获取错误发生的代码行号。
  2. 启用IIS详细错误:临时在web.config中设置<customErrors mode="Off"/>(仅调试环境),浏览器会显示完整错误页面,包含具体代码行。
  3. 添加调试日志:在关键转换代码前后写入日志,追踪变量值:
System.IO.File.AppendAllText(Server.MapPath("~/Logs/debug.log"), 
    $"[{DateTime.Now}] Session UserCode: {Session[SessionKeys.UserCode]}\n" +
    $"LineManager值: {resignationRequester.LineManager}\n");

四、修正代码中的错误解析逻辑

核心问题修复:

  1. 补充缺失的模型属性:在ResignationRequester中添加DirectManager属性:
public class ResignationRequester
{
    [Display(Name = "Employee No : ")]
    [Required]   
    public int EmpID { get; set; }
    
    [Display(Name = "Line Manager: ")]
    public int? LineManager { get; set; }
    
    // 添加缺失的DirectManager属性
    public int? DirectManager { get; set; }
}
  1. 重构Action中的验证逻辑:替换不安全转换,修正逻辑矛盾:
[HttpPost]
public JsonResult RequesterIndex(ResignationRequester resignationRequester)
{
    dynamic responseData = new ExpandoObject();
    responseData.success = false;
    responseData.message = "";
    try
    {
        // 校验Session有效性
        if (Session[SessionKeys.UserCode] == null)
        {
            responseData.message = "会话已过期,请重新登录";
            return Json(responseData);
        }
        
        // 安全转换Session用户ID
        if (!int.TryParse(Session[SessionKeys.UserCode]?.ToString(), out int empId))
        {
            responseData.message = "用户ID格式无效,请重新登录";
            return Json(responseData);
        }
        resignationRequester.EmpID = empId;
        
        // 模型绑定校验
        if (!ModelState.IsValid)
        {
            var errorMessages = ModelState.Values
                .SelectMany(v => v.Errors)
                .Select(e => string.IsNullOrEmpty(e.ErrorMessage) ? e.Exception?.Message : e.ErrorMessage);
            responseData.message = string.Join(";", errorMessages);
            return Json(responseData);
        }
        
        // LineManager非空校验与长度校验
        if (!resignationRequester.LineManager.HasValue)
        {
            responseData.message = "Line Manager不能为空";
            return Json(responseData);
        }
        string lineManagerStr = resignationRequester.LineManager.Value.ToString();
        if (lineManagerStr.Length < 6)
        {
            responseData.message = "Line Manager编号长度必须≥6";
            return Json(responseData);
        }
        
        // DirectManager非空校验
        if (!resignationRequester.DirectManager.HasValue)
        {
            responseData.message = "Direct Manager不能为空";
            return Json(responseData);
        }
        
        // 申请人与经理编号重复校验
        if (resignationRequester.EmpID == resignationRequester.DirectManager.Value &&
            resignationRequester.EmpID == resignationRequester.LineManager.Value)
        {
            responseData.message = "申请人编号不能与Line Manager、Direct Manager编号相同";
            return Json(responseData);
        }
        
        // 业务逻辑执行
        if (string.IsNullOrEmpty(ViewBag.errorMsg))
        {
            responseData.success = true;
            responseData.message = "辞职申请表提交成功";
            return Json(responseData);
        }
        responseData.message = ViewBag.errorMsg;
    }
    catch (Exception ex)
    {
        responseData.message = $"提交失败:{ex.Message}";
        System.IO.File.AppendAllText(Server.MapPath("~/Logs/error.log"), 
            $"{DateTime.Now:yyyy-MM-dd HH:mm:ss} - 错误详情:{ex.ToString()}\n");
    }
    return Json(responseData);
}
  1. 前端输入校验优化:禁止选择无效选项,清空非法输入:
$("#txtLineManagerId").autocomplete({
    source: function (request, response) {
        var searchText = $("#txtLineManagerId").val();
        $.ajax({
            url: '@Url.Action("GetAllEmployeeBasedSearchText", "Resignation")',
            data: { searchText: searchText },
            method: "GET",
            dataType: "json",
            success: function (data) {
                if (!data.length) {
                    response([]);
                    alert("未找到匹配的员工,请重新输入");
                } else {
                    response($.map(data, function (item) {
                        return {
                            label: `File No : ${item.EmployeeID} - Name : ${item.EmployeeName} - Designation : ${item.Designation}`,
                            value: item.EmployeeID,
                            employeeName: item.EmployeeName,
                            designation: item.Designation
                        };
                    }));
                }
            }
        });
    },
    position: { my: "right top", at: "right bottom" },
    appendTo: '#searchContainer',
    select: function (event, ui) {
        $("#LineManagerName").val(ui.item.employeeName);
    },
    minLength: 2,
    change: function(event, ui) {
        // 未选择有效选项时清空输入
        if (!ui.item) {
            $("#txtLineManagerId").val("");
            $("#LineManagerName").val("");
            alert("请选择有效的Line Manager");
        }
    }
}).data("ui-autocomplete")._renderItem = function (ul, item) {
    return $("<li>")
        .append(`<div>File No: ${item.value}<br/>Name: ${item.employeeName}<br/>Designation: ${item.designation}</div>`)
        .appendTo(ul);
};

内容的提问来源于stack exchange,提问作者ahmed abdelaziz

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.01 13:30:55