Login / Register  search  syndication  about

          Ryan Farley's Blog

Ryan Farley on .NET Development with a focus on CRM Development for SalesLogix

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=7.5.0.1484, 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()))
{
conn.Open();
using (System.Data.OleDb.OleDbCommand cmd = new System.Data.OleDb.OleDbCommand("select u1.email 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.

What's This?
  
Bookmark and Share

About Ryan Farley

   Ryan Farley is the Director of Development for Customer FX and creator of slxdeveloper.com. He's been blogging regularly about SalesLogix since 2001 and believes in sharing with the community. He loves C#, Javascript, Python, web development, open source, and Linux. He also loves his hobby as an amateur filmmaker.

View the SalesLogix Mobile Seveloper Series
View the SalesLogix SData Developer Series
View the Git for the SalesLogix Developer series



Related Content
   Video: Demystifying Infor CRM (Saleslogix) Updates
Watch it now! If you missed yesterdays demo, "Demystifying Infor CRM (Saleslogix) Updates" ,
Posted on Sep 26, 2014 by Brianna Ojard to The Inbox
 
   Official Infor CRM Acquisition FAQ
What to expect now that Saleslogix is Infor CRM. Like many of you, it will take some time (probably a
Posted on Sep 18, 2014 by Brianna Ojard to The Inbox
 
   Problem with the Clean Build Folders option in Application Architect
On occasion, it becomes necessary to clean out the build folders and deployed website prior to a build/de
Posted on Sep 16, 2014 by Jason Buss to Jason Buss' Blog
 
   Restricting Adding Opportunity Contacts to Contacts at the Opportunity's Account
 One thing that clients have asked for is how to restrict the selection of the Opportunity Contacts
Posted on Sep 09, 2014 by Kris Halsrud to Kris Halsrud's Blog
 
   How do I access the new Opportunity that I created in Saleslogix??
I had a user ask why they could not access a Salelogix opportunity when they clicked the hyperlink from t
Posted on Sep 04, 2014 by Dale Richter to SalesLogix Questions & Answers
 
Comments

 

CRM Developer said:

Five years ago I wrote a post about how to determine if a user is a member of a team in SalesLogix LAN scripts that is still referred to today. I&#39;ve been asked on occasion how one would go about doing the same in the SalesLogix Web platform, so I

February 4, 2009 3:56 PM
 

Kris Halsrud said:

On other blogs people have blogged a couple of times, like here and here , about how to use the Sage

November 19, 2009 4:25 PM

Leave a Comment

(required)  
(optional)
(required)  
Add
All contents Copyright © 2014 Customer FX Corporation
Customer FX Corporation
2324 University Avenue West, Suite 115
Saint Paul, Minnesota 55114
Tel: 800.728.5783

  Follow @CustomerFX on twitter
Follow the best news, tips, and articles
  Subscribe to Customer FX on youtube
Watch SalesLogix tutorial videos from Customer FX
Login / Register