Dynamics AX Document Bridge

I just had an enquiry about a question I posed to the Dynamics User Group a while ago and thought I’d answer it in a blog post.  My original question is here: http://dynamicsuser.net/forums/t/45181.aspx and the question I got was:

My name is xxxx and I need to implement s.th. similar in AX like you had to do. Did you find a solution uploading files from AX to Sharepoint?

As further insight into the problem the client:

  • Was unhappy with the way Dynamics AX stored documents
  • Wanted to store documents in their SharePoint intranet implementation
  • Wanted to be able to store them according to their ECM principles
  • Wanted to include data about the customer as metadata on the document
  • Wanted the documents to be returned in relevant search results

I did a fair bit of searching for the right solution to the problem and I have to say I was a bit disappointed with the result.  It seemed the only way people recommended doing this was to make changes to the core AX files.  I didn’t like this because:

  • It uses a proprietary code base (X++)
  • It makes changes to the product rather than allowing an extension point
  • It doesn’t  promote good source control principles
  • IT JUST FEELS WRONG!

To minimise the amount of change to the core code I wrote most of what was needed as a web service and just called the web service with the relevant values to populate SharePoint.  The solution looked like this:

image

The call was made from the procedure saveTempFile

 

static public Filename saveTempFile(DocuRef docuRef, boolean internetCache = true)
{
    BinData     binData;
    Filename    filename;
    FilePath    filePath;
    DynamicsAXWebServices.DocumentManagementSoapClient soapClient;
    str endSlash(str _str)
    {
        return (strscan(_str, ‘\\’,strlen(_str),-1)) ? _str : _str + ‘\\’;
    }
    ;
    binData = new BinData();
    binData.setData(docuRef.docuValue().file);

    filePath = endSlash(internetCache ? WinAPI::getFolderPath(#CSIDL_INTERNET_CACHE) : xInfo::directory(DirectoryType::Temp));
    filename = docuRef.completeFilename(filePath);

    binData.saveFile(filename);

    if (true)
    {
        try
        {
            new InteropPermission(InteropKind::ClrInterop).assert();
            soapClient = new DynamicsAXWebServices.DocumentManagementSoapClient(“DynamicsAXWebServices”);
            soapClient.uploadDocument(
http://portal, “AX”, “Shared Documents”, filename, “[AXID]”, “[client]”, “[recId]”, “[Ref]”);
            CodeAccessPermission::revertAssert();
        }
        catch (Exception::CLRError)
        {
            throw error(AifUtil::getClrErrorMessage());
        }
    }
    return  filename;
}

The web service simply took the data and uploaded the document to SharePoint:

System.Net.NetworkCredential NC = new System.Net.NetworkCredential(sUser, sPwd, sDomain);
            try
            {
                string SiteURL = _URL + _Site;
                String Library;
                SPSite sp = new SPSite(SiteURL);
                SPWeb site = sp.OpenWeb();
                Library = _Library;
                SPFolder folder = site.GetFolder(Library);
                SPFileCollection files = folder.Files;
                FileStream fStream = File.OpenRead(_File); //path of the file to upload
                byte[] contents = new byte[fStream.Length];
                fStream.Read(contents, 0, (int)fStream.Length);
                fStream.Close();
                Hashtable MetaDataTable = new Hashtable();
                MetaDataTable.Add(“AX-ID”, _AXID);
                MetaDataTable.Add(“AX-Client”, _AXClient);
                MetaDataTable.Add(“AX-RECID”, _AXRECID);
                MetaDataTable.Add(“AX-Reference”, _AXReference);
                _File = _File.Substring(_File.LastIndexOf(“\\”) + 1);

                SPFile currentFile = files.Add(_File, contents, MetaDataTable, true);

                if (currentFile.CheckOutType != SPFile.SPCheckOutType.None)
                {
                    currentFile.CheckIn(“New Version from AX”);
                }

                return SiteURL + “/” + currentFile.ToString();
            }
            catch (Exception err)
            {
                return (” ” + err.Message);
            }

It was later extended to use content types and all the good ECM stuff but in basic form that was the approach I took, I still have no real idea if I’ve missed something here but I can’t help but think, even if it works, IT STILL FEELS WRONG!

Advertisements

7 thoughts on “Dynamics AX Document Bridge”

  1. hi Andy,

    i also followed the similar method during my development. Did you face any issues when it works in production environment ?

    I am using C# code with sharepoint web services attached as web references to the C# project. in C# i am calling the SP web service for upload and delete.

  2. Hi Andrew,

    We are trying to do similar thing. Attaching the document to records in Ax (e.g. ProjectTable) and then storing the document in Sharepoint directory. We have an additional requirement of creating a folder (e.g. with same name as Project id) in sharepoint and storing the document in that path.

    Can you please let me know if you have any experience with creating folder in Sharepoint through Ax?

    Also, I am not a Sharepoint guy and haven’t worked much with .Net code. Can you please also let me know the what we need to do in order to use the following DLL in Ax client :-
    DynamicsAXWebServices.DocumentManagementSoapClient soapClient;

    It’ll be awesome if you are able to share the XPO for this Dev project.

    Thanks very much,
    Nitin

  3. Hi Nitin, regarding folders that’s one of the things this solution does, it keeps a consistent folder structure in place as documents are added. We actually hide that structure from SharePoint views but maintain it for forward comparability. Regarding sharing the solution, we can help you but we can’t give it away. If you need help get in touch via http://www.resonateit.com.au 😉

  4. Hi Andy,
    I was looking for some code to import or download the attachments from a Share point using X++.
    Can you please guide me on this, like how can i achieve this functionality.

    Best Regards
    Pranav Gupta

  5. Hello, I could change the DocuActionFile class and modify the SaveTempFile method to call custom SharePoint webservice passing it the filename and some data so that the web service could then copy the file over to SharePoint and set a few metadata fields… Can you help me about writing custom SharePoint webservice like DynamicsAXWebServices.DocumentManagementSoapClient in this example ?

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s