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

Model Binding无法绑定System.Drawing对象问题求助

解决System.Drawing.Size在ASP.NET MVC模型绑定中失败的问题

你遇到的问题很典型:ASP.NET的DefaultModelBinder并没有原生支持System.Drawing.Size这个值类型的模型绑定,虽然它有Width和Height属性,但默认绑定器在处理嵌套JSON对象时,没法正确实例化这个struct并为其属性赋值,导致始终得到{Height=0, Width=0}的默认值。

下面给你几个可行的解决方案,按推荐程度排序:

方案一:自定义Size类型的模型绑定器

这是最优雅的解决方案,直接扩展DefaultModelBinder的能力,让它能正确解析Size类型。

1. 创建自定义ModelBinder类

public class SizeModelBinder : IModelBinder
{
    public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
    {
        // 获取JSON中嵌套的Width和Height值
        var widthValue = bindingContext.ValueProvider.GetValue($"{bindingContext.ModelName}.Width");
        var heightValue = bindingContext.ValueProvider.GetValue($"{bindingContext.ModelName}.Height");

        // 如果值不存在,返回空Size
        if (widthValue == null || heightValue == null)
        {
            return Size.Empty;
        }

        // 尝试解析为整数并创建Size实例
        if (int.TryParse(widthValue.AttemptedValue, out int width) 
            && int.TryParse(heightValue.AttemptedValue, out int height))
        {
            return new Size(width, height);
        }

        // 解析失败时添加模型错误
        bindingContext.ModelState.AddModelError(bindingContext.ModelName, "Size格式无效,请传入有效的Width和Height整数");
        return Size.Empty;
    }
}

2. 注册绑定器

有两种注册方式:

  • 局部注册:直接在ConvertSettings的Size属性上添加特性:
    public class ConvertSettings : IListItem
    {
        // 其他属性...
        [ModelBinder(typeof(SizeModelBinder))]
        public System.Drawing.Size Size { get; set; }
        // 其他属性...
    }
    
  • 全局注册:在Global.asax的Application_Start方法中注册,让整个应用都能识别Size类型的绑定:
    protected void Application_Start()
    {
        // 其他初始化代码...
        ModelBinders.Binders.Add(typeof(Size), new SizeModelBinder());
    }
    

方案二:改用自定义DTO类替代System.Drawing.Size

如果不想写自定义绑定器,可以创建一个简单的DTO类来接收前端的Size数据,然后在控制器中转换为System.Drawing.Size。

1. 创建SizeDTO类

public class SizeDTO
{
    public int Width { get; set; }
    public int Height { get; set; }

    // 添加隐式转换,方便后续使用
    public static implicit operator Size(SizeDTO dto)
    {
        return new Size(dto.Width, dto.Height);
    }
}

2. 修改ConvertSettings模型

public class ConvertSettings : IListItem
{
    public int? ID { get; set; }
    public string Title { get; set; }
    // 替换原Size属性为SizeDTO
    public SizeDTO Size { get; set; }
    public SizeType SizeType { get; set; }
    public MimeType MimeType { get; set; }
}

3. 在控制器中使用

public ActionResult ConvertPictures(ConvertSettings settings)
{
    // 自动转换为System.Drawing.Size
    System.Drawing.Size actualSize = settings.Size;
    // 后续业务逻辑...
}

方案三:手动解析JSON(应急方案)

如果以上两种方式都不想用,可以直接在控制器中读取请求的JSON内容,手动反序列化并处理Size属性:

public ActionResult ConvertPictures()
{
    // 读取请求流中的JSON内容
    string jsonContent = new StreamReader(Request.InputStream).ReadToEnd();
    var jsonObj = Newtonsoft.Json.JsonConvert.DeserializeObject<Newtonsoft.Json.Linq.JObject>(jsonContent);
    
    // 反序列化基本属性
    var settings = jsonObj["settings"].ToObject<ConvertSettings>();
    
    // 手动解析Size属性
    var sizeJson = jsonObj["settings"]["Size"];
    settings.Size = new Size(
        sizeJson["Width"].Value<int>(),
        sizeJson["Height"].Value<int>()
    );
    
    // 后续业务逻辑...
}

验证前端请求

你的AJAX代码是正确的:已经设置了contentType: 'application/json; charset=utf-8',并且用JSON.stringify序列化了数据,这确保了前端发送的是标准的JSON格式,所以问题完全出在后端的模型绑定逻辑上。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 07:51:33