Web API ApiController PUT and POST methods receive

2019-07-24 11:42发布

My ApiController methods receive null parameters sometimes when I run tests in the debugger. But if I touch the controller file and rebuild it, it works fine with the same tests. Everything is the same, except it recompiles the Web Api project's DLL. I turned on tracing but it doesn't tell me anything except whether the parameter was null or not. How could this happen?

I guess it fails to deserialize the JSON object into the parameter type, but how can I troubleshoot this?

EDIT: code added

This method sometimes receives value=null

public FilterItem Post(uint jobId, uint columnID, FilterItemDTO value)
    {
        // save a new FilterItem
    }

FilterItemDTO is a DTO class I made just because the FilterItem class has a bunch of unwanted inherited fields and I can't annotate them in the base class:

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);
    }
}

Here's the request I sent (copied from Fiddler scratch-pad)

POST http://localhost:56875/api/job/4513/column/21213/filter HTTP/1.1
Host: localhost:56875
Connection: keep-alive
Content-Length: 28
Accept: application/json, text/javascript, */*; q=0.01
Origin: http://localhost:56875
X-Requested-With: XMLHttpRequest
User-Agent: Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.31 (KHTML, like Gecko) Chrome/26.0.1410.64 Safari/537.31
Content-Type: application/json
Referer: http://localhost:56875/Content/test.htm
Accept-Encoding: gzip,deflate,sdch
Accept-Language: en-GB,en-US;q=0.8,en;q=0.6
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.3

{"type":"Equal","value":"1"}

Here's my formatter config. The type:"Equal" value should be automatically converted using the StringEnumConverter.

 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);
    }
}

1条回答
▲ chillily
2楼-- · 2019-07-24 12:15

I would try isolating the issue first:

  • comment out everything but one method in one controller and see if it is still affected

  • do the same with every method in isolation

  • should they be fine in isolation then it means that maybe the methods are not clearly separated, maybe sometimes WebApi selects the wrong method (because of missing properties or something)

  • if they still fail, and the failures are still random, I'd check for any dodgy objects being passed in - try replaying requests several times using fiddler and check for differences between them on failure (params, cookies, accept/content-type headers etc.)

  • debug through from app_start, several times if need be - you probably know your patterns of failure quite well, just keep on debugging to see what has changed in between the requests

  • check if any methods/tests are not overriding any configuration / changing state of the app in any other way

  • try removing complex properties from your objects, leaving them just with primitive types and see if that helps (if it does, it means there might be issues around serialization of the types (e.g. inheritance related))

  • change the serializer

If none of that helps, post some code.

查看更多
登录 后发表回答