.net Web API ApiController PUT和POST方法间歇性地接收空参数

.net Web API ApiController PUT和POST方法间歇性地接收空参数,.net,asp.net-web-api,.net,Asp.net Web Api,当我在调试器中运行测试时,我的ApiController方法有时会接收空参数。但是,如果我触摸控制器文件并重建它,它在相同的测试中运行良好。除了重新编译WebAPI项目的DLL之外,所有内容都是一样的。我打开了跟踪功能,但除了参数是否为null之外,它没有告诉我任何事情。这怎么会发生 我猜它无法将JSON对象反序列化为参数类型,但是如何解决这个问题呢 编辑:添加代码 此方法有时接收value=null public FilterItem Post(uint jobId, uint columnI

当我在调试器中运行测试时,我的ApiController方法有时会接收空参数。但是,如果我触摸控制器文件并重建它,它在相同的测试中运行良好。除了重新编译WebAPI项目的DLL之外,所有内容都是一样的。我打开了跟踪功能,但除了参数是否为null之外,它没有告诉我任何事情。这怎么会发生

我猜它无法将JSON对象反序列化为参数类型,但是如何解决这个问题呢

编辑:添加代码

此方法有时接收value=null

public FilterItem Post(uint jobId, uint columnID, FilterItemDTO value)
    {
        // save a new FilterItem
    }
FilterItemDTO是我创建的DTO类,只是因为FilterItem类有一堆不需要的继承字段,我无法在基类中对它们进行注释:

public class FilterItemDTO
{
    public uint Id;
    public uint ColumnID { get; set; }
    public FilterItem.FilterType Type;
    public string Value;

    //Date/Time Stamps
    public DateTime? CreatedDate = null;
    public string CreatedBy = null;
    public DateTime? ModifiedDate;
    public string ModifiedBy = null;
    public int FilterLevel = 0;

    public FilterItemDTO(FilterItem f)
    {
        Id = f.ID;
        ColumnID = f.ColumnID;
        Type = f.Type;
        Value = f.Value;
        FilterLevel = f.FilterLevel;
        CreatedDate = f.CreatedDate;
        CreatedBy = f.CreatedBy;
        ModifiedDate = f.ModifiedDate;
        ModifiedBy = f.ModifiedBy;
    }

    internal static FilterItem ToFilterItem(FilterItemDTO value)
    {
        FilterItem f = new FilterItem(value.Type, value.Value, value.FilterLevel);
        f.ID = value.Id;
        f.ColumnID = value.ColumnID;
        f.CreatedDate = value.CreatedDate;
        f.CreatedBy = value.CreatedBy;
        f.ModifiedDate = value.ModifiedDate;
        f.ModifiedBy = value.ModifiedBy;

        return f;
    }

    public FilterItem ToFilterItem()
    {
        return FilterItemDTO.ToFilterItem(this);
    }
}
这是我发送的请求(复制自Fiddler scratch pad)

这是我的格式化程序配置。应使用StringEnumConverter自动转换类型:“Equal”值

 public class FormatterConfig
{
    public static void RegisterGlobalFormatters(MediaTypeFormatterCollection formatters)
    {
        var jsonSerializerSettings = formatters.JsonFormatter.SerializerSettings;
        jsonSerializerSettings.Converters.Add(new IsoDateTimeConverter());

        // serialize every enum as a string
        jsonSerializerSettings.Converters.Add(new Newtonsoft.Json.Converters.StringEnumConverter());

        // include null value fields
        jsonSerializerSettings.NullValueHandling = NullValueHandling.Ignore;

        // use camel case
        jsonSerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();

        // indented formatting
        formatters.JsonFormatter.Indent = true;

        formatters.Remove(formatters.XmlFormatter);
    }
}

我会先尝试隔离这个问题:

  • 注释掉除了一个控制器中的一个方法之外的所有内容,看看它是否仍然受到影响

  • 孤立地对每个方法执行相同的操作

  • 如果它们在隔离状态下是好的,那么这意味着可能这些方法没有明确地分开,可能有时候WebApi选择了错误的方法(因为缺少属性或其他原因)

  • 如果它们仍然失败,并且失败仍然是随机的,我会检查传入的任何不可靠的对象-尝试使用fiddler多次重放请求,并检查失败时它们之间的差异(参数、cookie、接受/内容类型头等)

  • 从app_开始调试,如果需要,可以多次调试-您可能非常清楚自己的失败模式,只需继续调试,看看请求之间发生了什么变化

  • 检查是否有任何方法/测试未以任何其他方式覆盖应用程序的任何配置/更改状态

  • 尝试从对象中删除复杂属性,只保留基本类型,看看这是否有帮助(如果有帮助,则意味着类型序列化可能会出现问题(例如,与继承相关的问题))

  • 更改序列化程序


如果这些都没有帮助,请发布一些代码。

我会先尝试隔离问题:

  • 注释掉除了一个控制器中的一个方法之外的所有内容,看看它是否仍然受到影响

  • 孤立地对每个方法执行相同的操作

  • 如果它们在隔离状态下是好的,那么这意味着可能这些方法没有明确地分开,可能有时候WebApi选择了错误的方法(因为缺少属性或其他原因)

  • 如果它们仍然失败,并且失败仍然是随机的,我会检查传入的任何不可靠的对象-尝试使用fiddler多次重放请求,并检查失败时它们之间的差异(参数、cookie、接受/内容类型头等)

  • 从app_开始调试,如果需要,可以多次调试-您可能非常清楚自己的失败模式,只需继续调试,看看请求之间发生了什么变化

  • 检查是否有任何方法/测试未以任何其他方式覆盖应用程序的任何配置/更改状态

  • 尝试从对象中删除复杂属性,只保留基本类型,看看这是否有帮助(如果有帮助,则意味着类型序列化可能会出现问题(例如,与继承相关的问题))

  • 更改序列化程序


如果这些都没有帮助,请发布一些代码。

一些问题:1。尝试使用setter将公共字段更改为公共属性,2。将无参数构造函数添加到Dto,3。您是否总是提出与您发布的请求相同的请求?4.复制步骤是什么,何时开始失败(例如,调试时总是失败还是启动时失败等)?当应用程序未在IIS中设置调试时?5。您在web api配置中设置了哪些路由?尝试发布完全相同的属性名称(即区分大小写)-因此
{“Type”:“Equal”,“Value”:“1”}
而不是
{“Type”:“Equal”,“Value”:“1”}
,并将枚举值设置为字符串。此外,我还简化了路由——删除前两个int参数,只保留复杂对象。这应该没有什么区别,但值得一试。DTO缺少无参数构造函数!非常感谢。我仍然不知道为什么它会间歇性地工作,但到目前为止还不错。我确信路由是正确的,CamelCasePropertyNamesContractResolver处理案例转换。尝试使用setter将公共字段更改为公共属性,2。将无参数构造函数添加到Dto,3。您是否总是提出与您发布的请求相同的请求?4.复制步骤是什么,何时开始失败(例如,调试时总是失败还是启动时失败等)?当应用程序未在IIS中设置调试时?5。您在web api配置中设置了哪些路由?尝试发布完全相同的属性名称(即区分大小写)-因此
{“Type”:“Equal”,“Value”:“1”}
而不是
{“Type”:“Equal”,“Value”:“1”}
,并将枚举值设置为字符串。此外,我还简化了路由——删除前两个int参数,只保留复杂对象。这应该没有什么区别,但值得一试。DTO缺少无参数构造函数!非常感谢。我仍然不知道为什么它会间歇性地工作,但到目前为止还不错。我确信路由是正常的,CamelCasePropertyNamesContractResolver处理案例转换。
 public class FormatterConfig
{
    public static void RegisterGlobalFormatters(MediaTypeFormatterCollection formatters)
    {
        var jsonSerializerSettings = formatters.JsonFormatter.SerializerSettings;
        jsonSerializerSettings.Converters.Add(new IsoDateTimeConverter());

        // serialize every enum as a string
        jsonSerializerSettings.Converters.Add(new Newtonsoft.Json.Converters.StringEnumConverter());

        // include null value fields
        jsonSerializerSettings.NullValueHandling = NullValueHandling.Ignore;

        // use camel case
        jsonSerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();

        // indented formatting
        formatters.JsonFormatter.Indent = true;

        formatters.Remove(formatters.XmlFormatter);
    }
}