Thursday, January 14, 2016

AX2009 Call Webservice from X++

As we know AX2009 does not allow for consuming web-services as AX2012 does, so to call the web-service you either need to build a separate windows service that calls the web service and update the AX tables via the AX Connector or use the .NET Classes to call the web service

I have recently discovered a method of consuming a web-service directly out of AX2009 X++ code.

for this instance I used the google maps API where I provide two coordinate points and the google maps API will give me the distance back.


static void googleAPITest(Args _args)
{
    System.Net.WebRequest request;
    System.Net.WebResponse response;
    str origin, destination, url, content, status, distance;
    System.IO.StreamReader reader;
   
    System.Xml.XmlDocument xmlDoc = new System.Xml.XmlDocument();
    System.Xml.XmlNodeList xnListStatus, xnList;
    System.Xml.XmlNode xnNode;
    ;

    //-33.914561, 18.421480
    origin = strFmt("%1, %2", '-33.914561', '18.421480');
    //-33.971872, 18.580566
    destination = strFmt("%1, %2", '-33.971872', '18.580566');

    url = "http://maps.googleapis.com/maps/api/directions/xml?origin=" + origin + "&destination=" + destination + "&sensor=false";
    content = "";

    try
    {
        request = System.Net.WebRequest::Create(url);
        response = request.GetResponse();

        reader = new System.IO.StreamReader(response.GetResponseStream());
        content = reader.ReadToEnd();

        xmlDoc.LoadXml(content);
        xnListStatus = xmlDoc.SelectNodes("/DirectionsResponse/status");
        xnNode = xnListStatus.Item(0);
        status = xnNode.get_InnerText();

        if (status == "OK")
        {
            xnList = xmlDoc.SelectNodes("/DirectionsResponse/route/leg/distance/text");
            xnNode = xnList.Item(0);
            distance = xnNode.get_InnerText();
            status = "OK";
        }
        else
        {
            distance = '-1';
            status = "ZERO_RESULTS";
        }
    }
    catch
    {
        distance = '-1';
        status = "NO_RESPONSE";
    }
   
    info(StrFmt('The distance between the 2 points is: %1 and the status is: %2', distance, status));

}

AX2012/AX2009 X++ Base64 Convertion

The easiest method for me to get this working was to use the existing .net objects in X++

Conversion works as the following:

static void simpleBase64(Args _args)
{
    str val, valToConv;
    System.Byte[] bytes;
    System.Text.Encoding encoding = System.Text.Encoding::get_UTF8();
    ;
   
    valToConv = 'Hello World!';
    val = '';
   
    info(StrFmt('Vale to convert is : %1', valToConv));
   
    bytes = encoding.GetBytes(valToConv);
    val = System.Convert::ToBase64String(bytes);
   
    info(StrFmt('Value Converted to Base64: %1', val));
   
    bytes = System.Convert::FromBase64String(val);
    val = encoding.GetString(bytes);

    info(StrFmt('Value Converted back to String: %1', val));

}



Tuesday, November 9, 2010

Image to Base64

I recently wanted to add small icon images to a project and i wonderd if there wasnt a beter solotion to storing small icon images inside a data base for quick retrieval.

So i found a solution to convert a image to base64 on www.dailycoding.com I took the code from www.dailycoding.com and add a few of my code just make more sense of whats going on.

There are two methods ImageToBase64 and Base64ToImage i will only be using ImageToBase64 and I think the description comes with the name.

In the Page_Load event I made use of two properties (Base64Image and Base64Start) to build the image for display there has to be "data:image/gif;base64," in front of the base64 string to display it as an image and this is stored in the Base64Start. lastly I displayed the image and text

The only downside to base64 is that it makes the files increasingly larger than binary format but it is easier/safer to Send file data. For example if you want to send file to another server using a web service or ftp base64 will be beater because it is less likely that data will be lost




public partial class WebForm1 : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {
            //create image from full path
            System.Drawing.Image image = System.Drawing.Image.FromFile(Server.MapPath("list.gif"));

            //Create base64 and store in property
            Base64Image = ImageToBase64(image, System.Drawing.Imaging.ImageFormat.Gif);

            //Display image and string
            imgMyImage1.ImageUrl = String.Format("{0}{1}", Base64Start, Base64Image);
            lblBase64Text.Text = Base64Image;
        }

        public string ImageToBase64(System.Drawing.Image image,
            System.Drawing.Imaging.ImageFormat format)
        {
            using (MemoryStream ms = new MemoryStream())
            {
                // Convert Image to byte[]
                image.Save(ms, format);
                byte[] imageBytes = ms.ToArray();

                // Convert byte[] to Base64 String
                string base64String = Convert.ToBase64String(imageBytes);
                return base64String;
            }
        }

        public System.Drawing.Image Base64ToImage(string base64String)
        {
            // Convert Base64 String to byte[]
            byte[] imageBytes = Convert.FromBase64String(base64String);
            MemoryStream ms = new MemoryStream(imageBytes, 0,
              imageBytes.Length);

            // Convert byte[] to Image
            ms.Write(imageBytes, 0, imageBytes.Length);
            System.Drawing.Image image = System.Drawing.Image.FromStream(ms, true);
            return image;
        }

        private String base64Image;
        public String Base64Image
        {
            get 
            {
                return base64Image;
            }
            set 
            {
                base64Image = value;
            }
        }

        public String Base64Start
        {
            get 
            { 
                return "data:image/gif;base64,";
            }
        }
    }


    

The output will be displayed as following

Base64 displayed as Image :



Base64 displayed as full text :

R0lGODlhDgAOAPAAAFRWVPz+/CwAAAAADgAOAAACFoyPqcttAF2AQFJ5rtONJ7+AioiVRwEAOw==


Source Code

Monday, November 8, 2010

Hierarchical Data Population

Populating Herarchial data from a table can sometimes get really tricky its not the hardest thing to do but it is something to remember.

The perfict example will be to populate data from a table that has a PK ID a ParentId that shows the which Parent Id the row belongs to and the Name.

In this example I wont be using a SQL Table but a Object List.





Cosider the following




private List<String> menu = new List<String>();
        private List<MenuItem> menuList = new List<MenuItem>();
        private Boolean flag = true;

        protected void Page_Load(object sender, EventArgs e)
        {
            LoadMenu();

            BuildMenu(0);

            foreach (String item in menu)
            {
                litMenu.Text += item;
            }
        }

        private void LoadMenu()
        {
            //List of MenuItem        ID |ParentId  |Name
            //------------------------------------------------------
            menuList.Add(new MenuItem(1,  0,        "Home"));
            menuList.Add(new MenuItem(2,  0,        "Contact Us"));
            menuList.Add(new MenuItem(3,  0,        "About Us"));
            menuList.Add(new MenuItem(4,  1,        "Profile"));
            menuList.Add(new MenuItem(5,  1,        "Goal"));
            menuList.Add(new MenuItem(6,  2,        "Send Mail"));
            menuList.Add(new MenuItem(7,  3,        "What we do"));
            menuList.Add(new MenuItem(8,  7,        "Skinning"));
            menuList.Add(new MenuItem(9,  7,        "Milking"));
            menuList.Add(new MenuItem(10, 3,        "What we wont do"));
        }

        private void BuildMenu(int ParentId)
        {
            List<MenuItem> newList = (from p in menuList
                                      where p.ParentId == ParentId
                                      select p).ToList<MenuItem>();

            if (newList.Count > 0)
            {
                for (int i = 0; i < newList.Count; i++)
                {
                    if (i == 0)
                    {
                            menu.Add("<ul>");
                    }

                    menu.Add("<li>");
                    menu.Add(newList[i].MenuName);
                    BuildMenu(newList[i].ID);
                    menu.Add("</li>");

                    if (i == newList.Count - 1)
                    {
                        menu.Add("</ul>");
                    }

                }
            }
        }
    
The ouput from the object list will be displayed as following
  • Home
    • Profile
    • Goal
  • Contact Us
    • Send Mail
  • About Us
    • What we do
      • Skinning
      • Milking
    • What we wont do
Source Code

Sunday, October 31, 2010

N-Tier Architecture (Part 1)

I have seen many data models in applications, saying that they all are data
models. But the best one that I have seen is the N-Tier data model it is fast, easy
to maintain and extremely feasible it also works very well with the current .Net
framework. The layer names are not 100% correct if you compare it to other models but the point stays the same, these name are mostly made up and works fine for me

Here is a graph that explains the data model. The Object Data Source connects and configures the data model with the page. for more information on Object Data Source




Connection Object

The Connection Object in this example the Data Layer Helper class is a central connection class that handles all connections to the data base. I only added two methods and the two will work for most cases. One for data retrieval and one for execution (insert, updates) a third can be added for SQL Scalar to retrieve a single value. also notice that i made use of Stored Procedures for faster data retrieval, it will also be a wise decision to add Transactions since all will be Stored Procedures. normally you will only create one Connection Object class and all other classes will work with this class to connect to the db.


using System;
        using System.Data;
        using System.Data.SqlClient;
        using System.Data.Sql;
        using System.Configuration;
        using System.Collections;

        /// 
        /// central point to execute comands to reduce code
        /// 
        public class DataLayerHelper
        {
            /// 
            /// used for sql select comands, SqlDataReader used for faster retrieval
            /// 
            /// Stored Procedure name/// List of Sql Parameters/// 
            public static SqlDataReader GetList(string cmdText, SqlParameter[] sqlParams)
            {
                using (SqlConnection conn = new SqlConnection(
                ConfigurationManager.ConnectionStrings["ConnectionString"].
                  ConnectionString))
                {
                    conn.Open();
                    SqlCommand cmd = new SqlCommand(cmdText, conn);
                    cmd.CommandType = CommandType.StoredProcedure;
                    cmd.Parameters.AddRange(sqlParams);
                    SqlDataReader rdr = cmd.ExecuteReader(CommandBehavior.CloseConnection);
                    return rdr;
                }
            }

            /// 
            /// used for sql execute comands
            /// 
            /// /// /// 
            public static int ExecuteNonQuery(string cmdText, ref SqlParameter[] sqlParams)
            {
                using (SqlConnection conn = new SqlConnection(
                ConfigurationManager.ConnectionStrings["ConnectionString"].ConnectionString))
                {
                    conn.Open();
                    SqlCommand cmd = new SqlCommand(cmdText, conn);
                    cmd.CommandType = CommandType.StoredProcedure;
                    cmd.Parameters.AddRange(sqlParams);
                    return cmd.ExecuteNonQuery();
                }
            }
        }



    

Data Object

The Data Object Class is primarily used to get and set queries and parameter to send to Connection Object class for execution. normally you will have one Data Object class for a table or a set of tables. instead of using dataTable to load data in I make use of a object List this has many advantages and works great with Linq


using System;
    using System.Data;
    using System.Data.SqlClient;
    using System.Data.Sql;
    using System.Configuration;
    using System.Collections;
    using System.Collections.Generic;

    public class BookDB
    {
        public static List<Book> GetBookList(int BookId, String BookName, Boolean BookActive)
        {
            List<Book> itempList = null;
            Book item = null;

            SqlParameter[] sqlParams = new SqlParameter[]
                {
                new SqlParameter("@BookId", SqlDbType.Int),
                new SqlParameter("@BookName", SqlDbType.VarChar),
                new SqlParameter("@BookActive", SqlDbType.Bit)
                };

            sqlParams[0].Value = BookId;
            sqlParams[1].Value = BookName;
            sqlParams[2].Value = BookActive;

            SqlDataReader rdr = DataLayerHelper.GetList("BookGet", sqlParams);

            if (rdr.HasRows)
            {
                itempList = new List<Book>();
                

                while(rdr.Read())
                {
                    item = new Book();
                    item.pBookId = Convert.ToInt32(rdr["BookId"]);
                    item.pBookName = Convert.ToString(rdr["BookName"]);
                    item.pBookPrice = Convert.ToDecimal(rdr["BookPrice"]);
                    item.pBookDesc = Convert.ToString(rdr["BookDesc"]);
                    item.pBookActive = Convert.ToBoolean(rdr["BookActive"]);
                    
                    itempList.Add(item);
                }
            }

            return itempList;
        }

        public static int Insert(Book item)
        {
            SqlParameter[] sqlParams = new SqlParameter[]
            {
                new SqlParameter("@BookName", SqlDbType.VarChar),
                new SqlParameter("@BookPrice", SqlDbType.Money),
                new SqlParameter("@BookDesc", SqlDbType.VarChar),
                new SqlParameter("@BookImage", SqlDbType.Image)
            };

            sqlParams[0].Value = item.pBookName;
            sqlParams[1].Value = item.pBookPrice;
            sqlParams[2].Value = item.pBookDesc;
            sqlParams[3].Value = item.pBookImage;

            return DataLayerHelper.ExecuteNonQuery("BookInsert", ref sqlParams);
        }
    }



    

Property Class
used by Data Object to populate the data lists


public class Book
    {
        private int BookId;
        private String BookName;
        private Decimal BookPrice;
        private String BookDesc;
        private Boolean BookActive;
        private System.Drawing.Image BookImage;

        public int pBookId
        {
            get { return BookId; }
            set { BookId = value; }
        }

        public String pBookName
        {
            get { return BookName; }
            set { BookName = value; }
        }

        public Decimal pBookPrice
        {
            get { return BookPrice; }
            set { BookPrice = value; }
        }

        public String pBookDesc
        {
            get { return BookDesc; }
            set { BookDesc = value; }
        }

        public Boolean pBookActive
        {
            get { return BookActive; }
            set { BookActive = value; }
        }

        public System.Drawing.Image pBookImage
        {
            get { return BookImage; }
            set { BookImage = value; }
        }
    }


    

Business Object

The last object connects the other objects with the front end and all the business logic is used in here. also notice that there is a [DataObject(true)] Declaration above the class declaration this is just to let the framework know that this is an Data Object class and will make it easy to work with the Object Data Source


using System;
    using System.ComponentModel;
    using System.Collections.Generic;
    using System.Collections;

    [DataObject(true)]
    public class BookManager
    {

        [DataObjectMethod(DataObjectMethodType.Select, true)]
        public List<Book< GetBookList()
        {
            int BookId = 0;
            String BookName = "";
            Boolean BookActive = true;
            return BookDB.GetBookList(BookId, BookName, BookActive);
        }

        [DataObjectMethod(DataObjectMethodType.Select, true)]
        public List<Book< GetBookList(int BookId, string BookName, Boolean BookActive)
        {
            BookName = (BookName == null) ? "" : BookName;
            return BookDB.GetBookList(BookId, BookName, BookActive);
        }

        [DataObjectMethod(DataObjectMethodType.Insert, true)]
        public int Insert(Book item)
        {
            return BookDB.Insert(item);
        }

        [DataObjectMethod(DataObjectMethodType.Update, true)]
        public int Update(Book item)
        {
            return BookDB.Update(item);
        }
    }
    

On the next post i will explain how this works with the front end.

Source Code

Thursday, October 28, 2010

Opening

This is my first post and got allot of plans for the blog
 
As a start I want to focus on C# and T-SQL development 

The main reason for the blog is to use it as information storage. 

The development world is a challenging world and is hard to keep up and remember all, so I hope the blog will help and also bring new ideas and knowledge 

Unfortunately time is against me but will start adding some useful blogs soon

Thanks