Accessing User and Security Entity Properties in SalesLogix Web

There are likely many cases in SalesLogix Web where you need to access properties on the User and Security related entities that are not included in the entity by default, meaning that there is no public property exposing the value. For example, the IsManager property on the User entity. A co-worker of mine ran into just this problem this week (See Retrieving the Manager in SalesLogix 7.5 Web)

The Problem

The root of the problem is that there are some often necessary properties on the User & Security related entities that are not included in the entity. See the image below:

Notice in the image above that the “Include” checkbox is not checked for the IsManager property on the User entity. What the Include value means is whether to include a public accessor property for this when the entity is built. So, you might think that checking this checkbox and doing a build will make it available to you at runtime. You build & deploy and get no errors. However, when you attempt to access the site you get a runtime error that states the following:

System.TypeLoadException: Method ‘get_ManagerId’ in type ‘Sage.SalesLogix.Security.User’ from assembly ‘Sage.SalesLogix.Security, Version=, Culture=neutral, PublicKeyToken=null’ does not have an implementation

Here is why you are getting this error; the “Packages” in the entity model are more than just for the sake of organization. The “SalesLogix Security Support” package of entities does not just exist to separate these entities from the others. Each package is built to a separate assembly. They can have different templates for code generation. They can also have properties to indicate whether they are built into an assebmly at build time at all. This is the case with the User and Security entities in the SalesLogix Security Support package. If you open the package itself and “Build Settings” tab you will see something different about this package.

You can see in the screenshot above that the SalesLogix Security Support package isn’t event built when you build the web platform. However, it’s interface is. When you check the Include checkbox on the IsManager property it is added to the interface. This is why you don’t get a compile error when you use it in a code snippet because you’re likely using the User entity via it’s interface. However, since the assembly is not built as well there is no implementation for the IsManager property that now exists in the IUser interface, hence the “does not have an implementation” error. Checking the box for “Generate Assembly” on the package won’t fix the problem. If you do, you’ll get compile errors. These User and Security entities are available in the Application Architect so you can create relationships to them from other entities, however their implementation is quite different and the standard code generation templates will not account for all the extra things they do. So, what is the solution?

The Solution

Knowing why you’re getting the errors and what the problem is does not exactly help in getting to these not-included values that you need from these entities. However, there is hope. When you access any entity in SalesLogix code, you’re likely accessing the entity via it’s interface (as you should). However, I mentioned above that there is a lot more to the implementation of the User and Security entities. That is where you’ll find what you need.

Normally, you would access a User, such as the current user, like this:

Sage.SalesLogix.Security.SLXUserService usersvc = (Sage.SalesLogix.Security.SLXUserService)Sage.Platform.Application.ApplicationContext.Current.Services.Get<Sage.Platform.Security.IUserService>();
Sage.Entity.Interfaces.IUser user = usersvc.GetUser();

Note that you are accessing the User via the IUser interface. Now, the IUser interface is just a standard entity interface. Since the interface is being built when you do a “Build Web Platform” (note, the checkbox to build it’s interface is checked for the package) it is a true representation of what you see in the Application Architect. However, there is quite a bit more to it’s implementation found in the User class. Fire up Reflector and take a look at some of the things available in Sage.SalesLogix.Security.User:

Notice all the extra goodies there to use? For example, the Manager property, that returns a Manager object. The Manager class simply inherits from User, meaning that it has all the properties and methods that a User object has as well as a few more. To use this property, as well as the others in the User class, you just need to use the reference via the User class instead of via the IUser interface. Something like this:

// get the current user as a User (not IUser)
Sage.SalesLogix.Security.SLXUserService usersvc = (Sage.SalesLogix.Security.SLXUserService)Sage.Platform.Application.ApplicationContext.Current.Services.Get<Sage.Platform.Security.IUserService>();
Sage.SalesLogix.Security.User user = usersvc.GetUser();

// now get the user's Manager
Sage.SalesLogix.Security.Manager manager = user.Manager;
string manageremail = "Manager e-mail: " + manager.UserInfo.Email;

Note that the code is basically the same as when you accessed the User via the IUser interface. You just use the actual implementation class instead and you can get to what you need.

A Solution for All Cases?

This is not a solution for every case. There will without question be some properties that you just can’t get to. The “last resort” solution to access these inaccessible properties is to go to the database. You can easily get a connection to the underlying database and use that to query for the value you’re after. Here’s an example:

// get the manager's e-mail address using a connection to the database
// Note: this is just for example purposes, instead of doing this
// use the user.Manager property available on Sage.SalesLogix.Security.User

string manageremail = string.Empty;
// get the DataService to get a connection string to the database
Sage.Platform.Data.IDataService datasvc = Sage.Platform.Application.ApplicationContext.Current.Services.Get<Sage.Platform.Data.IDataService>();
using (System.Data.OleDb.OleDbConnection conn = new System.Data.OleDb.OleDbConnection(datasvc.GetConnectionString()))
    using (System.Data.OleDb.OleDbCommand cmd = new System.Data.OleDb.OleDbCommand("select from userinfo u1 inner join usersecurity u2 on u1.userid = u2.managerid where u2.userid = '" + user.Id.ToString() + "'", conn))
        object o = cmd.ExecuteScalar();
        if (o != null) manageremail = o.ToString();

This is not an ideal solution, and isn’t meant to be.In my opinion, accessing the database directly should absolutely be a last resort and avoided if possible. Why, the entity model is rich and complete in most cases. The majority of times I’ve seen someone go direct to the database it is more than likely because of a lack of knowledge of how to do something in the entity model, not because the entity model could not provide what was needed. Business rules that might be in place in the entity model will not apply to things you do in the database (unless they are implemented in Process Orchestration).

Ideally these properties in the implementation that are hidden by their absence in the interface would just be included in the interface. However, knowing that some of these things are there, and how to get to them, will definitely save you some headaches.


Ryan Farley

Ryan Farley is the Director of Development for Customer FX and creator of He's been blogging regularly about SalesLogix, now Infor CRM, since 2001 and believes in sharing with the community. His new passion for CRM is Creatio, formerly bpm'online. He loves C#, Javascript, web development, open source, and Linux. He also loves his hobby as an amateur filmmaker.

Submit a Comment

Your email address will not be published.

Subscribe To Our Newsletter

Join our mailing list to receive the latest Infor CRM (Saleslogix) and Creatio (bpm'online) news and product updates!

You have Successfully Subscribed!