When opening this link in my browser, ServiceStack generates the typescript definitions quite nicely on first glance. All the DTO classes are in there and the clients can happily interact with the services.
On closer inspection, there are far too many classes being generated. All of the project’s OrmLite mapping POCOs have found their way into this generated typescript file which is definitely not correct. This can be tracked by these classes having an IsNew property on them.
I have added the [Exclude(Feature.Metadata)] attribute to all the OrmLite POCOs to try and get them to stop being generated, but this did not help. All these generated POCOs implement an IBaseObject interface which I tried to add to the ExcludedTypes but this does not help either. I cannot go and manually add every single POCO into the ExcludedTypes manually either.
var nativeTypes = this.GetPlugin<NativeTypesFeature>();
nativeTypes.MetadataTypesConfig.IgnoreTypes.Add(typeof(ActivityLog)); // ignore this POCO object
Why are these classes finding their way into the generated nativetypes and how do I remove them?
The only thing I can think of is some of my POCO classes have enums which are exposed through the services (as I am not creating duplicate enums) and when ServiceStack reflects on this it comes across the POCO dll which then exposes all the classes in it? Even still, ServiceStack should be able to tell that these classes are not being exposed as DTOs and should not generate them, even if they are being used by the ServiceInterface layer to build up the DTOs.
Add ServiceStack Reference starts from your Request and Response DTOs and then adds all dependent types referenced recursively, so they should only being added because they’re somehow transiently referenced from your Request/Response DTOs.
You can start commenting out Services (Request DTOs are only recognized if they have an impl) then re-checking /types/typescript or /types/metadata route to find out which Services are bringing them in.
Please see an example project I just put together. It is very highly stripped down, but will demonstrate my issue.
What you will see is in the ServiceModel project there is a DTO class called Issue. The ServiceModel class does refer to the Poco project, which it does to build itself. However there are absolutely no public (or private) properties on the DTOs that have classes from the Poco project exposed. I mean this would go against having a DTO in the first place.
However when checking types/metadata, my issue is that all the Poco classes are being generated.
Have you tried removing the BusinessLogic.* references to find all external references? The purpose of DTOs is that they’re decoupled from your Services implementation and why the ServiceModel project should be dependency and implementation-free, i.e. only Containing your Services Data Transfer Objects - but this ServiceModel project contains implementation and tight coupling to external BusinessLogic.* references everywhere.
It was hard to find because this implementation is so intertwined with the implementation project but the issue is because your IssueStatus enum is defined within a concrete class of your implementation assembly, moving the IssueStatus enum outside of the Issue class, removes that coupling.
But I’d highly recommend removing all BusinessLogic.* references from your ServiceModel project completely, there’s no benefit to how it’s structured at the moment and behaves the same as keeping all your models in the BusinessLogic.Poco project, as separating them but retaining its tight coupling just adds artificial friction yielding none of the benefits and purposes of maintaining a separate ServiceModel project - which is your Services most important contract.
Note: DTOs should have parameter-less constructors or will otherwise fail to serialize in some serializers
I completely understand that - and if that is the convention required by ServiceStack I will follow.
However the way I design code is that each class is responsible for itself. This means that if I have a DTO, it is responsible for populating it’s properties. This could be through automapping, extension methods or manual property mapping. This is the reason why my DTO object reference many different classes from elsewhere in the solution - these are required for it to populate itself.
This may be seen as being tightly coupled, but the way it’s been structured makes a lot of sense for developers utilizing the classes. Yes, it negates the ability to share the dependency free DLL with clients, but this has not been a requirement for my projects for over 3 years.
I guess I will have to move the hydration of the DTOs into the ServiceInterface project. However as you mentioned, all types are in the DTO .dll now means I may have duplicate items (mainly things such as enums), which introduces code complexity and duplication which I am not overly happy with.
Sorry Dylan I don’t agree at all, take a look at all our Live Demos projects, we maintain ServiceModel project defining clean Data Models and we don’t have any code duplication. The ServiceModel project just contains Data Transfer Objects which doesn’t contain any behavior or implementation - and they shouldn’t, they’re objects for enabling Data Transfer, you shouldn’t be serializing business objects with behavior - this is frequently a source of runtime issues with serialization and what DTOs exists to prevent. The behavior is in the ServiceInterfaces implementation project.
This negates the very purpose of maintaining Data Transfer Objects in an isolated Service Model project in the first place which just contains your Service Models to define your Service Contract and enable Service interoperability. If you’re not going to keep the responsibilities of the projects separate you might as well not have a separate Service Model project in the first place, it’s just an extension of your business objects with no clear purpose or responsibility.