Archive for October, 2009

Code Snippet Action Item vs. C# Snippet Action Item which to use?

Posted by Jason Huber on October 30, 2009
Developer / 1 Comment

It may seem an obvious question: Which to choose Code Snippet Action Item or C# Snippet Action Item (obsolete). The latter clearly says obsolete — so why would you use it? Why is it still included?

CodeSnippetActionItem_vs_C_SharpSnippetActionItem

The answer is not so simple. Could it be removed? Perhaps, but there are cases when it is necessary. Let’s cover the differences first.

The Code Snippet Action items are compiled into a dll. This dll is then placed into the bin directory of the deployed portal. This is nice for you because you can use an external dll, vb.net, or C# to code. It does raise a problem though. The dll does not have direct access to the page. This means if the code in the dll needs to interact with the form — let’s say update a textbox — it needs to do so through the form object that is passed into it. It cannot talk directly to the textbox. This is also its major benefit by the way, but we can talk about that in a bit.

So the C# Snippet Action Item DOES have direct access to the form right? Right. The code you write in a C# Snippet Action Item actually gets placed onto the form itself. It is IN the aspx page. You can see it there. You can edit that file in notepad (I like notepad++ myself) and then refresh your browser and see the changes. That makes for some fast development. So why is it obsolete? It is faster and easier! Hold on for a minute.

The Code Snippet Action Item makes you go through the form to access the controls on the form. This means that you are accessing the SLX controls through the form and through that interface. The C# Snippet Action Item talks with the .NET version of the control. Anything that the SalesLogix developers did not implement in the SalesLogix version of a TextBox will not be exposed through the form. I talked about this last week here: http://slxtraining.net/2009/10/new-form-control-in-saleslogix-7-5-2-sp2/ . This means if they left something off, perhaps a new feature or something more obscure — you have to do something extra to get to it. Not too bad. The C# Snippet Action Item can interact with the page directly and therefore can do a bit more. This is certain to be true.

So I am not convincing anyone that the C# Snippet Action Item should be marked as obsolete am I?

Consider when the platform you are deploying to changes. Perhaps you are deploying to the web now and later also to a smartphone portal. You may have a slightly different TextBox control in that deployment — it will likely be a bit more limited and not implement .Text but instead .Value. If you are writing code that ends up on the page itself you would have to write code to check for the deployment and capabilities of the deployed platform. That will not be fun to check for .Text or .Value each and every time.

If you use the Code Snippet Action item and work through the SalesLogix TextBox control this work will be done for you. This means you code for TextBox.Text and you do not worry about the platform changes so much. For this same reason you should avoid getting to the NativeControl when in a Code Snippet Action item. The SalesLogix developers take your code and write it up in a dll for the target platform. You write the code once and the build process works for you.

So the C# Snippet Action Item is obsolete because it should no longer be needed and can actually cause future deployment issues. It is that simple. It is that simple to NOT use it? Not yet. There are still very few cases when it is needed, but by default you should be choosing Code Snippet Action Item.

Tags: ,

SData debugging — where can I find my errors?

Posted by Jason Huber on October 28, 2009
Developer / 2 Comments

When writing code against an SData feed you are bound to make some mistakes along the way. You will likely leave off a required field, miss a dependency, and a variety of other mistakes that will cause SData to respond with an error message. The good news is that these are well defined and contain a good deal of information to help you find what went wrong.

First you can look at the response that is returned:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<diagnosis xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:sdata="http://schemas.sage.com/sdata/2008/1" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:opensearch="http://a9.com/-/spec/opensearch/1.1/" xmlns:sme="http://schemas.sage.com/sdata/sme/2007" xmlns:http="http://schemas.sage.com/sdata/http/2008/1">
  <sdata:severity>error</sdata:severity>
  <sdata:sdataCode>ApplicationDiagnosis</sdata:sdataCode>
  <sdata:applicationCode />
  <sdata:message>Exception caught during the processing of a message
 
Verb: GET
Uri: http://localhost:3333/sdata/slx/dynamic/-/Addresses?where=asdasdasd
 
Original Message: Unable to cast object of type 'NHibernate.Criterion.PropertyProjection' to type 'NHibernate.Criterion.ICriterion'.
 
Stack Trace:    at System.Linq.Enumerable.<CastIterator>d__aa`1.MoveNext()
   at Sage.Platform.SData.Dynamic.DynamicRequestBase`3.GetEntities(ISession session, SDataUri uri, Boolean isNested, Int64&amp; totalResults, Int32&amp; startIndex, Int32&amp; itemsPerPage)
   at Sage.Platform.SData.Dynamic.DynamicRequestBase`3.InternalGet(ISession session, IRequest request, Boolean isNested)
   at Sage.Platform.SData.Dynamic.DynamicRequestBase`3.DoGet(IRequest request)
   at Sage.Integration.Entity.Adapter.AddressRequest.GetAddresses(IRequest request) in c:\Documents and Settings\Administrator\Application Data\Sage\Platform\Output\sdata\Address.cs:line 68
   at Invokef7c9a0ead7974fb398c076d409441bb3.Invoke(Object , IRequest )
   at Sage.Integration.Messaging.RequestTargetRegistration.RequestTargetInvoker.Invoke(IRequest request)
   at Sage.Integration.Messaging.Request.Process(RequestTargetInvoker invoker)
   at Sage.Integration.Messaging.MessagingService.Process(IRequest request)
 
</sdata:message>

As defined by the SData spec sdata:severity can be Info, Warning, Transient, Error, or Fatal.
sdata:sdataCode is used to provide a bit more information. Some examples are BadUrlSyntax and BadQueryParameter

What I think is the most useful is the message and the response.status. If the HTTP response is not 200 or 301 (it is 400 or 500 series) then we have a problem and need to handle the response. In code this can all be handled in a try .. catch or an IF statement at worst. We are talking about debugging here so what can you do with the response?

If you are working with FireFox and Firebug (or IE8 and the dev tools) you can just look at the response:
SData_errorFF

if you are working with .NET the problem isn’t described so well. It is “hidden” from you a bit. You can still get to it, but it isn’t as easy. The good news? As defined in the log4net.config file in your SData portal all errors are also logged to the event log:
SData_errorEventViewer

What you do with the information will vary from case to case, but getting the information quickly as as completely is the important part when writing code. Remember you can always edit the Log4Net.config to log in a variety of ways. This is covered well in our developer classes and in the developer subscription.

Tags: , ,

New form control in SalesLogix 7.5.2 SP2

Posted by Jason Huber on October 23, 2009
Developer / 1 Comment

In http://slxtraining.net/2009/09/how-do-i-add-two-datagrids-to-a-form-that-are-correlated-dependent-datagrids/ we talked about how we needed to get a hold of the NativeControl to do things like .SelectedIndex . We needed to get the nativecontrol because the SalesLogix control did not expose the properties we needed. The SalesLogix developers are smart people. Being wise they leveraged what was already available to them from ASP.NET and the .Net framework. So most of the controls in the web client are wrapped .Net controls. Wrapping the control means that you need to expose all the same properties of the base control and then add on any features you want to add. They are doing a pretty outstanding job and this is why I needed the nativecontrol in that old post.

No longer. We now have that ability in SP2. As of the Release Candidate you have an enhanced version of the form being passed in a Code Snippet Action Item. Really the form isn’t enhanced, but the controls also have been augmented to better replicate what their base implements. This is a great step forward and part of the evolution of the product.

Why does this matter? What is the point?

It matters because at some point SalesLogix will be a multi-platform offering. This means you will write code once in Application Architect and it will output in more than one format. It already does this in a variety of ways such as SData, but we are talking different formats like Pocket PC or BlackBerry. So in my case a datagrid for the web is different than a datagrid for the Pocket PC. Just barely, but I suspect in the future the code I write using the enhanced controls in SP2 will work against either (when that time comes). What we are doing now is setting ourselves up for that time. The short term benefit is easier code and shorter development times. The long term benefit is shorter development time porting our code to a new platform.

If you abstract the way a form is coded against then our ultra-smart SalesLogix developers can recode what you do towards a new platform. So you interact with ImySLX form and do things like form.controlname.method and they turn that into the appropriate code for the appropriate client platform. Right now most of that is web, but we need to learn it and get used to it and then take advantage of it.

Really what I am looking at now is the new ImySLX interface and what it offers. The developer of the code is very helpful (we do not mention names intentionally by request) and details should be forthcoming. This interface is a start on the web version of Application.Basicfunctions.xxxx you can do perhaps 10 things with it now, but this is just the ground work for what is to come.

Tags: , , , ,

SData changes in SP2 — what you need to know to upgrade your code

Posted by Jason Huber on October 22, 2009
Developer / No Comments

SP2 brings some changes to the SData portal within SalesLogix. In conversation we say something like “there is a new Payload node and some enhancements such as batch loading and transaction tracking.” Where does this leave your 7.5.0 or 7.5.1 SData code? Some changes are needed and here is the short and sweet of it.

First there is a new payload node. Sorry, but I had to point it out. What this really means is that you cannot just go to the <entry> node anymore. You still need the <entry> node for the etag and some other things, but the actual data you want is actually two nodes down.

Also the URL has changed. Really a /-/ was added. Instead of:


'Dim result As String = client.DownloadString("http://localhost:3333/sdata/slx/dynamic/addresses")

you need this:


Dim result As String = client.DownloadString("http://localhost:3333/sdata/slx/dynamic/-/addresses")

That was easy.

If you look at the xml that you get back (in either case) you will see some namespaces defined at the top. Things like http, slx, sdata with a url at the end. These correspond to elements in your result. You need to have a XNamespace for each of these:


ReadOnly cf As XNamespace = XNamespace.Get("http://www.microsoft.com/schemas/rss/core/2005")
ReadOnly atom As XNamespace = XNamespace.Get("http://www.w3.org/2005/Atom")
ReadOnly slx As XNamespace = XNamespace.Get("http://schemas.sage.com/dynamic/2007")
ReadOnly sdata As XNamespace = XNamespace.Get("http://schemas.sage.com/sdata/2008/1")
ReadOnly xhttp As XNamespace = XNamespace.Get("http://schemas.sage.com/sdata/http/2008/1")

What this allow you to do is something like:


entry = (From Entry In doc.Descendants(atom + "entry") Select Entry).First()
etag = entry.Element(xhttp + "etag").Value

Now the code above is both LINQ and some xml manipulation. Basically the node called <entry> is within the atom namespace (because it is not specified) and I can get each one. I only want the first in this example because I am selecting an address by id (not shown).

Then I retrieve the etag using the xhttp namepace I declared above and the tag etag. This represents a hash of the entity and if this etag does not match when I PUT an update then I will receive an error telling me that the address I am trying to change has changed since I last got (GET) it.

I will use this etag later to place an if-match header when I try and update (PUT) later:


client.Headers.Add(HttpRequestHeader.ContentType, "application/atom+xml;type=entry")
client.Headers.Add(HttpRequestHeader.IfMatch, etag)
client.UploadString(putURI, "PUT", putPayload)

What else changed?

When you go to get the values for the actual address you need to get past the <entry> and into the <sdata:payload> and then you can get to your entity:


address = (From Entry In doc.Descendants(slx + "Address") Select Entry).First()

Again, LINQ and slx from the XNameSpace from above. In my example I am only getting one address, so I get the first one. (not shown).

The address will not contain the entry node or the payload node so you can add these back on:


Dim putPayload As String = " " & address.ToString() & ""

Now there are 101 ways to get this done and this is one way. Give it a try and editing your existing code to work with the new SP2 changes should be a piece of cake.

Tags: , , , ,

SData in SalesLogix 7.5.2 — PUT and DELETE

Posted by Jason Huber on October 16, 2009
Developer / No Comments

We have already learned how about the verbs: PUT, DELETE, POST and GET, and we have exposure to Basic and Digest Authentication, so now we need to actually PUT or DELETE something.

PUT and DELETE in this context are used as the method on your http request. Each HTTP request has a method if you did not already realize it. If you look at the IIS logs for any IIS server you will see many POST and Get requests because those verbs are normally associated with web browsing. The SData team and based on, I am guessing, the RESTful web services guys recommendation that certain verbs be used when accessing RESTful resources over http (not your typical web browsing).

PUT is to tell SData that you are Updating and DELETE is to tell SData that you are deleting. That is just fine. So how can you actually do the telling? First we know how to do a get on any resource:

System.Net.WebClient client = new System.Net.WebClient();
client.Encoding = Encoding.UTF8;
client.Headers.Add(System.Net.HttpRequestHeader.ContentType, "application/atom+xml");
client.Credentials = new System.Net.NetworkCredential(_User, _Password);

string result = client.DownloadString("http://localhost:3333/sdata/slx/dynamic/-/Tickets");

where the url is the RESTful end point for all tickets. This will return a feed of Tickets. If you wanted just a single ticket you could:
string result = client.DownloadString("http://localhost:3333/sdata/slx/dynamic/-/Tickets('123123123')");

where TicketId is 123123123.

You can also perform searches like

string result = client.DownloadString("http://localhost:3333/sdata/slx/dynamic/-/Tickets?where=ticketid eq '123123123'");

and so on. Documentation for the Query Expression is forthcoming and remind me to update this if 7.5.2 is out and you do not yet have it (I will add a link).

The Ticket comes back in the result and has a root node of feed (it is all xml). Within the feed are various items including an entry which contains the actual ticket and the tickets payload. To retrieve that we can do something like :
(snippet of code – this is well documented in the developers subscription) :

XPathNodeIterator nav = xmlNav.Select("//slx:Ticket"manager);
nav.MoveNext();
return nav.Current.InnerXml;

Now we have an xml file (XmlDocument type) and it contains the values for the Ticket we selected. We wanted to update something. Each value will be returned as a node:
SDataPost_delete_Nodes

You need to get one of these nodes. Here is the code to get back the Area:

You need to know that passed in is a valid xml document (xdoc and the node you want: “//slx:Area”)

var manager = new XmlNamespaceManager(xdoc.NameTable);
XmlNamespaceManagerAddNamespacesforslx(ref manager);

XmlNode xnode = xdoc.SelectSingleNode(sNodeName, manager);
return xnode.InnerText;

But this will not update the value, it will only return it. We need to get something to update.
(this code was note written by me, but only edited):
private void UpdateSingleValue(string nodename, string nodevalue, ref XmlDocument doc)
{
var xmlNav = doc.DocumentElement.CreateNavigator();
var manager = new XmlNamespaceManager(doc.NameTable);
XmlNamespaceManagerAddNamespacesforslx(ref manager);

var nav = xmlNav.SelectSingleNode(nodename, manager);
if (nav.Value != nodevalue)
{
var nil = nav.SelectSingleNode("@xsi:nil", manager);
if (nodevalue == null)
{
if (nil == null)
{
var attributes = nav.CreateAttributes();
attributes.WriteAttributeString("xsi:nil", "true");
attributes.Close();
}
}
else
{
if (nil != null)
{
nil.DeleteSelf();
}
}

nav.SetValue(nodevalue);
}
else
{
nav.DeleteSelf();
}
}

Once we have an xml doc containing and entry and a payload node we can tell it to go back to the server and update right? Not so fast. We still need to pass in an if-match header. This ensures that the record has not been updated since we last retrieved it. How do we get the if-match header value? It is actually in the entry node in a node called etag:

SDataPost_delete_etag

We need to get the etag (like we did for the single value) and this time we use it. We take the etag and add it to the request headers as the if-match and PUT our data. Our response should be 200 and the database should be updated:

private bool SendUpdatedEntryViaPUT(XmlDocument _xmlCurrent, string url)
{
Uri uri = new Uri(url);
System.Net.HttpWebRequest request = null;
request = (HttpWebRequest)WebRequest.Create(uri);
request.Method = "PUT";
request.ContentType = "application/atom+xml;type=entry";
request.Headers.Add("if-match", GetSingleValueFromxmldoc(_xmlCurrent, "//http:etag"));

UTF8Encoding encoding = new UTF8Encoding();
byte[] postBytes = encoding.GetBytes(_xmlCurrent.InnerXml);
request.ContentLength = postBytes.Length;

System.IO.Stream postStream = request.GetRequestStream();
postStream.Write(postBytes, 0, postBytes.Length);
postStream.Close();

request.PreAuthenticate = true;
request.Credentials = new NetworkCredential(_User, _Password);
string result = string.Empty;
using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
{
using (Stream responseStream = response.GetResponseStream())
{
using (StreamReader readStream = new StreamReader(responseStream, Encoding.UTF8))
{
result = readStream.ReadToEnd();
//MessageBox.Show(result);
}
}
}
return true;
}

What about DELETE? That is the easy part. For DELETE we should not need the etag and change the method to DELETE.
That’s it!

Tags: , , , , ,

SData in SalesLogix web 7.5.2 Introduction

Posted by Jason Huber on October 13, 2009
Developer / 2 Comments

There are a few changes to SData in 7.5.2, but if you are already writing code against SData the only thing you will really need to be concerned about is the new Payload Node. It is a new node within the entry and contains most of what you are looking for. This is the only real breaking change that has caused me to rewrite any code.
SDataPayload

There are some benefits such as Batch Mode, Basic authentication, and a few others, but let’s make sure we know the pieces first. We will need to cover $template, $schema, POST, GET, DELETE, PUT, Basic, Digest, and probably a few more things. In this post we will just define each one and tell you what it is used for (or what I use it for – there is always another use).

One of the first things I wanted to do when I started to look at SData from JavaScript was to get back some data. I wanted to either see what an entity was made of ($schema or $template) or actually get back an actually Account (GET). The trouble is previously authentication with SData was done only via Digest authentication. Digest works this way:

  1. You request a resource (you send a POST to a page or perhaps /Accounts/$template)
  2. You are rejected by the web server with a 400 error and also sent back a “nonce”
  3. The nonce is really a string you use to MD5 your username and password
  4. You MD5 your username and password and repeat the request
  5. You are authenticated for this request and you can continue

JavaScript does not like this process so well. Not only it is not something supported by a JavaScript Library like jQuery, but it is also hard to manage the state when the request comes back and then needs to be posted again. You end up with a triple request for each verb you need to send. Ugly.

Enter basic authentication. Basic authentication is like Digest in that the information is passed over http, but in Basic your username is simply base64 encoded. At this point the security risk flags go up. Basic is less secure than Digest! While that is true for the initial username and password, think about all the actual data you are passing after authenticated! None of that is encrypted in either case. So we suggest https. Simple as that.

Back to Basic authentication. With Basic authentication I can base64 my username and password and pass that as a header along with my request. Simple as that. I need to edit the headers of my request anyway, so this is a piece of cake for authentication. Check out the screenshots for Digest in C# and Basic in JavaScript:
SDataBasicAuthJavaScriptSDataDigestAuthCSharp

Now that we are authenticated we can do a few things. We can get the $template for an entity. This gives us the outline of the object that we would use to POST (insert) a new entity. We do this by issuing the following GET:
“http://localhost:3333/sdata/slx/dynamic/-/” + _entity + “/$template”

You get the point. It is just the entity/$template. What we get back is an ATOM feed with a Payload of an empty version of that entity. You edit the XML and add the values you want and then send it back with a POST and a record will be inserted.

What about POST, GET, PUT and DELETE? These are RESTful verbs. Used in the actual command (request) sent to SData they tell SData what action you want to take:

  1. POST – Insert a new record
  2. PUT – Update a record (needs an etag added for if-match
  3. Delete – Deletes a record (also needs the etag on it)
  4. Get – select or read

So what if you do not know the make-up of an entity? What if you do not know the $schema? You can go GET it:

“http://localhost:3333/sdata/slx/dynamic/-/$schema”

Why did I not do:
“http://localhost:3333/sdata/slx/dynamic/-/Accounts/$schema” ? Because according to the spec that just redirects you to: “http://localhost:3333/sdata/slx/dynamic/-/$schema” with a #Accounts on the end (pretty much).

The problem here is that $schema returns all of the entities. This means that you need to find the node you want and loop through the nodes within that entity. Here is some sample JavaScript:

x=xml.getElementsByTagName("xs:complexType")
for (i=0;i {
if(x[i].getAttribute("name") ==_singularentity + "--type")
{

y = x[i].childNodes[0].childNodes;
sappend +="<table width='500 px'>";
sappend +="<tr><td>Field Name</td><td>Type</td><td>Nullable?</td></tr>";
for (j=0;j {
sappend += "<tr><td width='300 px'>" + y[j].getAttribute("name") + "</td><td>";
sappend += y[j].getAttribute("type");
sappend += "</td>";
sappend += "<td>";
sappend += y[j].getAttribute("nillable");
sappend += "</td></tr>";

}

So far we can get the $template, $schema, and we understand the verbs. How do we then PUT an update or DELETE a record? Well we will take a look at that in the next post.

Tags: , , , , , ,

How can I install a bundle from within a bundle?

Posted by Jason Huber on October 07, 2009
Administrator, Developer / No Comments

Why would you want to install a bundle from within a bundle?

There are a couple of reasons this is being asked. First the developer may want to use a method of bundle “stacking” to keep a master bundle of their changes. This way if he creates 15 bundles over the course of a year and wants to reapply these changes he can simply install the master bundle instead of installing 15 individual bundles. Another reason may be if you are working with another developer on a project you may want to share your changes with that other developer by bundling them up and emailing the bundle to them. In either case it is a good thing to know what you are dealing with.

What about the web bundles?

This question was specifically asked regarding the LAN product so I am going to stick with that. Realize there are other options for sharing customizations on the web side with other developers which may or may not address this need.

So where do we start?

We start with a project that has been bundled and is saved somewhere on the network. This is a file with the extension “sxb”. As a developer or administrator we can take this bundle and install it into the database if we like. You can double click the bundle to open it in the Architect or you can open the Administrator and install the bundle there. In either case we will have probably installed the bundle into production. Now we want to add this bundle to our master bundle we are creating.

Create a project or open an existing project

Create a copy database that you can work with independently of projection, QA and development. Why? Most of the bundles you get at this point have already been installed in all of those environments. You will be prompted to overwrite those changes if they exist. Also, if you make a mistake against one of those environments you are probably going to have some work ahead of you. Play it safe and make a copy db, connection and datalink.

If this is the first of the 15 bundles you are adding to the master bundle then you can just create a new project in Architect – call it Master Project or something like that. At the top of the Project Manager you will see an icon that allows you to “Merge Bundle Into Project” our project is empty so we can just go ahead with it. how-can-i-install-a-bundle-from-within-a-bundle_mergeintoprojectYou are asked to browse for the bundle you want to merge in. If you are not working with a copy of your database and sometimes if you are, you will receive a warning telling you that the plug-ins already exists. Consider that dialogue carefully. I will assume you are working with a copy of your database.how-can-i-install-a-bundle-from-within-a-bundle_warning

Click “Yes to all” and you can then close the bundle manager. Your new plug-ins will be added to your project.

What could go wrong?

Well you need to make sure that you get the bundles installed in the right order. When you are adding the 2-15th bundles you will be asked what order you want the bundle to be placed. Select the plug-in that you want the bundle to be placed after and you will be set.
how-can-i-install-a-bundle-from-within-a-bundle_order
You may also have the same plug-in being changed many times over those 15 bundles. In this case you need to ensure that you update the plug-ins carefully. Selecting “yes to all” when prompted is usually the best way to go if you are sure that your bundles are being added to the master in the correct order.

Name your bundles correctly

Give your Project, and thus your bundle, a good name. Something like the date and a good description, perhaps including the customer name. I would suggest 20091008_customername_descriptionofchange.sxb – but that is just me. Anything descriptive is the point.

Tags: , , , ,

Use FireBug to help in your client-side development in SalesLogix Web

Posted by Jason Huber on October 05, 2009
Developer / No Comments

What is Firebug?

Firebug is a free add-on for Mozilla FireFox. It can be installed from https://addons.mozilla.org/en-US/firefox/addon/1843. Once it is installed it is launched by clicking the little “bug” in the lower right corner of FireFox. The bug will turn Orange to indicate it is enabled. Here you can see it turned “off”: UseFireBug_firebugoff

Why Firebug?

What can FireBug do for you that will help with your development? The most obvious feature is that is allows you to inspect the HTML code. While in this mode you hover over items on the webpage you are viewing and the code the generated these User Interface items will be shown. This is helpful when trying to diagnose misplaced elements on a page or when looking for the Cascading Style Sheet class that a particular UI element implements.
UseFireBug_firebugtabs
You can edit the Cascading Style sheets inline. By clicking the CSS tab at the top of the firebug window you can actually edit the CSS and make changes. These changes will be immediately reflected in the browser window.

UseFireBug_NETThe NET option allows you to see how long each request took to perform and the details of that request. This allows you to see all POST, GET, and other NET request sent down the http pipeline. You can tell what is being passed and how long it is taking. What is really important to me right now is being able to see the request and response headers. This tells me the authentication method I am using for my SData work in JavaScript.

The script tab helps if you need to debug your JS code. You can step through your code by placing a breakpoint to the left of the line of code that you want to break on. You can step through the code using the menu options in the upper right of the firebug toolbar.UseFireBug_script

How have I found it to be most useful?

When working with ATOM result sets like those received from a GET to an SData feed Firebug allows you to look right into the resulting XML. This makes traversing the DOM a bit easier since you can see where you are at in the structure. In previous days we would alert or print the elements while looping which was time consuming to say the least.
Internet Explorer 8 ships with a set of developer tools as well which rival what we use firebug for nearly every day. I guess since the days of the javascript: console in Mozilla it was hard to not use FireFox when it comes to client side code. Perhaps I will take a look at the IE tools in a future post.

Tags: , , , , ,

What’s New in the SalesLogix v7.5.2 Web Client

Posted by Kristin Lisson on October 02, 2009
Administrator, End User / 1 Comment

This article summarizes the enhancements available in the Web Client after installing Service Pack 2 for Sage SalesLogix v7.5.

Overall Enhancements

  1. Use a new Sales Order main view to track the products purchased by your accounts. Sales orders include information such as the Account Manager, the date the sales order was made, the date the sales order was promised to the customer, and its status.
  2. Navigate the Sales Library more easily using a folder hierarchy.
  3. View data entered in non-native languages (Unicode support).
  4. salesorder    library    unicode

Calendar Enhancements

  1. Click on an activity to see more information in a pop-up window.
  2. See which activities and calendar items contain attachments.
  3. Link from calendar items directly to the related account, contact, ticket, opportunity, and so on.
  4. calendar

Activities Enhancements

  1. Dismiss, snooze, delete, reschedule, complete multiple activities in a single step.
  2. Confirm or decline activity confirmations.
  3. reminder

Tags: , ,

Redirecting Web Client Log Off/Timeout

Posted by Kristin Lisson on October 01, 2009
Administrator, Developer / No Comments

In SalesLogix v7.5 Service Pack 2, the Sage SalesLogix Web Client redirects to the logoff.aspx page when it times out or a user logs off. The following image shows what the default Log Off page looks like in a browser.
logoff

If your company wants to send users to a different page instead of this default Log Off page—maybe your Web site’s Home page, for example, or to accommodate single sign-ons—simply edit the LogoffRedirectUrl key in the web.config file.

Before You Begin

The web.config file (associated with ASP.NET) acts as a container for settings that describe how the ASP.NET-specific portions of the application should be handled.

Where is the web.config file? There are multiple copies of the web.config file:

  • Model copies – A web.config file exists for each portal definition in an exported model.
  • Web site copies – When the portal is deployed to a target, the web.config file is copied to the root of the Web site (also known as the deployment folder). For example, the web.config file for the Sage SalesLogix portal might be located under C:\Inetpub\wwwroot\SLXClient.

Which web.config file should I modify? If you modify the web.config file in your model, the changes are propagated to the Web server each time you deploy, for every deployment target. You must deploy before you can test the changes.

You can also edit the Web server copy of the web.config file directly inside Inetpub, but any changes you make to this file will be overwritten by the web.config in your model after you deploy.

Quick Steps

This example shows you how to modify the redirect URL for the SlxClient portal. Instead of sending users to an intermediary logoff.aspx page, we will just send users right back to the logon.aspx page. We will also edit the file directly from within the deployment folder.

  1. Open the web.config file for the SlxClient portal in Inetpub\wwroot.
  2. In the appsettings section, locate the value for the LogoffRedirectUrl key.
  3. Enter a new path in the value.

    The value can be a relative path such as ~/logon.aspx or any full URL such as http://www.mycompany.com.

    Example: < add key="LogoffRedirectUrl" value="~/logon.aspx"/ >

  4. Save and close the web.config file.
  5. Open a new browser session, and log on to the Web Client.
  6. In the upper, right corner, click Log Off.
    You should now see the SalesLogix Web Client Log On screen instead of the Log Off screen.
    logon
  7. Copy the web.config file from your deployment folder into your portal Model.

Source: The “Redirecting Web Client Logoff/Timeout” topic in the Application Architect Help.

Tags: , ,