Quantcast
Channel: SData – Customer FX
Viewing all 32 articles
Browse latest View live

An Overview of SData – The SalesLogix Web Enabled API

$
0
0

Chances are, if you work or use SalesLogix (or any Sage product) you’ve heard of SData by now. SData is a basically a web enabled API for SalesLogix allowing you to interact with SalesLogix data from an external application or website. The great thing about SData is that it is a specification that is implemented via RESTful web services. This means you’re not limited to using SData with a particular technology (such as exclusively via .NET). In a nutshell, SData works via sending and receiving XML payloads via a URL. Pretty simple. This article will take a high-level overview of SData as an introduction (which means there will be several more in-depth posts on the way).

View the SalesLogix SData Developer series index

SData Versions

We started to see parts of SData as early as SalesLogix 7.5 and even more in 7.5.1. While these versions did work, SData wasn’t exactly considered fully-baked until SalesLogix 7.5.2 (and even more functionality added in 7.5.3 such as picklist support). Needless to say, there were significant changes in 7.5.2 from it’s earlier beta versions in 7.5.1 and prior. These changes were breaking changes, so if you’re on 7.5 or 7.5.1 what I will be outlining here won’t fit completely. The URL structure will be different and the way the payload is deilivered is quite different (but you’ll still get the general ideas from this article, just bear in mind you’ll have these changes to deal with).

The SData Server

The SData server is deployed from the Application Architect as a web portal. However, I do want to point out that using SData does not mean you have to be using the SalesLogix Web client. You can be an all LAN implementation and still deploy an SData portal. You only need to be on a version that includes support for SData. The SData deployment will create an “sdata” application in the deployment location (so you will have this next to your typical “slxclient” folder if you have a SalesLogix Web deployment). If you have a SalesLogix Web deployment then also deploying SData can be simpler since SData also uses the same entity model.

The Anatomy of an SData URL

Using SData comes down to an XML payload exchange via a URL. Knowing how these URLs are formed is important, and luckily, they are pretty easy to understand. A sample SData URL to access a list of Accounts would look like this:

http://server:port/sdata/slx/dynamic/-/Accounts

Let’s break down what all those values mean:

  1. server & port: These are the server address and port of your SalesLogix web deployment.
  2. sdata: This is the deployment folder for the SData portal. As I mentioned earlier, the SData portal will reside as a folder named sdata next to your slxclient portal deployment.
  3. slx: The application name. SData is a specification that is currently used by several Sage applications, not just SalesLogix.
  4. dynamic: This is the contract name. I won’t get too deep into this now and may address this in a future post, but an SData deployment can support several integration contracts. For now, just stick with dynamic.
  5. -: This part of the URL defines the dataset to use. Stick with the hyphen “-” which means the default dataset (or that the application only supports a single dataset).
  6. Accounts: This is a resource to access, more on this next.

SData Resources

A resource is the entity type or table that you wish to query (or add, modify, delete, etc). Not all entities or tables are exposed by default. You get to pick and choose which entities are exposed via SData in the Application Architect (open the entity and you’ll see an SData tab ewhere you can specify whether the entity is exposed or not.

Sample SData URLs

Here’s some useful sample SData URLs you can use to query SalesLogix data via your browser. This is a great way to test things. When you access one of these URLs in your browser you’ll be promoted for your SalesLogix login credentials. One thing to keep in mind as you use these, normal SalesLogix security applies, so you’ll only see records that the user you’re logged in with can see.

Get a list of all adapters or resources exposed by the dynamic contract
http://server:port/sdata/slx/dynamic/-

Get the schema for an entity (account entity)
http://server:port/sdata/slx/dynamic/-/$schema(Account)
or
http://server:port/sdata/slx/dynamic/-/accounts/$schema

Get a list of all products
http://server:port/sdata/slx/dynamic/-/product

Get first 10 products only
http://server:port/sdata/slx/dynamic/-/product?count=10&startIndex=1

Get a specific product by ID
http://server:port/sdata/slx/dynamic/-/product(‘YDEMOA000002’)

Get child entities for an entity (contacts for account)
http://server:port/sdata/slx/dynamic/-/Accounts(‘AGHEA0002669’)/Contacts

Query accounts where AccountName starts with ‘Ab’
http://server:port/sdata/slx/dynamic/-/accounts?where=AccountName like ‘Ab%’

Query accounts where AccountName equals “Abbott Ltd.”
http://server:port/sdata/slx/dynamic/-/accounts?where=AccountName eq ‘Abbott Ltd.’

The SData Client Library

If you’re using .NET with SData, one of the more easy ways to work with it is using the SData Client Library developed by Sage. When using the SData Client Library you don’t necessarily need to know how to structure the SData URLs, but that certainly does help. The source for this lirbary is available on github as well. I will definitely have more posts on this in the future including how to use, best ways to get this library and more.

View the SalesLogix SData Developer series index


Getting Started with SData for SalesLogix – Installing the SData Client Library

$
0
0

In my previous post, an Overview of SData, I outlined the working parts and anatomy of the web enabled API for SalesLogix known as SData. In this post I will show you how to take your first step with how to get the SData Client Library.

View the SalesLogix SData Developer series index

Getting the SData Client Library?

As I mentioned in my previous post, the best route to take when using SData is to use the SData Client Library. While it is possible to parse the payload XML in an SData feed, using the client library will make this a very easy task. There are a few places to get the SData Client Library, however, the best and easiest place is from the NuGet packaging system. NuGet is a packaging system that you can install as an extension in Visual Studio 2010. You can get NuGet from the Microsoft Extension Library here. Once it is installed in Visual Studio, you can easily add libraries to projects – including the SData Client Library.

With NuGet installed, you can right click on the References folder of your project and select “Add Library Package Reference”

The NuGet dialog will open and you can search for SData and you’ll find the SData Client Library.


Click for larger image

When you find it, click the “Install” button and it will be downloaded and added to your current project. Some of the other ways you can get the client library is direct from it’s github repository. Stay tuned next time when I’ll show you how to use the client library and easily work with SData.

View the SalesLogix SData Developer series index

Retrieving Data via SData for SalesLogix

$
0
0

If you followed my last two posts, you’ll know some basics of what SData is and how to get it to use in your projects. In this post, we will take this a step further and look at how to actually use it, starting with how to query data from SalesLogix.

View the SalesLogix SData Developer series index

Getting a list of Contacts

Let’s start with a basic query. For this example, we will retrieve all contacts whose last name starts with ‘Ab’. Take a look at the code (with comments to walk through each part)

using Sage.SData.Client.Core;
using Sage.SData.Client.Atom;
using Sage.SData.Client.Extensions;
//...
 
 
// All requests require an ISDataService which provides
// the service location and user authentication values
ISDataService svc =
    new SDataService("http://localhost/sdata/slx/dynamic/-/", "lee", "");
 
// Now create the request, passing in the ISDataService we created
// above
var req = new SDataResourceCollectionRequest(svc);
 
// Tell it which kind of resource we want to access, in this case
// Contacts. Note, this needs to match the values on the SData tab
// of the entity in Application Architect
req.ResourceKind = "Contacts";

// This part is optional (without it we'd be getting ALL contacts).
// This is our where clause, or condition of which contacts we want.
// In this example we want all contacts whose last name starts with
// the value 'Ab'. We need to use the exact property name as defined
// in the entity (case-sensitive).
req.QueryValues.Add("where", "LastName like 'Ab%'");
 
// Now read the data (or run the query)
AtomFeed feed = req.Read();
 
// We now have the results in our AtomFeed variable, which is
// basically a list of AtomEntry objects. To get to our data,
// we need to read the payload from each AtomEntry and then we
// can access the values for each field from it's Values
// dictionary. In this example, we'll just write a few fields
// from each contact to the console.
foreach (AtomEntry entry in feed.Entries)
{
    // Get the payload for this entity
    SDataPayload payload = entry.GetSDataPayload();
     
    // Now read some values from the payload. Note, the
    // property names you use here need to match the property
    // names defined for the entity (these are case-sensitive).
    string account = payload.Values["AccountName"].ToString();
    string contactName = payload.Values["NameLF"].ToString();
    string title = payload.Values["Title"].ToString();
     
    Console.WriteLine("{0}, {1} from {2}", contactName, account, title);
}

That’s not too bad. You do have to access the fields by string name, which means you don’t get intellisense, but at least it’s easy code to write. There are ways to retrieve the schema for an entity which I will look at in a future post.

View the SalesLogix SData Developer series index

Writing Queries for the SalesLogix SData API

$
0
0

In this fourth post in the SalesLogix SData series, I will introduce how to write queries for SalesLogix SData and will point to a useful resource as you get started, or more comfortable with SData.

View the SalesLogix SData Developer series index

SData Query Language

Be sure to first take a look at my last post which covers how to retrieve data via the SData API. The ability to read data from SalesLogix via the SData API is only useful if you know how to control it. Reading all records from a table isn’t exactly useful. Knowing how to control which records you’re retrieving is a must. Fortunately, that is easy, but it does take some knowledge of the SData Query Language.

SData uses a language refered to as SData Query Lanaguage. So, what does this mean to you, another thing to learn? Not really. The syntax for the language is simple and easily guessable. If you know how to write NHibernate queries then this won’t look much different. As a matter of fact, if you know how to write SQL queries, this won’t really look much different.

Example Query Conditions

Before we get too deep into things, let’s take a look at some sample query conditions using SData. As I showed in the previous post (Retrieving Data via SData), you can use these conditions by adding them to the QueryValues collection of the SDataResourceCollectionRequest for the “where” part of the query.

  1. Retrieve all records created since 5/1/2011
    “CreateDate ge @2011-01-05@”
  2. Retrieve all account records whose Name starts with the letter A through L
    “left(AccountName,1) between ‘A’ and ‘L'”
  3. Retrieve all SalesOrders whose State on it’s associated BillingAddress is ‘AZ’
    “BillingAddress.State eq ‘AZ'”
  4. Retrieve all Accounts whose name contains the word Bank
    “AccountName like ‘%bank%'”

You’ll see something that looks familiar and understandable with all of those.

Query Conditions, Functions, & Operators

So what are all the possible things you can use in an SData query? Rather than list them all here, I will point to the official SData specification where it outlines the available functions and operators for SData.

SData Query Language  on SData Core Specification

View the SalesLogix SData Developer series index

Including Nested Payloads with SData for SalesLogix

$
0
0

When you’re developing an application or customization using SData for SalesLogix, the fewer trips you make to the server the better. Moving data back and forth across the wire will always be the biggest bottleneck in your code, so making use of embedded payloads will save you some trips by bringing all the data you’re after back in one pass.

View the SalesLogix SData Developer series index

What Are Nested Payloads?

Before we get into things, what exactly are nested payloads? Maybe a better term might be “included” payloads. Either way, when you request an entity, or entities, via SData, some part of the entity might be missing, or incomplete. Why? Because of the way that relationships work in the entity model. For example, if you request an Account entity, the AccountManager is a relationship to the User entity. These relationship properties are not included by default in the Account entity unless you tell SData you want those too. If you include related entities, such as the AccountManager, when you get back the Account entity you’ll have an nested payload inside the Account payload. So, no need to make another trip back to the server to get the AccountManager. One thing to keep in mind, including related entites will increase the size of the data coming back in the SData feed, this is why these are not included by default, so be sure only include them when you really need them.

Adding An Included Entity In An SData URL

I think it is important to know what the SData URL looks like when doing anything with the client library. I think it helps to understand what you’re ultimately ending up with. It also helps to see what the data coming back looks like using your browser by using the URL. When you want to include related entities you simple add an “include” parameter to the query string. For example, consider this URL to get a specific account:

http://localhost:3333/sdata/slx/dynamic/-/accounts('AA2EK0013023')

Now, to include the AccountManager entity as an embedded payload, add to the URL as follows:

http://localhost:3333/sdata/slx/dynamic/-/accounts('AA2EK0013023')?Include=AccountManager

To include additional related entities, such as all Contact entities for the Account, add that as well:

http://localhost:3333/sdata/slx/dynamic/-/accounts('AA2EK0013023')?Include=AccountManager,Contacts

Now when the Account entity comes back it will include an nested payload for the AccountManager, but also a collection of payloads for each Contact related to the Account – all in one trip to the server.

Including Related Entities Using the C# Client Library

Now that you know what the URL with includes look like, let’s take a look at how to write the code and how to use the nested payloads. We’ll use the example above to get a single Account and include the AccountManager and all related Contacts for the Account as nested payloads.

using Sage.SData.Client.Atom;
using Sage.SData.Client.Core;
using Sage.SData.Client.Extensions;


//...


var service = new SDataService("http://localhost:3333/sdata/slx/dynamic/-/", "admin", "");


var req = new SDataSingleResourceRequest(service);
req.ResourceKind = "Accounts";
req.ResourceSelector = "'AA2EK0013023'";


// We have to include the entities we want returned as nested payloads
req.QueryValues.Add("include", "Contacts,AccountManager");


// We can access normal properties of the Account
var string accountName = payload.Values["AccountName"].ToString();


// Now get nested payload for AccountManager
var accMgrPayload = (SDataPayload)payload.Values["AccountManager"];
// We can access properties in the AccountManager payload
var accMgrUserName = accMgrPayload.Values["UserName"].ToString();


// Get nested Contacts collection of payloads
var contactsPayloadCollection = (SDataPayloadCollection)payload.Values["Contacts"];
// And iterate through each one
foreach (SDataPayload contactPayload in contactsPayloadCollection)
{
    // We can access properties in this Contact payload
    var contactLastName = contactPayload.Values["LastName"].ToString();
}

The key is to just access the property in the entity and cast it to either an SDataPayload or a SDataPayloadCollection. Cool beans.

View the SalesLogix SData Developer series index

Error adding SData feed to a SalesLogix entity

$
0
0

I recently ran into an issue with trying to enable an SData feed on a custom entity.  I was actually trying to expose the PLUGIN table to SData in order to get around a different bug with SData.  I was able to add Plugin as a new SalesLogix entity to the entity model.  Building the web platform with this new entity was not a problem, but when I went to enable the “Generate SData feed” on the new entity, the web platform would not build.

I would receive an error like this:

 C:Documents and SettingsAdministratorApplication DataSagePlatformOutputsdataPlugin.cs(335,22):  Cannot implicitly convert type ‘Sage.Common.Syndication.FeedAuthor’ to ‘string’.

Looking at that line in the PLugin.cs file in my build folder revealed this line of code:

        public PluginEntry()
        {
            Author = new FeedAuthor {Name = Constants.FeedAuthor};
        }

Turns out that the problem was the Plugin entity contained a property called Author.  This was confusing the sdata build which attempts to create an SData feed property also called Author.  I ended up removing the Author property from my entity definition since I did not need it, and presto!  The SData feed built successfully.

Inability to query non ACO groups using the SalesLogix SData system groups endpoint

$
0
0

I recently ran into an issue when trying to use SData to retrieve group information for groups other than Account, Contact, or Opportunity groups.

SalesLogix stores non ACO groups as a different plugin type in the SLX Plugin table.  They are a type 23 rather that type 8 of the ACO groups.  This is the result of back when the support client used to be a separate animal than the sales client.

The
problem is that the group endpoint is supposed to allow querying syntax
to find a group by family and name.  It works OK for ACO groups but not
for any other groups.  So something like this works:

http://sdatahost/sdata/slx/system/-/groups/$queries/execute?_family=Account&_name=All%20Accounts
 
The underlying query for this is 
SELECT
PLUGINID FROM PLUGIN WHERE TYPE = 8 AND NAME = ‘All Accounts’ AND
FAMILY = ‘Account’ AND BASEDON IS NULL ORDER BY DEV DESC, MODIFYDATE
DESC
 
However, a similar query but to Defects does not work:
http://sdatahost/sdata/slx/system/-/groups/$queries/execute?_family=Defect&_name=My%20Defects
 
The underlying query:
SELECT
PLUGINID FROM PLUGIN WHERE TYPE = 8 AND NAME = ‘My Defects’ AND FAMILY =
‘Defect’ AND BASEDON IS NULL ORDER BY DEV DESC, MODIFYDATE DESC
 
Notice it is only looking at type 8 and not 23.
 
However a query on ID, like this, does work:
http://sdatahost/sdata/slx/system/-/groups(‘p6UJ9A0003H2’)
 
The underlying query:
SELECT
this_.PLUGINID as PLUGINID5_0_, this_.NAME as NAME5_0_, this_.FAMILY as
FAMILY5_0_, this_.TYPE as TYPE5_0_, this_.USERID as USERID5_0_,
this_.CREATEDATE as CREATEDATE5_0_, this_.LOCKED as LOCKED5_0_,
this_.LOCKEDID as LOCKEDID5_0_, this_.VERSION as VERSION5_0_,
this_.SYSTEM as SYSTEM5_0_, this_.ISPUBLIC as ISPUBLIC5_0_,
this_.DESCRIPTION as DESCRIP12_5_0_, this_.DATACODE as DATACODE5_0_,
this_.BASEDON as BASEDON5_0_, this_.TEMPLATE as TEMPLATE5_0_,
this_.AUTHOR as AUTHOR5_0_, this_.COMPANY as COMPANY5_0_,
this_.COMPANYVERSION as COMPANY18_5_0_, this_.BASEDONCOMPANY as
BASEDON19_5_0_, this_.BASEDONCOMPANYVERSION as BASEDON20_5_0_,
this_.RELEASED as RELEASED5_0_, this_.DEV as DEV5_0_, this_.READONLY as
READONLY5_0_, this_.INSTALLATIONDATE as INSTALL24_5_0_,
this_.RELEASEDDATE as RELEASE25_5_0_, this_.DISPLAYNAME as
DISPLAY26_5_0_, this_.MODIFYDATE as MODIFYDATE5_0_, this_.MODIFYUSER as
MODIFYUSER5_0_, this_.CREATEUSER as CREATEUSER5_0_ 
FROM PLUGIN this_  
WHERE
this_.PLUGINID = ‘p6UJ9A0003H2’ and this_.TYPE in (8, 23) and
this_.BASEDON is null ORDER BY this_.DEV desc, this_.MODIFYDATE desc
 
Notice it looks at both type 23 and 8.
 
Similarly, this query of the entire groups list returns everything:
http://sdatahost/sdata/slx/system/-/groups?format=html
 
Underlying query:
SELECT
* FROM (SELECT ROW_NUMBER() OVER (ORDER BY CURRENT_TIMESTAMP) as
SLXRN,  this_.PLUGINID as PLUGINID5_0_, this_.NAME as NAME5_0_,
this_.FAMILY as FAMILY5_0_, this_.TYPE as TYPE5_0_, this_.USERID as
USERID5_0_, this_.CREATEDATE as CREATEDATE5_0_, this_.LOCKED as
LOCKED5_0_, this_.LOCKEDID as LOCKEDID5_0_, this_.VERSION as
VERSION5_0_, this_.SYSTEM as SYSTEM5_0_, this_.ISPUBLIC as ISPUBLIC5_0_,
this_.DESCRIPTION as DESCRIP12_5_0_, this_.DATACODE as DATACODE5_0_,
this_.BASEDON as BASEDON5_0_, this_.TEMPLATE as TEMPLATE5_0_,
this_.AUTHOR as AUTHOR5_0_, this_.COMPANY as COMPANY5_0_,
this_.COMPANYVERSION as COMPANY18_5_0_, this_.BASEDONCOMPANY as
BASEDON19_5_0_, this_.BASEDONCOMPANYVERSION as BASEDON20_5_0_,
this_.RELEASED as RELEASED5_0_, this_.DEV as DEV5_0_, this_.READONLY as
READONLY5_0_, this_.INSTALLATIONDATE as INSTALL24_5_0_,
this_.RELEASEDDATE as RELEASE25_5_0_, this_.DISPLAYNAME as
DISPLAY26_5_0_, this_.MODIFYDATE as MODIFYDATE5_0_, this_.MODIFYUSER as
MODIFYUSER5_0_, this_.CREATEUSER as CREATEUSER5_0_ FROM PLUGIN this_ 
WHERE this_.TYPE in (8, 23) and this_.BASEDON is null) query WHERE SLXRN
>= 1 AND SLXRN < 101 ORDER BY SLXRN

Sage has acknowledged this as a defect but unfortunately they will not address until some point in version 8.  No existing versions will receive the fix.  So if you need to get the group information through SData you need to do it in 2 parts:

1a) Add the Plugin table as an entity in the SLX entity model and expose it for SData feeds.

1b) Query the Plugin sdata feed in the dynamic endpoint by name, family, and type.  From this get the plugin ID.

2) Use the retrieved plugin ID in the system group endpoint like so: http://sdatahost/sdata/slx/system/-/groups(‘p6UJ9A0003H2’)

Inability to edit or delete sales order or Opportunity products in the SalesLogix 7.5.4 web client

$
0
0

If you are running IIS 7 there is an important step you need to do in order to allow the SalesLogix web client to edit or delete products from both the Opportunity and Sales order product’s tabs.

Since the Product’s tab uses client side SData calls,  these calls can’t work right if the All Verbs setting isn’t set on the ‘SimpleHandlerFactory-ISAPI-2.0’.  

The Implementation guide has you set All Verbs, and create the Wildcard mapping on the SData portal.  Apparently this works in IIS6, but in order for the SLXClient portal to work completely in IIS 7, All Verbs needs to be set there too.

 


Sorting an SData base grid in the SalesLogix web client

$
0
0

In the SalesLogix 7.5.4+ web client the “editable grid” control that allows for inline editing and the like is based on a client side SData feed to bind and control updates.  An example of this is on the Sales Order Product’s tab.  This grid is actually rendered completely client side using dojo and its DataGrid implementation.  Because of this you can add client side scripting to work with the underlying grid and do things with it, like control sorting.

Working with the grid client side on a quick form is a bit of a pain as when the quick form is converted to a user control it is split into a ascx file with the normal controls rendered, along with any of the server code  on the form.  The grid itself only exists in the ascx form in the form of a placeholder where the dojo grid is loaded into.  All of the client script regarding the grid is built and deployed into a separate js file that can not be modified.  This means if you want to be able to add your own code you need to either create a stand alone js file that is accessed from the ascx file, or by injecting javascript within the ascx file.  It is this later option I am going to walk through today.

The easiest place to inject client script is on the quick form  load event.  Using the Scriptmanager.RegisterClientScriptBlock we can add code that is injected client side onto the page.  There is a bit of a hiccup in this though because depending on if the tab is active or not when the page loads, the client script loading can behave differently I will talk about how to handle this too.

Lets take a look at how to add the javascript code to do what we need.

First  we need to identify the name of the grid control as it exists in the DOM.  You can find the name of the grid by looking at the deployed file and searching for the empty div markup that is in the ascx that exists as the placeholder for the dojo grid.  It also seems like there is a standard naming convention for it which is the name of the quick form + the Control Id of the grid.  So for instance on the SalesOrderProducts quick form, it has a grid control called grdItems so the deployed grid DOM id is called “SalesOrderProductsgrdItems”.  Again we can look in the deployed file and find the empty div to get this, here is what it looks like:

<div id=”SalesOrderProductsgrdItems” style=”width:100%;” class=””>
    <div id=”SalesOrderProductsgrdItems_Grid” style=”width:100%;height:25px;”></div>
</div>

We want the name of the outer div, not the inner one. Now that we know the ID we can use that in a javascript code block to get the grid instance and manipulate it:

var grid = dijit.byId(‘SalesOrderProductsgrdItems’);

Now that we have an instance of the grid, we can do something like sort by a particular column:

grid.sortInfo = 5;
grid.sort();

Now the sortInfo is an index of the column you want to sort on.  Note that there are some hidden columns in the grid that are not rendered on the screen, so what you think is the first column may not be.  You might need to play around with the number to see which one is sorting.  You will be able to tell as a visual arrow representation will appear on the column heading of the grid column that has been sorted.

So a complete function can be written like:

dojo.require(‘dojox.grid.DataGrid’);   
function doGridSortCode() {
var grid = dijit.byId(‘SalesOrderProductsgrdItems’);
grid.sortInfo = 5;
grid.sort();
}

Notice I am including a command to include the dojo Datagrid library so my dijit.byId works. 

So now we have a function that will sort a grid, but how do we call it?  Well in my case I want to sort whenever the page opens.  You certainly could call this code from a client side click event of a button or something, but lets look at the page load:

What I will do is use the jQuery $(document).ready function.  We need it here because this function runs after dojo has rendered the controls.  Basically it runs after the DOM has finished being constructed by the browser.  However there is one more hurdle to overcome because of the async postback loads of tabs.  The solution is to use a recursive function within the ready function.  The recursive function simply checks to see if the dojo grid exists yet using the dijit.byId.  If it doesn’t it calls itself again until it does:

function wireSO(){
if(!dijit.byId(‘SalesOrderProductsgrdItems’)) setTimeout(function() { wireSO() }, 50);
else doGridSortCode();
}

So now we have a function that checks if the grid is there, if not it waits 50 milliseconds and then checks again.  if it is there it runs our function from earlier to sort the grid.

Finally we just need to add our recursive function in the ready function (and the pageLoad so it works on postbacks):

function pageLoad(){wireSO();}
$(document).ready (function () {
wireSO();}); 

So now that we have our client side code we can build a string variable in server side code containing it all and then register it on the page.  So in a quick form load action we can do something like:

string script = @”
dojo.require(‘dojox.grid.DataGrid’);   
function doGridSortCode() {
var grid = dijit.byId(‘SalesOrderProductsgrdItems’);
grid.sortInfo = 5;
grid.sort();
}

function wireSO(){
if(!dijit.byId(‘SalesOrderProductsgrdItems’)) setTimeout(function() { wireSO() }, 50);
else doGridSortCode();
}


function pageLoad(){wireSO();}

$(document).ready (function () {
wireSO();});”;               
                   
ScriptManager.RegisterClientScriptBlock(this.Page, GetType(), “FXSortGrid”, script, true);

There you have it!

Saleslogix Job Server on an Upgraded SalesLogix 8.1 Web

$
0
0

Although these steps are primarily for an application server with a web server to host IIS, some of these steps are good checks on any Job Server install.
1. Ensure that the actual executable (SLXJobServer.exe) has been upgraded to 8.1.
2. Port 1895 must be open for inbound and outbound traffic on the server hosting the Job Server executable as well as the web servers.
3. SData must be deployed, configured, and functional in order for the Job Service (and thereby the Web Client) to operate properly.
4. Map the WebDLL user to the Saleslogix Admin user in Administrator. Double-check that the WebDLL user is properly configured on the web servers and the job server itself – proper permissions and local server rights, etc.
5. Set the Saleslogix Job Service to log on as WebDLL.
6. Deploy the SLXJobService portal from within Application Architect.
7. On the server hosting the Saleslogix Job Service, locate the SLXJobServer.exe.config file. Verify that the sage.scheduling.server.tenantRoot value matches the path to which the portal was deployed in step 6.
8. On each web server, locate the web.config file for the SData portal. In the Sage.Integration.WebAdapters section of the file, ensure that there is an entry for Sage.Platform.Scheduling.SData.Adapter.
9. On each web server, locate the appSettings.config file for the SData portal. In the Sage.Scheduling.Client.serverURL section, edit the URL from ‘localhost’ to the server name of the server hosting the actual job service.
10. On each web server, locate the appSettings.config file for the SlxClient portal. Repeat step 9 for this file.
11. Perform an IISReset.
12. Start the Saleslogix Job Service

Systems that do not have the Job Service configured properly can expect to see Error 500 issues and errors in the Event logs pointing to the SLX Job Service.

Saleslogix 8 and 8.1 Windows Authentication in Saleslogix Mobile 3.0.3

$
0
0

If your company is using windows authentication in the Saleslogix Web client then you will want to use Windows Authentication for your mobile clients. After setting up the Windows Authentication according to the instructions in the Admin help set up the SData portal with basic authentication and with windows authentication disabled. On a system without mobile customizations install the SLXMobile bundle 3.0.3 and build and deploy your system. Test your Sdata portal with the adapters test and test your mobile client login in IE by using the FQDN ie. domainusername. Once the url has tested send it out to your users and remind them to use the FQDN.

Resolving 500 Errors in SalesLogix Web 8.1

$
0
0

If you see an error like this “The following SData diagnosis occurred: Description=Operation failed. Message=Could not load type ‘Sage.Entity.Interfaces.ICollection`1’ from assembly ‘Sage.Entity.Interfaces’. HTTP status: Internal Server Error (500).” in the web client when opening an entity the issue could be a corrupted group.
We recently had a system where the Admin could not open the Users area under administration and the 500 error message was returned. The issue was the Allusers group was corrupt and the admin was set to use the Allusers group in the options.

Here are the steps to resolve:
1. Select options|groups|users and change the default group to another group like network users
2. Next click on users in the administration module
3.Find and hide the existing Allusers group
4.Finally build a new Allusers group and make it visible.

The same technique can be used for Account, Contact, Opportunity, Ticket, Defects, and any other entity that has a default group.

Saleslogix Sdata Doesn’t Like Tables in Lowercase

$
0
0

I recently ran into an issue with a client’s system who was using SQL views as entities.  This is a powerful capability of Saleslogix but there is one caveat.  Make sure that the Saleslogix view is in all caps.  When you add the view as an entity, one of the attributes that gets generated is the entity’s “Table Name” property.  This will match the underlying case of your SQL view.  There is however, Sdata feed code that will assume the table name is all caps.  And while SQL is not case sensitive, the Sdata feed is case sensitive so when it goes to look for the entity with the “Table Name” of X when your entity has had it’s “Table Name” property set to x, the Sdata feed will fail.

SalesLogix 8.1 Job Service Scheduling Executions Error Resolution

$
0
0

Often times a web implementation will have an application server that is used to deploy the web portals to a web host server. When the Saleslogix web client and SData portals are deployed and then tested an Internal Server Error is encountered on the URL, similar to the following:

Http://Webserver:3333/slxclient/slxdata.ashx/$app/scheduling/-/executions?

What is occuring is the Job Service is attempting to run the scheduled jobs, like activity rollover, and it cannot run them on the web host because the deployment was on the application server and the Job Service must run there.
This setting is found under the appsettings.cfg file in the SLXCient and SData folders. Open the file and change this setting ” http://localhost:1895″ to ” http://YOURAPPLICATIONSERVER:1895″ to allow the Job Service to run on the Application Server.
After changing this setting in the files run an IISRESET and the problem is solved.

Saleslogix XBar Installation

$
0
0

When installing the new XBar application I found the instructions a little vague so I thought I would pass on a clarification. The installingSaleslogixXbar.pdf refers to the Service URL as the Saleslogix SData portal and on the install the user must fill in the Server URL. This is actually the Service URL and it is the path to the SData portal, i.e. https://mydemowebserver/SData or https://webserver:3333/SData. This helped me clear an issue with a quirky install so hope this helps.


Retrieving Items from a Picklist via Javascript using SData

$
0
0

Saleslogix is very light on how to use client side processes to do things in the Saleslogix web client.  I have decided to start to try to document snippets of things I find useful and make a repository of them.  The first one I am showing here is how to retrieve a list of picklist items using the client-side SData library.

In this code sample the items are returned in a plain list.

function getPicklistItems(picklistName) {
    var service = Sage.Data.SDataServiceRegistry.getSDataService('system');
    var request = new Sage.SData.Client.SDataResourceCollectionRequest(service)

    //var items = new Array();
    var items = [];
    request.setResourceKind('picklists');
    request.setQueryArg("where", "name eq '" + picklistName + "'");
    request.setQueryArg("include", "items");

    request.read({
        success: function (feed) {
            for (var i = 0; i < feed.$resources.length; i++) {
                var entry = feed.$resources[i];
                     
                for (var i2 = 0; i2 < entry.items.$resources.length; i2++) {
                    var item = entry.items.$resources[i2];                            
                    items.push(item.text);
                }
            }
            return items;
        },
        failure: function (feed) { }
    });            
    return items;
}

InforCRM (formerly Saleslogix) Mobile – Clearing Out Earlier Customizations

$
0
0

If you started with an earlier version of SalesLogix Mobile, let’s say version 7.5.4, and customized the mobile platform at level 1.2 you may find the mobile client no longer runs in mobile devices at recent levels and newer browsers. Another problem you have is the existing custom screens don’t allow you to upgrade to version 3.0.4. You have two options here – have someone recreate the custom screens for version 3.0.4 or remove the customized screens and start over with a basic mobile v3.0.4. Here are the steps to remove the custom screens and reset to v3.0.4. (Before removing anything in the Application Architect you will want to take screen shots of the Sage SalesLogix Mobile Portal from the Portal Manager.) Now remove the bundle containing the mobile customized screens, and remove the Sage SalesLogix Mobile deployment, and the SLXMobile deployment target. At this point you are ready to add the Sage SalesLogix Mobile portal back clicking on the Portal Manager and using the New Portal Wizard. Select UIPortalTemplate and fill in the Portal Information with the settings you saved in your screen shots. Once you have finished recreating the Sage SalesLogix Mobile portal you can recreate the Deployment target as well.
All you have left now, is to install the SalesLogix Mobile v3.0.4 bundle for SalesLogix 7.5.4, redeploy the Sdata and the Mobile deployments, RESETIIS and you are ready to test the new Mobile deployment which will be at base level.

References for the Infor CRM (Saleslogix) SData REST API

$
0
0

The Infor CRM SData REST API is a web API that allows you to access the entire Infor CRM entity model, complete with business rules & events defined in the Application Architect along with other system data such as users, picklists, etc. The SData API allows you to interact with Infor CRM data over the internet or network without needing visibility to the database server itself. In addition to SData being available for use in external applications, the Infor CRM Web and Mobile clients use SData internally as well (in fact, the SData API is the only method used for connections in the Infor CRM Mobile client). The name “SData” originally meant “Sage data” and was a specification created by Sage (from when the SalesLogix product was owned by Sage). The SData specification resembles OData, the open data protocol originally drafted by Microsoft.

SData works by sending and receiving payloads via URLs that match the SData specification. By default, SData URLs return Atom syndication formatted XML with a nested payload inside, however this default behavior can be overridden to instead return and accept JSON by including “format=json” to all URLs when working with SData (this is the way I recommend using SData 100% of the time)

When working with SData you are working with the exact same entities defined in the Application Architect. This means that the entity events also apply. For example, if you’ve created an OnAfterInsert event for the Contact entity that creates a scheduled phone call for the Contact’s account manager, this will also apply to Contact’s created via SData.

Infor CRM SData References (Includes Documentation & Libraries)

Finding references and documentation for the Infor CRM SData API can be difficult. That is what the point of this post is, to provide a list of known documentation and articles for the Infor CRM SData API.

  • SalesLogix SData Endpoint Whitepaper: An overview of all endpoints implemented in SData. Note, this document was originally created for SalesLogix v7.5.4, however, all information is relevant to current versions of Infor CRM SData
  • Official SData Specification: Outlines how SData URLs are formed, describes the payloads for doing queries, reads, creates, updates, deletes, as well as service operations (business rules) and batch operations
  • SData Developer Series: A series of articles from Customer FX on the topic of SData
  • DotNetSDataClient Documentation: Official documentation for the .NET SData Client Library for working with SData from a .NET language. Very detailed documentation that includes all aspects of working with the Infor CRM data and system. Also supports linq queries and asynchronous usage. Note: this library can be obtained via the NuGet packaging system
  • DotNetSDataClient Source Code: Source code for the official .NET SData Client Library
  • SDataCSharpClientLib: Older (but still relevant) library for working with SData via .NET (Note: providing this for completeness sake. The newer DotNetSDataClient is the preferred library to use from .NET with SData)
  • SDataJavaScriptClientLib: Official JavaScript library for working with SData
  • sage-sdata.php: Unofficial 3rd-party PHP library for working with SData

Retrieving Picklist and Picklist Items via Infor CRM (Saleslogix) SData using C#

$
0
0

Accessing system level data, such as picklists, groups, etc, is an easy task with the SData system endpoint. In this post we will look at how to retrieve picklists and picklist items using SData, C#, and the DotNetSDataClient library.

The DotNetSDataClient Library

As I mentioned in an earlier post outlining SData resources, the DotNetSDataClient Library is a newer, officially supported client library for SData and .NET. This library replaces the older SDataCSharpClientLib library and is the recommended library for SData when using .NET. It is available via NuGet as DotNetSdataClient or on github, and has excellent documentation.

Retrieving Picklists and Picklist Items via SData

The way the DotNetSDataClient Library generally works is you create POCO (Plain Old CLR Object) classes for the entities and the library retrieves the data and fills the objects. If you’re familiar with Sublogix, it works the exact same way. For retrieving Picklists, the first thing we need to do is create the objects. We only need to create properties for the SData entity properties we’re interested in keeping. We could add more properties for Picklist entity properties and they will be filled as well (such as Id etc).

[SDataPath("pickLists")]
public class PickList
{
    public string Name { get; set; }
    public IList<PickListItem> Items { get; set; }
}

public class PickListItem
{
    public string Text { get; set; }
    public string Code { get; set; }
}

Now that we have those objects we can have the library fill them with our Picklist data.

// create the SData client
var client = new SDataClient("http://localhost/sdata/slx/system/-")
{
    UserName = "admin",
    NamingScheme = NamingScheme.CamelCase
};

// use the client to get the Picklist with ID kSYST0000001 and include the items 
var pickList = client.Get<PickList>("kSYST0000001", null, new SDataPayloadOptions {Include = "items"}); 

// display the picklist name on the console
Console.WriteLine(pickList.Name); 

// display the items on the console
foreach (var item in pickList.Items) 
{
    Console.WriteLine("- ({0}) {1}", item.Code, item.Text); 
}

That’s it. View more about retrieving picklists in the documentation.

Reducing Event Viewer SData errors in Infor CRM (formerly SalesLogix)

$
0
0

If this is a constant issue in the Event viewer “ERROR Sage.SalesLogix.Web.SLXMembershipProvider – No error message available, result code: E_FAIL(0x80004005).”  It may be due to the way the Webdll user is running the website.  We changed the Webdll user to a local admin ( in this case Webdll was a domain admin) and we gave Webdll read rights to the following folder: C:\Windows\SysWOW64\config\systemprofile.  This simple change increased the speed and stability of the SLXClient significantly!

 

Viewing all 32 articles
Browse latest View live