1 year ago
#318758
BLAZORLOVER
No serializer defined for type: System.Object when serializing generic API Response DTO
Context: I'm trying to improve the performance of a WebAPI endpoint that routinely returns about xx,xxx rows of data. The data is returned by a business logic pattern that tucks all API data into DTOs that look like this:
[ProtoContract]
public class ApiResponseDto {
public ApiResponseDto() {
Success = true;
}
[ProtoMember(1)]
public bool Success { get; set; }
[MaxLength(3000)]
[ProtoMember(2)]
public string Error { get; set; }
[MaxLength(3000)]
[ProtoMember(3)]
public string InternalError { get; set; }
[ProtoMember(4, DynamicType = true)]
public object Data { get; set; }
}
Before, I was using Newtonsoft.Json to serialize this DTO, which worked well enough regardless of the Data
I stuck in there.
To try protobuf-net, I've:
- Installed both protobuf-net and WebApiContrib.Formatting.ProtoBuf.
- Added
config.Formatters.Insert(0, new ProtoBufFormatter());
to WebApiConfig.cs. - Decorated all models with
ProtoMember
attributes, as demonstrated above. - Updated my client app to specify
headers: { Accept: 'application/x-protobuf, application/json' }
My expectation was that this would "just work", but I receive the error No serializer defined for type: System.Object
. After some investigation, it looks like untyped data isn't really supported: https://github.com/protobuf-net/protobuf-net.Grpc/issues/47
I'd love to be able to enjoy an instant perf gain by dropping a few lines of code into my app, but it's looking like in order to use protocol buffers, I need to strongly type my DTOs.
To test this out, I tried creating another, typed DTO specifically for this one endpoint:
[ProtoContract]
public class SidebarApiResponseDto
{
public SidebarApiResponseDto()
{
Success = true;
}
[ProtoMember(1)]
public bool Success { get; set; }
[MaxLength(3000)]
[ProtoMember(2)]
public string Error { get; set; }
[MaxLength(3000)]
[ProtoMember(3)]
public string InternalError { get; set; }
[ProtoMember(4)]
public List<SidebarItem> Data { get; set; }
}
I've decorated SidebarItem
's properties with the Proto
attributes.
But now, the error is: {"Method not found: 'ProtoBuf.Meta.RuntimeTypeModel ProtoBuf.Meta.TypeModel.Create()'."}
The only odd thing about SidebarItem
is that it has a few Enums properties, otherwise it's all bool
s, int
s, string
s, List<SidebarItem>
s.
Stack trace:
" at WebApiContrib.Formatting.ProtoBufFormatter.CreateTypeModel()\r\n at System.Lazy1.CreateValue()\r\n at System.Lazy1.LazyInitValue()\r\n at System.Lazy1.get_Value()\r\n at WebApiContrib.Formatting.ProtoBufFormatter.WriteToStreamAsync(Type type, Object value, Stream stream, HttpContent content, TransportContext transportContext)"
Before I get too much further along here - is there a "less obtrusive" way to upgrade a plain old webapi app from NewtonSoft.Json
to protobuf-net? Perhaps by somehow allowing untyped serialization?
protobuf-net
0 Answers
Your Answer