Tuesday, August 27, 2019

Proxy Classes for .NET Interop to X++: session open inside using statement

When you start using Proxy Classes for .NET Interop to X++ you need to open and close a session and in order to adhere to the DRY principle (do not repeat yourself) I created a new c# class to use in my project.

if you look in the examples of how to use Linq to Ax (https://docs.microsoft.com/en-us/dynamicsax-2012/developer/code-example-linq-to-ax-from-csharp) you can see in the code they have to open and close the session at the end:

using       System;  // C#
using       System.Linq;
using U23 = Microsoft.Dynamics.AX.ManagedInterop;
using U22 = Microsoft.Dynamics.AX.Framework.Linq.Data;
using       Microsoft.Dynamics.AX.Framework.Linq.Data; // .ForUpdate() needs this.

namespace LinqProviderSample
{
   class Program  // C#, LINQ to AX.
   {
      static void Main(string[] args)
      {
         // Logon to Dynamics AX.
         U23.Session axSession = new U23.Session();
         axSession.Logon(null, null, null, null);

    //more code...

    axSession.Logoff();
      }
   }
}

but what I want is to use a using statement like this so that I do not have to worry about opening and closing the session and repeat every time the same code:

public string GetTableLabel()
{
    using (AxSessionManager axSession = new AxSessionManager())
    {
        axSession.OpenConnection();

        MyTable record = new MyTable();

        var x = new SysDictTable(record.TableId);

        return x.label();
    }
}

Here the class you need to add to the project:

using System;
using System.Net;
using U23 = Microsoft.Dynamics.AX.ManagedInterop;

namespace MydDynamicsIntegration.DynamicsCommon
{
    public class AxSessionManager : IDisposable
    {
        private readonly U23.Session _axSession = new U23.Session();

        public U23.Session Connection
        {
            get { return _axSession; }
        }

        /// <summary>
        ///     Checks to see if the AX session is connected. If it's null we return false.
        ///     Then we check to see if it's logged in, then return true. Otherwise it's not logged in.
        /// </summary>
        public bool Connected
        {
            get { return _axSession != null && _axSession.isLoggedOn(); }
        }

        public void Dispose()
        {
            CloseConnection();
        }

        /// <summary>
        ///     This connects to the AX session. If it's already connected then we don't need to connect
        ///     again, so we return true. Otherwise we'll try to initiate the session.
        /// </summary>
        /// <returns>
        ///     True: Connection openned successfully, or was already open.
        ///     False: Connection failed.
        /// </returns>
        public bool OpenConnection()
        {
            if (Connected)
            {
                return true;
            }

            try
            {
                _axSession.Logon("fch", "en-GB", null, null);
                return true;
            }
            catch
            {
                return false;
            }
        }

        public bool OpenConnectionAs(NetworkCredential nc, string domain)
        {
            //System.Net.NetworkCredential nc = new System.Net.NetworkCredential("ProxyUserID", "password");
            var strUserName = nc.UserName;

            if (Connected)
            {
                return true;
            }

            try
            {
                //_axSession.LogonAs(strUserName.Trim(), "domain.com", nc, "fch", "en-GB", null, null);
                _axSession.LogonAs(strUserName.Trim(), domain, nc, "fch", "en-GB", null, null);
                return true;
            }
            catch
            {
                return false;
            }
        }

        /// <summary>
        ///     If the session is logged on we will try to close it.
        /// </summary>
        /// <returns>
        ///     True: Connection closed successfully
        ///     False: Problem closing the connection
        /// </returns>
        public bool CloseConnection()
        {
            bool retVal;
            if (Connection.isLoggedOn())
            {
                try
                {
                    _axSession.Logoff();
                    retVal = true;
                }
                catch
                {
                    retVal = false;
                }
            }
            else
            {
                retVal = true;
            }

            Connection.Dispose();
            return retVal;
        }
    }
}


as you see from the code you can either open the connection using
axSession.OpenConnection();
or use OpenConnectionAs where you need to pass the network credentials of the logged in user that match the user in Dynamics to impersonate that user in the session.

No comments:

Post a Comment