Name Collissions on DTOs

Yep, you get it, Charles. To the generated code’s perspective, it would be as if the end users wrote the plugin with the prefix themselves thus avoiding any collisions without putting the burden on the individual plugin codebase owners.

1 Like

I’m finding myself struggling with a similar problem. I’ve got a lot of experience in the Django framework, where “projects” are structured as a set of “applications”, (Applications | Django documentation | Django) and the framework provides functionality to assign all the stuff in an application, like all of its Routes, etc, under a prefix, which is why it feels similar to your issue… Most things have an adaptation to deal with potential conflicts in naming as the “application” abstraction allows you to just pull in a package from the public registry “PyPI” and use it as an “re-usable application”, where you have no control over database model names and class naming. For instance the Django framework has a built in authentication component which is an application with its own models, admin interface setup etc, and you can pull it in to a project simply by adding "‘django.contrib.auth’ to the “INSTALLED_APPS” setting, and other applications such as the built in admin can reference it via the normal Python code mechanisms to ensure the built in admin is only visible to logged in users.

While I’m not struggling with duplicate DTO naming, I am struggling with app structure, because I’m so much more used to being able to structure my websites/services “projects” as a set of “applications” which are combined together at the root of the “project”. ServiceStack is a great framework, but the standard project structure where it gives me 4 boxes “<project>”, “<project>.ServiceInterface”, “<project>.ServiceModel”, and “<project>.Tests” and everything lives inside these big flat namespaces with no ability to logically group together. Based on the docs I have a feeling that “plugins” is potentially a solution to my problem, but there isn’t a lot of examples for using plugins to group services, there’s one short section in the docs, and the auth service, but these don’t really show how you would take most of the functionality of a complete project (modulo what can’t or shouldn’t be in the plugin) and put it inside a plugin, and then add that plugin to a “parent” ServiceStack “project”.

This kind of composition of components feels very related to the issues your having @grexican and @Charles.

@mythz do you think there is a way to leverage the plugin mechanism to control the merge/translation of these DTOs into the unified top level project namespace, the level at which the DTOs need to have unique names in order to not break other language clients? I’m asking directly because I’m used to having these kind of mechanisms with what I think are equivalent features and I’m still pretty new to using the more advanced parts of ServiceStack, like writing my own Plugins.

Slight derail… I’m honestly not sure I fully understand plugins other than their primary use, which from the publicly available code I have to read for examples, appears to be for dropping in “logical” features like the AutoQuery system, or request logging, etc. Other than having the example of the Auth service as a “counter example”, I’m genuinely unsure that plugins are meant to be used to encapsulate a complete set of classes, DTOs, app logic, DTO to database mappings, and everything else that would be spread out across the “<project>”, “<project>.ServiceInterface”, “<project>.ServiceModel”, and “<project>.Tests” folders/assemblies. If there are examples I’ve missed that show how to take a top level “project” (with DTOs, logic, database mappings, etc) and turn it into a “plugin” and then include that plugin into a “parent” project all in the one codebase, I’d love to be pointed to it since I’m still trying to fully understand some of these ServiceStack of internals.

Plugins can indeed encapsulate functionality like services, filters, validation etc. The recommended pattern in the templates of ServiceModel/ServiceInterfaces/AppHost/Tests is there to strike a balance between basic setup vs one that will scale pretty well for a lot of use cases without the need to add additional projects, but that doesn’t mean you need to fit ‘everything’ in those 4 projects for any size application.

You start with these 4 boxes, but as your application grows, you might then start breaking up into additional ServiceModel/ServiceInterface/Tests projects depending on your requirements. This actually maps pretty well to what you describe where your ‘application’ is your AppHost, the entry point, that can use a combination of ServiceModels/ServiceInterface projects, however one difference might be, AppHosts are what you run and what listens for HTTP requests. We have a quick video tutorial that might help with this here →

If you are finding it hard to manage all your services in one AppHost, you might want to consider breaking them up into logical ServiceModel/ServiceInterface projects, however the constraint of uniquely named RequestDTOs still exists for each hosted AppHost. This same constraint also exists for any services added via Plugins. A Plugin can add the Services, how the Request DTOs still need to be unique within the AppHost. How those features are registered can be a bit different compared to working with your AppHost directly, the different life cycle interfaces sometimes need to be used to make your plugin register what it needs at different stages.

Plugins aren’t meant to wrap up entire applications/projects, but rather make individual features more composable. This can help especially for when you might have multiple AppHost projects.

I really appreciate your feedback on your journey coming from Django and learning ServiceStack, it helps us develop better documentation/tutorials. We are missing a longer concrete walkthrough of the development of custom Plugins, so this is something we’ll look at creating additional learning resources for, to make it easier to understand and leverage. If you feel there are any other gaps let us know, and I can either point you in the right direction or also look at how other docs and tutorials can be improved.

1 Like

As Darren mentioned plugins are for wrapping composable functionality which works for encapsulating any features, functionality, embedded resources and services a specific feature needs, but they’re not intended for splitting up your Application.

The recommendation is that all your DTOs are in your ServiceModel project which defines your typed Services contract. I go into explaining the importance of DTOs in the Complexity, Services and Role of DTOs docs. A DTO is a canonical symbol for a structure that your Service exports which is important that it’s unique. You can have multiple duplicate type names and that will serialize fine like it does in any Web Services framework but to support code generation in non .NET languages they need to be unique.

Smaller to medium sized projects should typically not need more than a single ServiceInterface assembly for your Services implementation. For larger projects I would refactor out the implementation of Services into a ProjectName.Logic assembly like EventMan.Logic that the Physical Project Structure docs mentions.

Whilst for even largest projects the Modularizing Services docs shows an example of how you can split your Services implementation across multiple assemblies, e.g:

public class AppHost : AppHostBase
{
    //Tell ServiceStack the name of your app and which assemblies to scan for services
    public AppHost() : base("Hello ServiceStack!", 
       typeof(ServicesFromDll1).Assembly,
       typeof(ServicesFromDll2).Assembly
       /*, etc */) {}

    public override void Configure(Container container) {}
}

This should be able to handle splitting out even the largest of projects, if you need even more modularization than you should start thinking about Microservices to split out cluster of functionality into different AppHosts which the Service Gateway can help with for any inter service calls.

Thanks for the helpful replies @layoric and @mythz

This was the impression I was left with from the documentation. The plugin feature is more about being able to “bolt on” mostly self contained functionality that you want to encapsulate and separate out, be it as a separate csproj in the same solution or a fully separated nuget package. They are primarily designed to “plug in and add on” their functionality, not as a generic “sub-component” complexity management mechanism.

Thanks. In all honesty documentation has been the biggest part of the learning journey by far. Using C# for several things now for a couple of years (compared to the >10 I have with Python) the language has few pitfalls, and is quite expressive. But the documentation, its wild… there’s excellent patches that clearly show how to do things, often smaller packages, that are fantastically documented, then there are huge swaths of documentation that is basically the .Net equivalent of the exported Java class docs with nicer HTML and CSS that doesn’t make your eyes bleed, there’s mountains of “just install our VS addon/plugin and use it to generate this based on these convenient class annotations” with zero other documentation on how to manually code anything and maybe some API docs on how the generated code can be used, and I seem to have picked a terrible time to learn a new skill as the wider educational market has drifted to monetised YouTube videos and self hosted course platforms instead of books and blog posts, and stack overflow is full of very old dotNet and C# content from back in the Foundation only days when it was a windows only world.

The ServiceStack docs are among the best I have found in the .Net world! But as a user of the framework I do find them a bit lacking compared to the documentation of Flask or Django in the Python world. Where there is a thorough onboarding section to introduce all (or at least the most common 80%) of the framework’s features and explain any framework specific terminology or methodologies to the new user before also including more detailed “how to use” reference and API documentation.

Just to clarify that a bit, your Django “site”/“project”, specifically the “WSGI config” is the HTTP handling entry point that would be most equivalent to the AppHost, and thanks to the extra context you’ve both provided provied in your replies, I now see that there isn’t actually an equivalent in ServiceStack to an application in a “Django app” sense of the word. I can make my own substitute by grouping multiple ServiceModel/ServiceInterface sets together as part of a larger dotNet Solution, but that’s just a difference in code organisation strategy (and it that might be worth adding to the physical layout docs as an example of what comes next as a project grows if there aren’t downsides I’m not aware of yet)… I can have TopLevelProject TopLevelProject.component_one.ServiceModel, TopLevelProject.component_one.ServiceInterface, TopLevelProject.component_two.ServiceModel, TopLevelProject.component_two.ServiceInterface and so on… and so as long as all the project and solution references are configured correctly as far as ServiceStack, C# and dotNet are concerned, it’s all the same to them as if there was just TopLevelProject, TopLevelProject.ServiceModel, and TopLevelProject.ServiceInterface. Nothing has been “modularised”, its just better organised.

To your point here @mythz

makes sense in this light, and also highlights one of the things that I find hard to reason about about based on the current documentation. To me this kind of a refactoring makes sense, if the service has logic spread out and its hard to work with, pull that into its own assembly/module, but adds yet more context to an implicit impression I have of ServiceStack, that its primarily designed for “microservices”/“self contained” services…

The experience I’ve had with Flask and Django in Python, Rails with Ruby, and Phoenix with Erlang/Elixir have involved projects where multiple things are handled by the one codebase… It will have logically grouped sections of functionality for all the things that have been added to the codebase/project because everyone is trying to contain complexity (Complexity, Services and Role of DTOs). Something might begin as an inventory and stock tracking system, then get extended to add warehouse management, then add external logistics for shipment tracking, then regulations change and they have to add a dedicated auditing history functionality, and one manager really wants to be able to plan and track future projects so you end up with some bare bones project management functions… all of this can co-exist neatly inside a Django project, each large enough logical section getting its own Django application, with its own collection of related database models with their specific business logic attached for the CRUD actions being performed on them, each mostly self contained but with relationships to models in other applications as appropriate, common things getting factored into utility applications to keep things DRY, and overall the complexity gets managed… which I don’t have examples of how to do for ServiceStack.

There are a couple of examples that show complete working Code-First projects like GitHub - ServiceStackApps/EmailContacts: Example layout of a typical medium-sized ServiceStack App with Rabbit MQ enabled, GitHub - NetCoreApps/Chinook: AutoQuery APIs around Chinook SQLite DB and GitHub - NetCoreApps/BookingsCrud: Code-first, declarative, multi-user .NET Core Booking system using Auto CRUD & ServiceStack Studio but these are small enough that they would comfortably live in a single Django application, GitHub - ServiceStackApps/Northwind: Northwind Data Servicified with ServiceStack seems like it might be a “two app” Django project if you wanted to keep things more tidy than they currently are but that’s a matter of preference and not being code-first it’s not a good example of how to managing a code first project project, beyond that its sort of left to us the user as an exercise in our best judgment how to fight the complexity as applications grow in scope and keep things organised, as there are no examples (at least that I have found) of what sort of layout would be even notionally better one way or the other.

I have to point out most of this does make more sense to me personally now I’m not confused by mis-understanding the point of the plugin mechanism, and I can see that ServiceStack is sticking to its guns on YAGNI by not building mechanisms that it doesn’t need to do what its trying to do… But since I’m here I’m just taking the opportunity to highlight what feels to me like a shortcoming of the documentation overall to someone with the bulk of my experience coming from outside the C#/.Net ecosystem. Much of my frustration learning anything C# or .Net related are because the framework, the compiler or the IDE will just do something for me, and the documentation doesn’t feel the need to mention these externalities, its been a consistent experience across all the documentation I’ve read for things in the C#/.Net ecosystem, if I’m struggling to understand something, 80% of the time it turns out to be because the documentation has assumed I already know something is going on elsewhere that they never mentioned, (and 80% of that is usually because they didn’t fully explain what Dependency Injection stuff they are expecting so I’ve made a mistake when initially adopting their module)

2 Likes

Thanks for the detailed feedback, also checkout:

For examples of larger projects, but still not large enough to refactor their ServiceInterface into multiple assemblies. It would need to be a fairly large project to require me to want to do add an additional assembly (typically the reasons for adding assemblies is to do with cohesion and dependency requirements rather than size), but my approach would be fairly straight forward, ServiceModel DTOs define your services contract, ServiceInterface is your surface level implementation of the contract and the implementation of those services can invoke different dependencies for their logic which can be refactored as you see fit.