Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Deserialization of reference types without parameterless constructor is not supported

I have this API

 public ActionResult AddDocument([FromBody]AddDocumentRequestModel documentRequestModel)
        {
            AddDocumentStatus documentState = _documentService.AddDocument(documentRequestModel, DocumentType.OutgoingPosShipment);
            if (documentState.IsSuccess)
                return Ok();

            return BadRequest();
        }

And this is my request model

    public class AddDocumentRequestModel
    {
        public AddDocumentRequestModel(int partnerId, List<ProductRequestModel> products)
        {
            PartnerId = partnerId;
            Products = products;
        }

        [Range(1, int.MaxValue, ErrorMessage = "Value for {0} must be between {1} and {2}.")]
        public int PartnerId { get; private set; }

        [Required, MustHaveOneElement(ErrorMessage = "At least one product is required")]
        public List<ProductRequestModel> Products { get; private set; }
    }

so when I'm trying to hit the API with this body

{
        "partnerId": 101,
        "products": [{
            "productId": 100,
            "unitOfMeasureId": 102,
            "quantity":5
        }
     ]
}

this is the request : System.NotSupportedException: Deserialization of reference types without parameterless constructor is not supported. Type 'Alati.Commerce.Sync.Api.Controllers.AddDocumentRequestModel'

I don't need parameterless constructor,because it doesn't read the body parameters.Is there any other way for deserialization?

like image 662
Yoana Gancheva Avatar asked Dec 05 '19 15:12

Yoana Gancheva


People also ask

Is it possible to deserialize a class without a parameterized constructor?

System.NotSupportedException: Deserialization of types without a parameterless constructor, a singular parameterized constructor, or a parameterized constructor annotated with 'JsonConstructorAttribute' is not supported. The code that takes care of deserializing is as follows:

What types of constructors can be used for deserialization?

On .NET Core 3.x, internal and private constructors can be used for deserialization. In the standalone packages, non-public constructors are not allowed, and a MissingMethodException is thrown if no public, parameterless constructor is defined.

What constructors are ignored by the serializer?

Non-public constructors, including parameterless constructors, are ignored by the serializer by default. The serializer uses one of the following constructors for deserialization: Public constructor annotated with JsonConstructorAttribute. Public parameterless constructor.

What is a public parameterless constructor?

Public parameterless constructor. Public parameterized constructor (if it's the only public constructor present). If none of these constructors are available, a NotSupportedException is thrown if you attempt to deserialize the type. 5.0


2 Answers

You can achieve your desired result. You need to switch to NewtonsoftJson serialization (from package Microsoft.AspNetCore.Mvc.NewtonsoftJson)

Call this in Startup.cs in the ConfigureServices method:

services.AddControllers().AddNewtonsoftJson();

After this, your constructor will be called by deserialization.

Extra info: I am using ASP Net Core 3.1

Later Edit: I wanted to give more info on this, as it seems that this can also be achieved by using System.Text.Json, although custom implementation is necessary. The answer from jawa states that Deserializing to immutable classes and structs can be achieved with System.Text.Json, by creating a custom converter (inherit from JsonConverter) and registering it to the converters collection (JsonSerializerOptions.Converters) like so:

public class ImmutablePointConverter : JsonConverter<ImmutablePoint>
{
...
}

and then...

var serializeOptions = new JsonSerializerOptions();
serializeOptions.Converters.Add(new ImmutablePointConverter());
serializeOptions.WriteIndented = true;
like image 131
Adrian Nasui Avatar answered Oct 24 '22 09:10

Adrian Nasui


Just in case someone have the same issue I had, I was using abstract class, once removed the abstract key word, it all worked just fine.

like image 4
IBRA Avatar answered Oct 24 '22 10:10

IBRA