I would understand if it required one for deserialization, but constructor requirement for serialization doesn't make sense. Issue goes away if I use AllowPrivate, but all my private members get included which I don't want. Here's the exception message. Thanks!
MessagePack.MessagePackSerializationException: Failed to serialize System.Collections.Generic.List
1[[MyAssembly.MyObject, MyAssembly, Version=1.0.0.1, Culture=neutral, PublicKeyToken=null]] value. ---> System.TypeInitializationException: The type initializer for 'FormatterCache1' threw an exception. ---> MessagePack.Internal.MessagePackDynamicObjectResolverException: can't find matched constructor. type:MyAssembly.MyObject
at MessagePack.Internal.ObjectSerializationInfo.CreateOrNull(Type type, Boolean forceStringKey, Boolean contractless, Boolean allowPrivate)
at MessagePack.Internal.DynamicObjectTypeBuilder.BuildType(DynamicAssembly assembly, Type type, Boolean forceStringKey, Boolean contractless)
at MessagePack.Resolvers.DynamicContractlessObjectResolver.FormatterCache1..cctor() --- End of inner exception stack trace --- at MessagePack.Resolvers.DynamicContractlessObjectResolver.GetFormatter[T]() at MessagePack.Resolvers.ContractlessStandardResolver.FormatterCache1..cctor()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at MessagePack.FormatterResolverExtensions.GetFormatterWithVerifyT
at MessagePack.Formatters.ListFormatter1.Serialize(MessagePackWriter& writer, List1 value, MessagePackSerializerOptions options)
at MessagePack.MessagePackSerializer.SerializeT
--- End of inner exception stack trace ---
at MessagePack.MessagePackSerializer.SerializeT
at MessagePack.MessagePackSerializer.SerializeT
at MessagePack.MessagePackSerializer.SerializeT
at WebDashboard.DataFetcher.Program.DoMsgPackT in C:devharmonicWebDashboard.DataFetcherProgram.cs:line 322
I suspect this is simply an early warning system that you're serializing a non-deserializable type. I agree, a constructor isn't required for serialization. However, when our dynamic resolver creates a formatter for the type, it creates it for serialization and deserialization at the same time. That's probably why you run into this error. So I'd say it's by design.
The only alternative I can imagine is that we generate the formatter and hard-code it to throw on deserialization instead of implementing the deserializer.
But I'm curious: why do you have a type you want to serialize that cannot be deserialized? Why don't you want the constructor to be accessible?
Also: You can use AllowPrivate and avoid too many fields being serialized by avoiding Contractless. Instead, decorate your type with [DataContract] and [DataMember] (or [MessagePackObject] and [Key]) and it should do what you want.
I have ASP.NET Web API which I want to switch to use MessagePack instead of JSON. This API can be consumed by different clients (.NET Core, Javascript, potentially Java, etc) and each of them generate classes based on OpenApi definition using NSwag or swagger-codegen. So in fact the deserialization happens to another (but similar) class. This is also why I have to use Contractless (plus, don't really want to specify attributes to thousands of classes). This is also why I don't go with Protobuf. I tried using utf8json, it works and doesn't require public constructor, but the performance is very close to Newtonsoft.
Actually, what I want is not to completely switch to MessagePack but to add another formatter to the API like "application/msgpack" and then when the client says "accept: application/msgpack" this one will be preferred as has a better performance. I tested this from .NET Core + NSwag client and it seems to work fine (although needed to patch NSwag templates to allow for configuring the serializer used). I can now use this API with MessagePack as a serializer (both directions) but it just doesn't work for private-constructor classes. Perhaps there could be more limitations along the road which will prevent me from implementing this but this one is the first I faced. I'm trying to test this with as many classes as possible (as I said, there are thousands of them) but the main showstopper now is the missing public constructor.
Adding constructor isn't as huge of a deal as adding the attributes, so we may end up doing so, but first, these classes have factories that must be used and constructors will be misleading for developers, and second, if someone implements a new class we don't want them to always remember to make a public constructor or the serialization will fail.
Any other ideas are very welcomed! :) Maybe you know some other way to speed up this API's serialization bit without too much intervention to the business code? I tried using Newtonsoft (currently in use), Newtonsoft BSON (surprisingly even slower than original), Utf8Json (all works great but not too much faster, worst case will stick with this one), this MessagePack, MsgPack.Cli (very slow), Jil (just about same performance as Newtonsoft).
My benchmark is for my use case, i.e., very large lists (140k) of quite heavy objects (5 string 50 chars long each, plus 25 decimals/ints) and without using serialization contracts. For someone elses needs the benchmark results could be completely different.
In case you're interested in the raw numbers:

PS: s=serialization, d=deserialization, t=total
PS2: DTO means objects in the list are represented by a Dictionary
I'd entertain a PR that replaces the rejection of types lacking a public constructor with a generated formatter that simply throws when deserializing that type.
But I'm curious: why do you have a type you want to serialize that cannot be deserialized? Why don't you want the constructor to be accessible?
@AArnott can you clarify this statement? For example BinaryFormatter supports deserializing types with private/protected constructors, doesn't it? (my apologies if I misunderstood what you said above or took it out of context)
or am I confused and the only way this may possibly work is by serializing/deserializing the private members? (as opposed to invoking a private constructor)
@zvolkov This bug is asking why serialization requires a public constructor when serialization doesn't need any constructor at all. While we could add support for private constructors in some cases, this issue isn't really about that. It's about supporting serialization of an object even if deserialization would fail.
So my question was why someone would define a type that could only be serialized. Why not make a public constructor so you can also deserialize it?
I have the same problem during serializing my types for SignalR (Just Server -> Client). There is no deserialization required on the Server (c#) side. So declare a constructor for that is really useless.
Is there no opportunity to configure messagePack to just serialize types?
Thanks for weighing in, @feitzi. There certainly is, but at present you'd have to write a custom formatter for these types.
But we'd welcome a PR to fix the dynamic formatters to support this scenario better.