Missing namespaces and types

I have a server solution with the following structure:

And these are the namespaces created in the generated code file:

What I am missing is:

  • All classes under BizBusLicenseServer.ServiceModel.Model e.g. AccountActivity, CommandMsgProtocol etc.
  • All classes under BizBusLicenseServer.ServiceModel.Util e.g. UserAuthToken

The DTOs I have in DLLs (see Dependencies | Assemblies) and are correctly detected and generated (very cool by the way…)

The interesting bit is, that the generator creates all classes that are in the namespce BizBusLicenseServer.ServiceModel.Model.PushMessages which is a sub-folder / namespace of Model. It also took my Interfaces from BizBusLicenseServer.ServiceModel.Interfaces, which I don’t need and like on the clients.

Any idea what is wrong here? When I ran my software only on Windows and the target framework was 4.6.1, I was sharing DLLs between projects (Servers and Clients). Since my servers are now targeting .NET Core 2.0, I prefer using the ServiceStack Reference feature at least for the clients whitch are all targeting the .NET “full” framework(s).

I tried to uncomment IncludeTypes like so:

IncludeTypes: BizBusLicenseServer.ServiceModel.Util/*,BizBusLicenseServer.ServiceModel/*

But this ended in an empty file only containing using statements:

 using System;
 using System.Collections;
 using System.Collections.Generic;
 using System.Runtime.Serialization;
 using ServiceStack;
 using ServiceStack.DataAnnotations;

What do I need to do to get these missing classes?

If you can put together a stand-alone repro on GitHub I’ll be able to identify and resolve the issue.

But you can add missing namespaces with the AddNamespaces customization option:

AddNamespaces: BizBusLicenseServer.ServiceModel.Util, BizBusLicenseServer.ServiceModel

Or you can include the additional namespaces in your AppHost:

var nativeTypes = this.GetPlugin<NativeTypesFeature>();
nativeTypes.MetadataTypesConfig.AddNamespaces = new[] {
    "BizBusLicenseServer.ServiceModel.Util",
    "BizBusLicenseServer.ServiceModel",
}.ToList();

Hi Demis,

I tried both, uncomment AddNamespaces and using the plugin on the server. Both do not work, the additional namespaces are not seen and are causing errors. The following screenshot show the error on the client in VS2017.

I can try to stip down the project but this will require quite a bit of time. Don’t know if the problem has something to do with the many dependencies and DLLs I need in the project…

I would greatly appreciate if you have any hint what I could try to diagnose more on this project, before I start create a new one…

Edit:
I was just looking at the console on the serverside and found the following entries:

Now listening on: http://172.16.63.241:6090
Application started. Press Ctrl+C to shut down.
[08:53:56 INF] Request starting HTTP/1.1 GET http://172.16.63.241:6090/types/csharp?Date=2018-04-26+08%3A07%3A01&Version=5.02&Tip=To+override+a+DTO+option,+remove+"%2F%2F"+prefix+before+updating
[08:54:02 WRN] Property ‘date’ does not exist on type ‘ServiceStack.NativeTypes.TypesCSharp’
[08:54:02 WRN] Property ‘tip’ does not exist on type ‘ServiceStack.NativeTypes.TypesCSharp’
[08:54:02 DBG] Saved session with Id btwMMHzRBk7ANATfCSon.
[08:54:02 INF] Request finished in 6221.61ms 200 text/plain; charset=utf-8

Don’t know if this means anything…

Your ServiceModel DTO project should not have any dependencies other than ServiceStack.Interfaces.dll

You need to uncomment the options in the header for it to take effect. The warnings are just the service being called with unknown properties, it doesn’t have any affect.

You can also try setting GlobalNamespace to have all DTOs under the same namespace.

The screenshot above shows the file, when using the plugin on the server, so it was sent from the server with the line comments and the two namespaces:

server:

        var nativeTypes = this.GetPlugin<NativeTypesFeature>();
        nativeTypes.MetadataTypesConfig.AddNamespaces = new[] {
            "BizBusLicenseServer.ServiceModel.Util",
            "BizBusLicenseServer.ServiceModel",
        }.ToList();

GlobalNamespace I tried as well but no change, same problems.

But I think your statement

Your ServiceModel DTO project should not have any dependencies other than ServiceStack.Interfaces.dll

brings us closer to the problem. I have a lot more dependencies:

And I have good reasons to have them:

I have a DLL with all my Enums. I use them everywhere in all my (micro-)services and even on the clients. To avoid multiplicated code I created a library project currently containing four .cs files, grouping those enums a bit. They contain lots and lots of Enums. This DLL is referenced in almost every project I have in my current application context.

However the ServiceStack References tool returns exactly THREE of them:

namespace BizBusEnums
{

public enum AccountActivityPeriod
{
    All,
    Today,
    Yesterday,
    ThisMonth,
    Past5Days,
    Past10Days,
    Past20Days,
    Past60Days,
}

public enum AccountActivityType
{
    All,
    AccountCreation,
    AccountDeletion,
    AccountUpdate,
    AccountArchiving,
    AccountAddedToTenant,
    AccountRemovedFromTenant,
    RoleCreation,
    RoleUpdate,
    RoleArchiving,
    Login,
    Logoff,
    ResetPassword,
    ForcedPasswordReset,
}

public enum AccountType
{
    All,
    SystemAccount,
    UserAccount,
    ServiceAccount,
}

}

I have no idea, what criteria selects exactly these three enums and ignores all the dozens of others…

Another example is the MongoDB.BSON library. It has a type ObjectID which is the primary key for every document. Since I use REST to handle synchronous communications between all my servers I don’t want to change them to strings all the time. For example my ‘MessageDTOs’ I use for RabbitMQ have only strings because these objects can also be consumed by services written in languages that may not have a MongoDriver.

So in this project, I must have a lot more dependencies then just the ServiceStack.Interfaces.dll.

So are you saying then, that ServiceStack References does NOT work, if the ServiceModel project contains more complex dependencies??

That would be really sad, because it is an excellent feature which avoids shipping DLLs around. It would mean for me, that I have to build all my DLLs multi-platform (.NET core AND .NET 4.x), since I cannot use a .NET core DLL in a windows WPF project. Also there will be soon another team that will build a Web UI probably using Angular. For them, ServiceStack References would also be an excellent thing to get the data definitions for my REST APIs!

No they should not have dependencies, the purpose of DTOs is to define your Services Contract, having dependencies breaks this contract and the interoperability that goes with it which is one of the core tenants of a Service and also the fundamental design ServiceStack enforces where all ServiceModel projects only has a reference to the impl-free ServiceStack.Interfaces.dll. You never need to leak impl models into your Service Contract, the way to decouple it when needed is to have a separate DTO and use mapping to bind them to your internal models.

Breaking this contract means your Services are no longer interoperable and Native Service Reference won’t work. You can still share dlls as long your DTOs are POCOs do not contain circular references or any implementation that breaks serialization. But you’re Services are still limited to only .NET clients.

It’s highly recommended to only use impl-free DTOs in future, breaking this rule is source of runtime issues.

Ok, I am migrating server by server and remove dependencies from the .ServiceModel project where ever this is possible. I still have a problem with missing types but only with Enums and I think I figured out why:

In the DTO I define a bunch of Enums, but NOT ALL of them are used in the .ServiceModel project but they are used in the .ServiceInterface AND the client(s). So I defined all Enums which are used on both ends (server and client) in the .ServiceModel project.

It looks like ServiceStack.Reference seem to only generate types, which are used in the .ServiceModel project. If they are defined but NOT used, they seem to be ignored. Maybe you build a dictionary of used types using Reflection (I did not search for the code).

And then there is a second problem which is maybe more or less cosmetic but causes a warning from “Re-sharper or Rider” saying “Virtual member call in constructor”. I have this situation only in “Response DTOs” where I return collections and where I initialize those collections in the constructor like so:

public SubscriptionDto()
{
      Subscribers = new List<TenantSelectorDto>{};
      TransactionList = new List<TransactionSelectorDto>{};
}

If the class could be made sealed this warning would disappear, which would require that you add an option

//MakeSealed: True

sometime in the future. The result would be class definitions like so:

    public sealed partial class SubscriptionDto

Don’t know if this makes sense for you.

DTOs should not contain any implementation. The DTOs should only contain the Data Structure definition which is all that can be observed from reflection and emitted in source code and the only thing that should be used to to define a public services contract.

This is just a warning, it doesn’t have any effect on behavior. Your proposal is to resolve a warning that shouldn’t exist. We’re not going to add unnecessary features and complexity to enable use-cases that shouldn’t exist. The DTO pattern is what enforces a well-defined service boundary that’s decoupled from your implementation and ensures interoperability, breaking it is an anti-pattern that’s a source of runtime issues, we’re not going to add features to work around any issues arising from violating it.

As you’re Service Model isn’t a dependency-free and implementation-free DTO project, you can’t use the Add ServiceStack Reference feature and should continue to distribute your .dlls to clients.

As you say it is a warning and does not really bother me.

But what really hurts me is the other problem: It does not transfer certain types!

Does dependency free mean you cannot add a reference to another DTO dll which is dependeny free?

Sample:

The dependencies of BediDto.dll are:

If this is really NOT working, then I cannot use it and need to write DLLs with binaries for Windows and Linux. Otherwise it is ignoring classes AND Enums.

It’s not expected for there to be more than 1 ServiceModel.dll but I’m not aware of anything preventing it.

It will only generate DTOs referenced from public (I.e not hidden) Services where it should include any concrete Types the Request and Response DTOs Reference in their public properties. So first ensure the missing Types are being referenced through public properties of public Services. If they are being referenced but not generated, put together a stand-alone project (e.g on GitHub) that repro’s the issue and I’ll take a look.

Ahh, this explains the missing types! The Enums and also static classes containing const string are not exposed as props or return values.

Here is a sample which illustates it:

public class MyClassDto
{
    public List<string> Roles {get;set;}
    ........
}

The class I use in my business and persistency layer (MyClass) is converted by AutoMapper in both directions. In some cases I use T4 “macros” to auto-generate DTOs from my domain objects. (unfortunately I did not find a replacement of T4, it is not supported in JetBrains Rider since it seems to use Roslyn)

To define all available roles I have a class containing some constant strings. It is defined in the .ServiceModel project:

public static class AccountRoles
{
    public const string Administrator = "Administrator";
    public const string All = "All";
    public const string User = "User";
    // other roles
}

Somewhere in my business layer I have code like:

var myClass = new MyClass();
myClass.Roles.Add(AccountRoles.Administrator);

Also in some RequestDTO``s I may supply a list of strings containing several roles to query objects matching these roles. In both cases the typeAccountRoles` is used internally on client and server but not exposed as public property somewhere!

AutoMapper converts these objects between DTO and domain object in a service and on the serverside everything works just fine. But on the client I may have code like

var myUiClass = new MyUiClass(myClassDto);
if (myUiClass.Roles.Contains("AccountRoles.Administrator")
{
    //do something in the UI
}

This will fail because the type AccountRoles was not transfered due to the fact it does not appear as a property in a DTO or a return value of a service! The exactly same is true for Enums I miss on the client side!

So I need to find a solution for these scenarios by either creating a MultiPlatform DLL for these kind of objects or have duplicated code (which is not really an option…).

They absolutely need to be. consts or static classes are never emitted as their references cannot be observed from reflection. For any other missing Types/Enums you want to include but aren’t referenced you can create a Dummy Service that holds them. e.g:

public class DummyTypes : IReturn<DummyTypes>
{
    public MissingType MissingType { get; set; }
}

public class DummTypeService : Service
{
    public object Any(DummyTypes request) => request;
}

Thanks Demis, that was the information I needed!

Are you using something like T4 internally or do you have an alternative that is better supported on .NET core?

Just vanilla C# code using StringBuilder most of the code for C# is in CSharpGenerator.cs.

But if we ever needed a template solution I’d be using http://templates.servicestack.net instead of T4 or Razor which is also just code, with no dependencies, tooling or custom build steps required.

Yeah, saw that you have introduced this recently. Need kind of dynamic Email templates which I can use at runtime. Need to look at it as soon as I have time…

When you look into it, check out the TechStack’s Email Solution documented in the latest Release Notes which uses the new BackgroundMqService to send emails in the background.

Really cool!! :smile:

I’m not yet on 5.1, need first to read your long, long, long release notes to figure out, if there are impacts on my code when upgrading!

But guess what I have added a couple of weeks ago to my task-list: Replace SmtpClient with RabbitMQ. There I found this plugin which I wanted to test.

Now I will definitely look into your new Background Service functionality! Thanks for that great work!