AJAX Script Services on SlxWeb
Nicolas Galler | March 12, 2009From my user perspective one of the most dreadful aspect of the "QuickForms" is how slow they are. If you want to associate a piece of custom logic to a control, typically you will have to set it to auto-postback. At this point whenever the user changes it Saleslogix will have to post the entire form and (since it does not know what may have changed) pull the entire form back over the network and render it in the browser. This is noticeable even on a local network connection but can easily take 1 to 3 seconds over a WAN, which really breaks the flow of the form.
In a custom smart part there are a couple ways to get around that. One of them and often the easiest is to put smaller updatepanels around the controls that you know are going to be updated. It is not the most efficient, and it requires a basic understanding of ASP.NET Ajax (because there are a few workarounds that need to be used to disable the default handling from the top-level SalesLogix container page), but it does not usually affect the page lifecycle so the code-behind does not need to be touched. This is not the subject here though.
As an alternative to the Microsoft ASP.NET Ajax controls it is perfectly possible to use 100% custom, client-side Javascript. For example it is easy to perform basic calculations in the page and display the results. If they are saved to a bound control they can be saved to the database when the form is actually posted. This is very fast because it is done entirely on the client but it does not let us access the database or any of the business rules defined in C# on the server side.
A middle-ground option is to have the client-side Javascript call a custom web service and display the results in the form controls. This can be quite a bit faster than using an UpdatePanel, especially if a lot of controls need to be updated, and it also offers greater control over the flow of the code. Sometimes the UpdatePanel’s behavior can become rather annoying and the custom Javascript actually be easier to use. This is the method that I want to write about here.
On the client side, traditionally this approach would have required coding of the Javascript XmlHttpRequest and possibly parsing of the resulting XML (unless JSON was used). However with ASP.NET it is a lot simpler, you can have a Javascript proxy generated automatically by using code like this:
<asp:ScriptManagerProxy runat="server" ID="scriptManagerProxy"> <Services> <asp:ServiceReference Path="~/SmartParts/QuickTicket/InsertQuickTicketScriptService.asmx" /> </Services> </asp:ScriptManagerProxy>
By the way the ScriptManagerProxy means that it will use the ScriptManager on the main page, which is created by the Saleslogix framework. You can’t just add a ScriptManager on your custom smart part as it will conflict with Saleslogix’. In the Javascript code the methods from the web service will appear as method under an "InsertQuickTicketScriptService" object:
InsertQuickTicketScriptService.GetAccountInfo(accId, function(accInfo){
alert(accInfo.AccountName);
})
Note they are called in an asynchronous fashion with a callback function.
Assuming the GetAccountInfo method returns an object containing a list of contacts the following code can be used to populate a list of contacts for the selected account:
InsertQuickTicketScriptService.GetAccountInfo(accId, function(accInfo){ var cbo = $get("<%= cboContacts.ClientID %>"); cbo.options.length = 0; for (var i = 0; i < accInfo.Contacts.length; i++) { cbo.options[cbo.options.length] = new Option(accInfo.Contacts[i].ContactName, accInfo.Contacts[i].Id); } if (cbo.options.length > 0) cbo.options[0].selected = true; })
On the server side things are pretty easy thanks to the flexibility of the Saleslogix Entity service… In this case I used something similar to this:
[WebMethod(EnableSession = true)] public AccountInfo GetAccountInfo(string accId) { IAccount account = Sage.Platform.EntityFactory.GetById<IAccount>(accId); if (account == null) throw new InvalidOperationException("Account id not found " + accId); return new AccountInfo { Contacts = (from c in account.Contacts select new ContactInfo { ContactId = (String)c.Id, FullName = c.FullName }).OrderBy(c => c.FullName).ToArray() }; }
Don’t forget the EnableSession=true… Saleslogix uses sessions to store the current user’s connection data and by default won’t be able to access it from an asmx. By the way if you need to access it from an ashx you need to look for the similar option. AccountInfo and ContactInfo are just locally defined classes, with the minimum properties that need to be passed down to the client script.
If you are writing a custom smart part ASP.NET truly makes it easy to call the web service from your Javascript.





