🌹欢迎来到《小5讲堂》🌹
🌹这是《C#》系列文章,每篇文章将以博主理解的角度展开讲解。🌹
🌹温馨提示:博主能力有限,理解水平有限,若有不对之处望指正!🌹

在这里插入图片描述

前言

尽管博主工作了十来年,但是有些知识点还是容易忽略。
比如这次遇到的后端接收参数问题,居然因为一个传递数据类型导致整个实体参数值为null.

在这里插入图片描述

后端为空整型参数,前端传递过来的是空字符串,导致无法解析,所以整个实体类接收对象为null
解决方案是,要么不传参数ID,要不ID这个参数赋值为0.

问题分析

好的,这个问题在 C# MVC 中非常典型。当 JSON 反序列化器遇到一个期望是 int 的字段却收到了空字符串 "" 时,它无法完成转换,从而导致整个模型绑定失败,模型对象为 null

你提出的两种思路(不传或传0)是正确的。以下是针对 C# MVC 的详细解决方案:


方案一:前端处理(推荐且最清晰)

在前端(JavaScript)发送数据之前,确保整型字段不是空字符串。

使用 JavaScript 处理:

// 假设这是你要发送的数据对象
let formData = {
    id: "", // 前端可能由于输入框清空而变成空字符串
    name: "Test Name",
    age: ""
};

// 在发送前清理数据
function cleanData(data) {
    const cleaned = { ...data };
    for (const key in cleaned) {
        // 将空字符串转换为 null 或直接删除
        if (cleaned[key] === "") {
            // 方式1: 转换为 null (需要后端配合使用 int?)
            cleaned[key] = null;
            
            // 方式2: 转换为 0
            // cleaned[key] = 0;
            
            // 方式3: 直接删除该属性(推荐,让后端用默认值)
            // delete cleaned[key];
        }
    }
    return cleaned;
}

// 使用清理后的数据发送请求
fetch('/YourController/YourAction', {
    method: 'POST',
    headers: {
        'Content-Type': 'application/json',
    },
    body: JSON.stringify(cleanData(formData))
});

使用 jQuery Ajax:

var dataToSend = {
    id: $("#idField").val(),
    name: $("#nameField").val()
};

// 清理空字符串
if (dataToSend.id === "") {
    delete dataToSend.id; // 直接删除属性
}

$.ajax({
    url: '/YourController/YourAction',
    type: 'POST',
    contentType: 'application/json',
    data: JSON.stringify(dataToSend),
    success: function(response) {
        // 处理响应
    }
});

方案二:后端模型使用可空整型 (int?)

将模型中的整型字段改为可空类型,这样就能接收 null 值。

public class YourModel
{
    public int? Id { get; set; } // 改为可空整型
    public string Name { get; set; }
    public int Age { get; set; }
}

然后在控制器中处理:

[HttpPost]
public ActionResult YourAction(YourModel model)
{
    if (model == null)
    {
        return BadRequest("Invalid model data");
    }
    
    // 处理 Id 可能为 null 的情况
    int effectiveId = model.Id ?? 0; // 如果为null则用0代替
    
    // 或者根据业务逻辑判断
    if (model.Id.HasValue)
    {
        // 更新操作
    }
    else
    {
        // 新增操作
    }
    
    // ... 其他逻辑
}

方案三:自定义模型绑定器 (Model Binder)

创建自定义模型绑定器来处理空字符串到整型的转换。

1. 创建自定义模型绑定器:

using System;
using System.Web.Mvc;

public class EmptyStringToZeroModelBinder : DefaultModelBinder
{
    public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
    {
        var valueProviderResult = bindingContext.ValueProvider.GetValue(bindingContext.ModelName);
        
        if (valueProviderResult != null)
        {
            // 如果是整型字段且值为空字符串
            if (bindingContext.ModelType == typeof(int) || bindingContext.ModelType == typeof(int?))
            {
                if (string.IsNullOrWhiteSpace(valueProviderResult.AttemptedValue))
                {
                    // 对于不可空int返回0,对于可空int返回null
                    return bindingContext.ModelType == typeof(int) ? (object)0 : null;
                }
            }
        }
        
        return base.BindModel(controllerContext, bindingContext);
    }
}

2. 注册全局模型绑定器(在 Global.asax.cs 中):

protected void Application_Start()
{
    AreaRegistration.RegisterAllAreas();
    FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
    RouteConfig.RegisterRoutes(RouteTable.Routes);
    BundleConfig.RegisterBundles(BundleTable.Bundles);
    
    // 注册自定义模型绑定器
    ModelBinders.Binders.DefaultBinder = new EmptyStringToZeroModelBinder();
}

或者针对特定属性注册:

// 在模型类中
[ModelBinder(typeof(EmptyStringToZeroModelBinder))]
public int Id { get; set; }

方案四:使用字符串类型接收再转换

public class YourModel
{
    public string IdString { get; set; } // 用字符串接收
    public string Name { get; set; }
    
    // 添加一个只读属性来获取转换后的整型值
    public int Id 
    {
        get
        {
            if (int.TryParse(IdString, out int result))
                return result;
            return 0; // 或者根据业务需求返回默认值
        }
    }
}

方案五:使用 JSON 反序列化设置

如果你使用的是 Newtonsoft.Json,可以配置反序列化设置:

var settings = new JsonSerializerSettings
{
    Converters = new List<JsonConverter> { new EmptyStringToZeroConverter() },
    NullValueHandling = NullValueHandling.Ignore
};

// 在Action中手动反序列化
[HttpPost]
public ActionResult YourAction()
{
    string json = new StreamReader(Request.InputStream).ReadToEnd();
    var model = JsonConvert.DeserializeObject<YourModel>(json, settings);
    
    // 处理model
}

需要创建相应的转换器:

public class EmptyStringToZeroConverter : JsonConverter
{
    public override bool CanConvert(Type objectType)
    {
        return objectType == typeof(int) || objectType == typeof(int?);
    }
    
    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        if (reader.TokenType == JsonToken.String && string.IsNullOrEmpty((string)reader.Value))
        {
            return objectType == typeof(int) ? 0 : (int?)null;
        }
        return serializer.Deserialize(reader, objectType);
    }
    
    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        serializer.Serialize(writer, value);
    }
}

推荐方案

  1. 首选方案一(前端处理):最清晰,责任分离明确
  2. 次选方案二(使用 int?:简单有效,适合大多数场景
  3. 复杂场景用方案三(自定义模型绑定器):适合需要全局处理的情况

推荐文章

【C#】.net core 8.0 MVC在一次偶然间发现控制器方法整个Model实体类对象值为null,猛然发现原来是

【C#】.net framework 4.8非常久远的框架如何把日期格式/Date(1754548600000)/以及带T的2025-08-07T14:36:40时间格式转为统一的格式输出

【C#】实体类定义的是long和值识别到的是Int64,实体类反射容易出现Object does not match target type

【C#】如果有一个数值如 168.0000100,如何去除末尾的无效零,只显示有效的小数位数,让DeepSeek给我们解答

【C#】Quartz.NET怎么动态调用方法,并且根据指定时间周期执行,动态配置类何方法以及Cron表达式,有请DeepSeek

【C#】.net core6.0无法访问到控制器方法,直接404。由于自己的不仔细,出现个低级错误,这让DeepSeek看出来了,是什么错误呢,来瞧瞧

【C#】Html转Pdf,Spire和iTextSharp结合,.net framework 4.8

【C#】事务(进程 ID 64)与另一个进程被死锁在锁资源上,并且已被选作死锁牺牲品。请重新运行该事务。不能在具有唯一索引“XXX_Index”的对象“dbo.Test”中插入重复键的行。

【C#】使用DeepSeek帮助评估数据库性能问题,C# 使用定时任务,每隔一分钟移除一次表,再重新创建表,和往新创建的表追加5万多条记录

【C#】合理使用DeepSeek相关AI应用为我们提供强有力的开发工具,在.net core 6.0框架下使用JsonNode动态解析json字符串,如何正确使用单问号和双问号做好空值处理

【C#】已经实体类和动态实体类的反射使用方法,两分钟回顾,码上就懂

【C#】使用vue3的axios发起get和post请求.net framework部署的API显示跨域

【C#】.net core 6.0 webapi 使用core版本的NPOI的Excel读取数据以及保存数据

【C#】pdf按页分割文件,以及分页合并,效果还不错,你值得拥有

【C#】未能加载文件或程序集“CefSharp.Core.Runtime.dll”或它的某一个依赖项。找不到指定的模块。

【C#】.net core 6.0 在program时间格式统一json格式化,并列举program默认写法和简化写法

【C#】.net core 6.0 ApiController,API控制器方法,API接口以实体类作为接收参数应该注意的点

【C#】 SortedDictionary,查找字典中是否存在给定的关键字

【C#】.net core 6.0 MVC返回JsonResult显示API接口返回值不可被JSON反序列化

【C#】.net core 6.0 使用第三方日志插件Log4net,配置文件详细说明

【C#】使用代码实现龙年春晚扑克牌魔术(守岁共此时),代码实现篇

【C#】使用代码实现龙年春晚扑克牌魔术(守岁共此时),流程描述篇

Logo

助力广东及东莞地区开发者,代码托管、在线学习与竞赛、技术交流与分享、资源共享、职业发展,成为松山湖开发者首选的工作与学习平台

更多推荐