1

//Class

public class Model
{
    public string Name { get; set; }
    public List<Item> Items { get; set; } = new List<Item>();    
}

public class Item
{
    public string Description { get; set; } 
}

This is the model that I was referring to.

//Model 1

{
    "Name": "",
    "Items":[
        {
            "Description":""
        }
    ]
}

//Model 2

{
    "Name": ""
}

//Request

var model = new Model();
var content = JsonConvert.SerializeObject(model);

using var client = new HttpClient { "BaseAddress" = new Uri("http://localhost:80/main") };
var content = new StringContent(
    content,
    Encoding.UTF8,
    "application/json");

content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("application/json");
var response = await client.PostAsync("insert", content);

//Controller

[ApiController]
public class MainController : ControllerBase
{
    [HttpPost("insert")]
    public async Task<IActionResult> Insert([FromBody] Model model)
    {

    }
}

If I insert a Model 1 with a list, i get a

{StatusCode: 500, ReasonPhrase: 'Internal Server Error', Version: 1.1, Content: System.Net.Http.HttpConnectionResponseContent, Headers:
{
  Date: Thu, 13 Feb 2020 22:04:06 GMT
  Server: Kestrel
  Transfer-Encoding: chunked
  Content-Type: text/plain
}}

But if I insert Model 2 w/o a list, works fine.
I did try passing the list as json string to my controller manually (post), and does the same behavior, does not accept the list, but does the model.
I did get an exception on the API

fail: Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware[1]
      An unhandled exception has occurred while executing the request.
System.NotSupportedException: Collection was of a fixed size.
   at System.Array.System.Collections.IList.Add(Object value)
   at System.Text.Json.JsonSerializer.ApplyObjectToEnumerable(Object value, ReadStack& state, Boolean setPropertyDirectly)
   at System.Text.Json.JsonSerializer.HandleEndArray(JsonSerializerOptions options, ReadStack& state)
   at System.Text.Json.JsonSerializer.ReadCore(JsonSerializerOptions options, Utf8JsonReader& reader, ReadStack& readStack)
   at System.Text.Json.JsonSerializer.ReadCore(JsonReaderState& readerState, Boolean isFinalBlock, ReadOnlySpan`1 buffer, JsonSerializerOptions options, ReadStack& readStack)
   at System.Text.Json.JsonSerializer.ReadAsync[TValue](Stream utf8Json, Type returnType, JsonSerializerOptions options, CancellationToken cancellationToken)
   at Microsoft.AspNetCore.Mvc.Formatters.SystemTextJsonInputFormatter.ReadRequestBodyAsync(InputFormatterContext context, Encoding encoding)
   at Microsoft.AspNetCore.Mvc.Formatters.SystemTextJsonInputFormatter.ReadRequestBodyAsync(InputFormatterContext context, Encoding encoding)
   at Microsoft.AspNetCore.Mvc.ModelBinding.Binders.BodyModelBinder.BindModelAsync(ModelBindingContext bindingContext)
   at Microsoft.AspNetCore.Mvc.ModelBinding.ParameterBinder.BindModelAsync(ActionContext actionContext, IModelBinder modelBinder, IValueProvider valueProvider, ParameterDescriptor parameter, ModelMetadata metadata, Object value)
   at Microsoft.AspNetCore.Mvc.Controllers.ControllerBinderDelegateProvider.<>c__DisplayClass0_0.<<CreateBinderDelegate>g__Bind|0>d.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.<InvokeInnerFilterAsync>g__Awaited|13_0(ControllerActionInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeFilterPipelineAsync>g__Awaited|19_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Awaited|17_0(ResourceInvoker invoker, Task task, IDisposable scope)
   at Microsoft.AspNetCore.Routing.EndpointMiddleware.<Invoke>g__AwaitRequestTask|6_0(Endpoint endpoint, Task requestTask, ILogger logger)
   at Swashbuckle.AspNetCore.SwaggerUI.SwaggerUIMiddleware.Invoke(HttpContext httpContext)
   at Swashbuckle.AspNetCore.Swagger.SwaggerMiddleware.Invoke(HttpContext httpContext, ISwaggerProvider swaggerProvider)
   at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context)

It does not reach the Controller when i put a break point.
I'm on netcoreapp3.1 Newtonsoft.Json 12.0.3 Its getting referenced in a netstandard project 2.1

Jensen
  • 199
  • 2
  • 11
  • Show Model class definition – Nkosi Feb 13 '20 at 22:17
  • public class Model { public string Name { get; set; } public List Items { get; set; } = new List(); } public class Item { public string Description { get; set; } } – Jensen Feb 13 '20 at 22:26
  • Remove the default `List` and try again – Nkosi Feb 13 '20 at 22:28
  • I did try that and does not change the results. – Jensen Feb 13 '20 at 22:31
  • Put a break point in the controller action. Does the error happen before or during the action? Would help to see the exception thrown – Nkosi Feb 13 '20 at 22:33
  • included the exception in the post, thank you. – Jensen Feb 13 '20 at 22:36
  • Ok. Jut to be sure, when I said default list I meant `public List Items { get; set; } ` Is that what you understood and already tried? – Nkosi Feb 13 '20 at 22:39
  • Seems `System.Text.Json` is having an issue identifying the list. What happens if you change to an array instead – Nkosi Feb 13 '20 at 22:40
  • If I remove the `public List Items { get; set; }` it works fine, yes. That is what I tried. I also removed the ` = new List();` after the property. – Jensen Feb 13 '20 at 22:41
  • I might be misunderstanding the comments. So to be clear. Keep the property but remove the `= new List();`. – Nkosi Feb 13 '20 at 22:46
  • Checking some issues on GH https://github.com/dotnet/runtime/issues/29843 and https://github.com/dotnet/runtime/issues/31089 – Nkosi Feb 13 '20 at 22:46
  • Ok another confirmation needed. The `Model` class serialized and used for the request and the one in the controller action are the same? – Nkosi Feb 13 '20 at 23:05
  • Yeah. I ended up switching to System.Text.Json instead of Newtonsoft. Got it to work. – Jensen Feb 13 '20 at 23:07
  • Ok Cool. Glad you figured it out. Happy coding. – Nkosi Feb 13 '20 at 23:08
  • Thank you so much for your time. I truly appreciate it. Those issues you sent me helped me understand it a little better. – Jensen Feb 13 '20 at 23:16
  • You're using the new serializer, `System.Text.Json`. What happens if you revert back to Json.NET by following the instructions from [Where did IMvcBuilder AddJsonOptions go in .Net Core 3.0?](https://stackoverflow.com/a/55666898/3744182)? – dbc Feb 14 '20 at 00:22
  • 1
    Gotcha, it does work with i add the AddNewtonsoftJson() option. Major oversight on my part. I can use Newtonsoft now with no issues. Thank you @dbc – Jensen Feb 14 '20 at 18:22

1 Answers1

0

Reference from the question "Where did IMvcBuilder AddJsonOptions go in .Net Core 3.0? " Link
Thank you @dbc

Jensen
  • 199
  • 2
  • 11