Creating XML feeds from Sage CRM

4 minute read time.

In this article I want to think about the creation of an XML feed from within CRM.

The structure of an XML feed may look like this:

[code language="xml"]














[/code]

To test this XML do the following

1) Create an empty text file.
2) Save the file as myData.asp and add it to the CustomPages folder of your test install of Sage CRM
3) Add the XML above in the file and save it.
4) Open your Internet Explorer and navigate to the address
http://localhost/crm62/CustomPages/mydata.xml

And you should see something that looks like the image below.

If the XML is malformed then you will get an error displayed. This is a pretty good quick check that you have correctly structured your XML.

But how do we create a dynamic feed?

Here we can either use a classic ASP page or use ASP.NET to generate the output.

Using ASP.NET to create a feed.

We have 2 issues with potentially creating a feed. Firstly how the data can be obtained to build the feed and secondly how XML can be returned to the requesting agent.

To consider the first point. To extract data from Sage CRM in an ASP.NET page then we can either use Web Services or less probably an external logon. I have written about using Web Services in ASP.NET before in the article
"Combining CRM WebServices and ASP.NET"
https://community.sagecrm.com/blogs/hints_tips_and_tricks/archive/2009/01/22/combining-crm-webservices-and-asp-net.aspx

The technique for calling an external COM logon from a .NET project has been discussed in the article
"Calling a Sage CRM COM object from a .NET project"
https://community.sagecrm.com/blogs/hints_tips_and_tricks/archive/2009/01/22/calling-a-sage-crm-com-object-from-a-net-project.aspx

The second issue of returning XML in response to the request is on the face of it pretty straight forward. A regular ASPX page could use Response.Write to return the XML. Example:

[code language="csharp"]
public class myXML : System.Web.UI.Page
{
private void Page_Load(object sender, System.EventArgs e)
{
Response.ContentType = "text/xml";
Response.ContentEncoding = Encoding.UTF8;

string sXml = myFuncXMLString();
//myFuncXML represents a function that creates the XML string

Response.Write( sXml );
Response.End();
}
}
[/code]

But this page class "myXML" uses System.Web.UI.Page and that page handler is for serving aspx pages (i.e WebForms) and includes a lot of overhead not needed for just serving a simple XML file. See the previously mentioned article "Combining CRM WebServices and ASP.NET" for an example.

But there is .NET file type ".ASHX" which maps to ASP.NET on the webserver. When .ashx files are called they can return the same XML as an .aspx but does not have the same overhead as an .aspx request does.

I will post an example of this a little later on.

Using ASP to create a feed.

Just as aspx and ashx pages can return XML so can a classic ASP Page. For most people developing extensions of CRM then this will be the most familiar way of returning information from the database. And of course classic ASP pages called within the Sage CRM interface allow the use of CRM objects.

This could be the Record Object to allow integration with Security Mechanism or the eWareQuery Object to provide 'free roam' access.

If we are going to use either the CRM Record object or the Query Object then we would need to instantiate the CRM object. When the ASP page is called it will need to be passed context and session variables.

The standard include files (accpaccrm.js and accpaccrmnolang.js) for ASP pages can't be used as they return HTML. I have posted an alternative include file that can be used to instantiate the CRM object. You can download "CRMInclude.js" here.

The code of the CRMInclude.js file looks like this:

[code language="javascript"]

<%
Response.Expires=-1;
Response.ContentType = "text/xml"
var sInstallName = getInstallName(Request.ServerVariables("URL"));
var ClassName = "eWare."+sInstallName;
var Accept=new String(Request.ServerVariables("HTTP_ACCEPT"));
CRM = eWare = Server.CreateObject(ClassName);
eMsg = CRM.Init(
Request.Querystring,
Request.Form,
Request.ServerVariables("HTTPS"),
Request.ServerVariables("SERVER_NAME"),
false,
Request.ServerVariables("HTTP_USER_AGENT"),
Accept);
// start the page
function Defined(Arg)
{
return (Arg+""!="undefined");
}
function getInstallName(sPath) {
//Parse the install name out of the path
var Path = new String(sPath);
var InstallName = '';
var iEndChar=0;iStartChar=0;
Path = Path.toLowerCase();
iEndChar = Path.indexOf('/custompages');
if (iEndChar != -1) {
//find the first '/' before this
iStartChar = Path.substr(0,iEndChar).lastIndexOf('/');
iStartChar++
InstallName = Path.substring(iStartChar,iEndChar);
}
return InstallName;
}
%>
[/code]

I have highlighted in blue the line that indicates that the page should return XML and not HTML.

Response.ContentType = "text/xml"

The actual ASP code for building the XML is pretty straight forward once we have the CRM object instantiated.

So an ASP page to return XML similar to the static XML example page above could be

[code language="javascript"]

<%
var intRecordId = CRM.GetContextInfo("selecteduser","user_userid");
var mySQL = "select count(oppo_opportunityid) as oppo_count, oppo_stage from opportunity where oppo_assigneduserid = "+intRecordId+" group by oppo_stage";
var myQuery = CRM.CreateQueryObj(mySQL,"");
myQuery.SelectSQL();

var strResponse = "";

with(myQuery)
{
while (!eof)
{
strResponse += "";

NextRecord();
}
}
strResponse += "";
Response.Write(strResponse);
%>
[/code]

The above code can be saved as a file, e.g. myXML.asp and added to the User system menu. At this stage it does allow use to do much be get a strange output of XML - but it will prove the point. See below for what the XML output looks like.

The next challenge is how we can make use of this idea of dynamically returning XML. But that will have to be another article.