How to force ServiceStack to serialize an object - servicestack

I am declaring my reponse-dto like this:
[Route("/activity/sync", HttpVerb.Get)]
public class SyncActivityRequest : IReturn<SyncActivityResponse>
{
public ICollection<SyncParam> ObjectsToSync { get; set; }
}
public class SyncActivityResponse
{
public ICollection<KeyValuePair<Activity, SyncMetadata>> Result { get; set; }
}
The problem is ServiceStack does not serialize Activity and SyncMetadata because those are only type-arguments for another object (KeyValuePair in this case).
Those two objects (activity and syncmetadata) both are declared in the same project.
How can I force the serialization of those two objects?
Thanks!

You should avoid using interfaces or objects in DTOs, use a concrete Type like List<T> or T[] instead.

Related

ServiceStack - Dynamic/Object in DTO

I am running into an issue while looking at SS.
I am writing a custom Stripe implementation and got stuck on web hooks, this in particular:
https://stripe.com/docs/api#event_object
data->object - this can be anything.
Here is my DTO for it:
public class StripeEvent
{
public string id { get; set; }
public StripeEventData data { get; set; }
public string type { get; set; }
}
[DataContract]
public class StripeEventData
{
[DataMember(Name = "object")]
public object _object { get; set; }
}
My hope is to basically just get that object as a string, and then parse it:
var invoice = (StripeInvoice)JsonSerializer.DeserializeFromString<StripeInvoice>(request.data._object.ToString());
Unfortunately the data that is returned from ToString does not have quotes surrounding each json property's name:
Capture
So, the DeserializeFromString returns an object that has everything nulled out.
Why does SS internally strip the quotes out? Is this the proper way to handle a json member that can be one of many different types? I did try the dynamic stuff, but did not have any luck with that either - basically the same result with missing quotes.
I searched very thoroughly for the use of objects and dynamic within DTOs, but there really was nothing that helped with this question.
Thank you!
The issue is that you should never have an object type in DTOs as the serializer has no idea what concrete type to deserialize back into.
The Stripe documentation says object is a hash which you should be able to use a Dictionary to capture, e.g:
public class StripeEventData
{
public Dictionary<string,string> #object { get; set; }
}
Or as an alternative you could use JsonObject which provides a flexible API to access dynamic data.
This will work for flat object structures, but for complex nested object structures you'll need to create Custom Typed DTOs, e.g:
public class StripeEventInvoice
{
public string id { get; set; }
public StripeEventDataInvoice data { get; set; }
public string type { get; set; }
}
public class StripeEventData
{
public StripeInvoice #object { get; set; }
}

Map to specific derived type based on value on source using Automapper

I'm having trouble implementing Automapper conversion in a situation where the source is a class which should be mapped to one of two derived classes based on a value on the source.
Here's a simplification of my classes:
public class FooContainerDTO
{
public FooDTO Foo { get; set; }
}
public class FooDTO
{
public string Type { get; set; }
//some properties..
}
public class FooContainer
{
public FooBase Foo { get; set; }
}
public abastract class FooBase
{
//some properties..
}
public class FooDerived1 : FooBase
{
//some properties
}
public class FooDerived2 : FooBase
{
//some properties
}
I'm using non-static Automapper so I create a MapperConfiguration from several Profiles at boot and inject the IMapper instance into my DI-container.
I want Automapper to map FooDTO to FooDerived1 when its Type property is "der1" and to FooDerived2 when it is "der2".
I've seen examples on this using the static api, something like this:
Mapper.CreateMap<FooContainerDTO, FooContainer>();
//ForMember configurations etc.
Mapper.CreateMap<FooDTO, FooDerived1>();
//ForMember configurations etc.
Mapper.CreateMap<FooDTO, FooDerived2>();
//ForMember configurations etc.
Mapper.CreateMap<FooDTO, FooBase>()
.ConvertUsing(dto => dto.Type == "der1"
? (FooBase) Mapper.Map<FooDerived1>(dto)
: Mapper.Map<FooDerived2>(dto));
This would map the Foo property of FooContainer to the correct derived type of FooBase.
But how can I do this without the static API?
The IMapper instance is not yet created at the point of configuring the profile.
Is there a way to leverage the overload of ConvertUsing() which takes a Func< ResolutionContext,object >? Can the resolution context give me whatever IMapper is currently being used? I've been looking, but can't find anything usable.
One way to get access to the mapping engine is via your own TypeConverter
abstract class MyTypeConverter<TSource,TDestination> : ITypeConverter<TSource, TDestination>
{
protected ResolutionContext context;
public TDestination Convert(ResolutionContext context)
{
this.context = context;
return Convert((TSource)context.SourceValue);
}
public abstract TDestination Convert(TSource source);
}
You then create an actual implementation like:
class MyTypeMapper : MyTypeConverter<EnumType,EnumTypeView>
{
public override EnumTypeView Convert(EnumType source)
{
return context.Engine.Mapper.Map<EnumTypeID, EnumTypeView>(source.EnumBaseType);
}
}
Except instead of unwrapping an enum structure, you'd check the type and call Map with different types.

Conditional project across all properties on a class using AutoMapper

I'd like to be able to project/map properties from either of 2 child classes.
Imagine a parent class that has 2 child classes, either of 1 which points to a child class. Each child class must map to properties on the model class.
However, if child class 1 is null then it shouldn't map across to the model it should map class 2 properties instead.
It's like what I want to do here except do it across a whole class of properties rather than 1 property:
Conditonal projection
I was hoping I don't have to create a CustomResolver for each class property and whether there is a better way of achieving this. Imagine that the child classes have 10 identical properties each, all I want to do is switch the map depending on which child class is populated.
public class Message
{
public string Comment { get; set; }
public Inbound? InboundMessage { get; set; }
public Outbound? OutboundMessage { get; set; }
}
public class Inbound
{
public string Body { get; set; }
// 10 properties...
}
public class Outbound
{
public string Body { get; set; }
// 10 properties...
}
public class MessageModel
{
public string Comment { get; set; }
public string Body { get; set; }
// 10 properties....
}
Surprised no-one had an answer to this so answered myself by the time I worked out what to do.
If you have the need to conditionally map properties depending on whether a child class is populated or not, or any other logic for the whole class for that matter, then you can use a TypeConverter.
Inside the TypeConverter, you test the source parameter in the ConvertCore function, and then call Mapper.Map on the correct source to pass the child class properties out to the model.
The return from mapper can be then returned back out which will be the destination.
I never realised that you can still call Mapper.Map() even in the TypeConverter.

XSD abstract types and polymorphism

I'm trying to model the following situation into an XSD schema, but kinda stuck and not sure if XSD supports what I'm trying to achieve.
I have two complex elements, which both should be abstract:
Session
SessionResult
Their relationship: one Session can contain zero or more SessionResults
Then I have these other complex types (non-abstract):
RaceSession (inherits from Session)
TimedSession (inherits from Session)
RaceSessionResult (inherits from SessionResult)
TimedSessionResult (inherits from SessionResult)
What I want to achieve is that, when a Session is of type RaceSession, only RaceSessionResult elements are allowed as SessionResult. Subsequently, when a Session is defined as a TimedSession, its SessionResult elements should be of TimedSessionResult.
Right now I'm not able to achieve this in XSD. For now as a workaround, I did not define SessionResult as a subelement-list of Session. Session serves as base for TimedSession and RaceSession, and these latter two just have TimeSessionResult or RaceSessionResult elements respectively.
Is there any way to achieve what I described above in XSD ? The purpose is then to generate c# classes out of them.
Here's the C# equivalent of what I'm trying to do.
public class Event
{
public List<Session> Sessions { get; set; }
}
public abstract class Session
{
public string Weather { get; set; }
public List<SessionResult> SessionResults { get; set; }
}
public abstract class SessionResult
{
public int Position { get; set; }
}
public class RaceSession : Session
{
public new List<RaceSessionResult> SessionResults { get; set; }
}
public class TimedSession : Session
{
public new List<TimedSessionResult> SessionResults { get; set; }
}
public class RaceSessionResult : SessionResult
{
public int StartPosition { get; set; }
}
public class TimedSessionResult : SessionResult
{
public decimal BestLapTime { get; set; }
}
Thanks a ton for any input !

How do restrict access to a class property to only within the same namespace

How do restrict access to a class property to within the same namespace? Consider the following class. The Content class cannot Publish itself, instead the ContentService class
will do a few things before changing the state to published.
public class Content : Entity, IContent
{
public string Introduction { get; set; }
public string Body { get; set; }
public IList<Comment> Comments { get; set; }
public IList<Image> Images { get; private set; }
public State Status { get; }
}
public class ContentService
{
public IContent Publish(IContent article)
{
//Perform some biz rules before publishing
article.Status = State.Published;
return article;
}
}
How can i make it so only the ContentService class can change the state of the article?
Are there any deisng patterns to help me deal with this?
You can use the "internal" access modifier so that only classes within the same Assembly can modify the Content class's State member (but everyone even in other assemblies can GET the value).
public State Status { get; internal set; }
So now ContentService can set the state because it is in the same Assembly, but outside callers can only get the state (they're not allowed to set it).
Java has the notion of "package visible" or "package private". This is in fact the default for anything where you don't specify a visibility (private or public). For some reason, almost no one ever uses this.
Declare ContentService as a friend?
Alternatively, Java has an access modifier that amounts to "package-private".

Resources