Building a Web Service that Receives and Returns Data Tables

As you will see below, it is quite easy to build a web service with the Web API Framework (ASP.NET), which:

  1. receives data tables from a web client as input parameters,
  2. makes some analytical operations on these input tables using table-valued functions,
  3. returns some resultant (output) tables to web client as output parameters.

web service that receive and return data tables

Download Description
WebService_MatrixTable MS Visual Studio 2012 project Web Service (.NET 4.0)
WebClient_MatrixTable MS Visual Studio 2012 project Web Client (.NET 4.0)

Application Examples

As you can imagine, you could implement a variety of data processing services with such a web service which is capable of receiving and returning data tables (of type MatrixTable). Here are some examples:

  1. Information services for business or scientific data for evaluations, estimations and forecasts. For example, clients could send some filtering criteria as inputs (see condition tables for filtering), and web service could send to the client the request the desired data after filtering.
  2. Complex computations based on historical tables such as financial, economic or scientific forecasts, sales commissions, performance or bonus calculations, and so on. A web service could be used to impose central calculation standards. In order to reduce the amount of data transfers some relatively static master-data could be kept in a remote database on the web server. In order to break the complexity down into modular and extendable structures Calculation Nodes and Networks could be used to implement a Calculation Engine on the web server.
  3. Statistical computations with matrices and vectors. High-level table functions like subtable transformers or function routers can split table data into matrices that are fed to matrix functions. These matrix functions can also be implemented with other math or statistics software like matlab or R (see integration examples for matlab and R).

MatrixTable and DataTable

Data tables are represented with the class named MatrixTable in finaquant’s .net libraries (Finaquant Protos and Finaquant Calcs). Compared to DataTable class of the .net framework, MatrixTable has a much simpler data structure which is adapted to analytical table operations like table arithmetics, aggregation, allocation and distribution, rather than SQL-type data manipulation operations (select, insert, update, delete). MatrixTable objects can easily be converted to DataTable, and vice versa..

Steps for building a web service for simple table multiplication

Following is a simple web service that offers three functions to a web client:

Method Name Description of Method
GetMatrixTable() Return (send) a table that is created by the web service to the web client
GetTableList() Return (send) a list of tables that is created by the web service to the web client
TableMultiplication(t1, t2) Return (send) the result of table multiplication to the web client. Web client sends two data tables and the name of key figures to the web service as input parameters.

Web Service

1) Download and open Visual Studio project WebService_MatrixTable

Visual Studio 2012, Web Service

Some words about the code in C#:
If you are new to web services with Web API I recommend you to read
Getting Started with Web API (tutorial) in order to understand controllers and models (MVC framework). Practical ASP.NET Web API (book) is another good resource for a quick start. You will see that the basic structure of a Web Api service is quite easy to understand, even for non-professional programmers.

TableController.cs Primary methods of the web service callable by the client, and some helper methods for creating data tables of type MatrixTable, and for converting MatrixTable into TableContent.

TableController.cs (expand to see the code)
// Finaquant Analytics - http://finaquant.com/
// Copyright © Finaquant Analytics GmbH
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Web.Http;
using WebService_MatrixTable.Models;   // right-click, resolve using helloWebapi.Models
using FinaquantCalcs;
using System.Data;
using System.Data.OleDb;
using System.Diagnostics;
using System.Web.Http.ModelBinding;
 
namespace WebService_MatrixTable.Controllers
{
    public class TableController : ApiController
    {
        private static MetaData md = null;
 
        // return a single table
        public HttpResponseMessage GetMatrixTable()
        {
            try
            {
                MatrixTable CostTable = CreateTable();
                var response = Request.CreateResponse<TableContent>(HttpStatusCode.OK,
                    ConvertToTableContent(CostTable));
                return response;
            }
            catch (Exception ex)
            {
                var response = Request.CreateResponse<TableContent>(HttpStatusCode.ExpectationFailed, null);
                response.ReasonPhrase = "ERROR in GetMatrixTable: " + ex.Message;
                return response;
            }
        }
 
        // return a list of tables
        public HttpResponseMessage GetTableList()
        {
            try
            {
                MatrixTable CostTable, MarginTable1, MarginTable2;
                Create_Cost_and_Margin_tables(out CostTable, out MarginTable1, out MarginTable2);
 
                var TblContList = MakeTableList(
                    new string[] { "CostTable", "MarginTable1", "MarginTable2" },
                    CostTable, MarginTable1, MarginTable2);
 
                var response = Request.CreateResponse<IList<TableContent>>(HttpStatusCode.OK, TblContList);
                return response;
            }
            catch (Exception ex)
            {
                var response = Request.CreateResponse<IList<TableContent>>(HttpStatusCode.ExpectationFailed, null);
                response.ReasonPhrase = "ERROR in GetTableList: " + ex.Message;
                return response;
            }
        }
 
        // return result of table multiplication, like Tout = Tin1 * Tin2
        public HttpResponseMessage TableMultiplication(List<TableContent> tblList,
            string inkeyfig1, string inkeyfig2, string outkeyfig)
        {
            HttpResponseMessage response;
 
            if (tblList == null || tblList.Count != 2)
            {
                response = Request.CreateResponse<IList<TableContent>>(HttpStatusCode.NotAcceptable, null);
                response.ReasonPhrase = "Improper input! Table list must contain exactly 2 tables.";
            }
 
            try
            {
                // get input tables from the list
                MatrixTable inTbl1 = ConvertToMatrixTable(tblList[0]);
                MatrixTable inTbl2 = ConvertToMatrixTable(tblList[1]);
 
                // multiply tables
                MatrixTable outTbl = MatrixTable.MultiplySelectedKeyFigures(inTbl1, inTbl2,
                    InputKeyFigTbl1: inkeyfig1, InputKeyFigTbl2: inkeyfig2, OutputKeyFig: outkeyfig);
 
                TableContent outTblCont = ConvertToTableContent(outTbl, "Result Table");
 
                // return result
                response = Request.CreateResponse<TableContent>(HttpStatusCode.OK, outTblCont);
                return response;
            }
            catch (Exception ex)
            {
                response = Request.CreateResponse<TableContent>(HttpStatusCode.BadRequest, null);
                response.ReasonPhrase = "ERROR in TableMultiplication: " + ex.Message;
                return response;
            }
        }
 
        #region "HELPER METHODS"
 
        // Convert a MatrixTable into TableContent
        internal static TableContent ConvertToTableContent(MatrixTable tbl, string TableName = "def")
        {
            var TblCont = new TableContent();
 
            try
            {
                // table name
                TblCont.tableName = TableName;
 
                // field names
                TblCont.textAttributes = (string[])tbl.TextAttributeFields.toArray.Clone();
                TblCont.numAttributes = (string[])tbl.NumAttributeFields.toArray.Clone();
                TblCont.keyFigures = (string[])tbl.KeyFigureFields.toArray.Clone();
 
                int nRows, nCols;
 
                // field values
                if (!tbl.TextAttribValues.IsEmpty)
                {
                    nRows = tbl.TextAttribValues.nRows;
                    nCols = tbl.TextAttribValues.nCols;
 
                    TblCont.textMatrixVal = new string[nRows * nCols];
 
                    for (int i = 0; i < nRows; i++)
                    {
                        for (int j = 0; j < nCols; j++)
                        {
                            TblCont.textMatrixVal[i * nCols + j] = tbl.TextAttribValues[i, j];
                        }
                    }
                }
 
                if (!tbl.NumAttribValues.IsEmpty)
                {
                    nRows = tbl.NumAttribValues.nRows;
                    nCols = tbl.NumAttribValues.nCols;
 
                    TblCont.numMatrixVal = new int[nRows * nCols];
 
                    for (int i = 0; i < nRows; i++)
                    {
                        for (int j = 0; j < nCols; j++)
                        {
                            TblCont.numMatrixVal[i * nCols + j] = tbl.NumAttribValues[i, j];
                        }
                    }
                }
 
                if (!tbl.KeyFigValues.IsEmpty)
                {
                    nRows = tbl.KeyFigValues.nRows;
                    nCols = tbl.KeyFigValues.nCols;
 
                    // TblCont.keyMatrixVal = new string[nRows * nCols];
                    TblCont.keyMatrixVal = new double[nRows * nCols];
 
                    for (int i = 0; i < nRows; i++)
                    {
                        for (int j = 0; j < nCols; j++)
                        {
                            // TblCont.keyMatrixVal[i * nCols + j] = tbl.KeyFigValues[i, j].ToString("r");
                            TblCont.keyMatrixVal[i * nCols + j] = tbl.KeyFigValues[i, j];
                        }
                    }
                }
                return TblCont;
            }
            catch (Exception ex)
            {
                throw new Exception("ConvertToTableContent: \n" + ex.Message);
            }
        }
 
        // Convert a TableContent into MatrixTable
        internal static MatrixTable ConvertToMatrixTable(TableContent tblcont)
        {
            int nRows, nCols;
            try
            {
                // create text attribute matrix
                TextMatrix textVals = TextMatrix.CreateEmptyMatrix();
 
                if (tblcont.textAttributes != null && tblcont.textAttributes.Length > 0)
                {
                    nCols = tblcont.textAttributes.Length;
                    nRows = tblcont.textMatrixVal.Length / nCols;
 
                    textVals = TextMatrix.CreateConstantMatrix(nRows, nCols);
 
                    // assign values
                    for (int i = 0; i < nRows; i++)
                    {
                        for (int j = 0; j < nCols; j++)
                        {
                            textVals[i, j] = tblcont.textMatrixVal[i * nCols + j];
                        }
                    }
                }
 
                // create numeric attribute matrix
                NumMatrix numVals = NumMatrix.CreateEmptyMatrix();
 
                if (tblcont.numAttributes != null && tblcont.numAttributes.Length > 0)
                {
                    nCols = tblcont.numAttributes.Length;
                    nRows = tblcont.numMatrixVal.Length / nCols;
 
                    numVals = NumMatrix.CreateConstantMatrix(nRows, nCols);
 
                    // assign values
                    for (int i = 0; i < nRows; i++)
                    {
                        for (int j = 0; j < nCols; j++)
                        {
                            numVals[i, j] = tblcont.numMatrixVal[i * nCols + j];
                        }
                    }
                }
 
 
                // create key figure (numbers) matrix
                KeyMatrix keyVals = KeyMatrix.CreateEmptyMatrix();
 
                if (tblcont.keyFigures != null && tblcont.keyFigures.Length > 0)
                {
                    nCols = tblcont.keyFigures.Length;
                    nRows = tblcont.keyMatrixVal.Length / nCols;
 
                    keyVals = KeyMatrix.CreateConstantMatrix(nRows, nCols);
 
                    // assign values
                    for (int i = 0; i < nRows; i++)
                    {
                        for (int j = 0; j < nCols; j++)
                        {
                            keyVals[i, j] = tblcont.keyMatrixVal[i * nCols + j];
                        }
                    }
                }
 
                // create meta data
                CreateMetaData();
 
                // get all ordered table fields
                string[] textAttribs = tblcont.textAttributes == null ? new string[] { } : tblcont.textAttributes;
                string[] numAttribs = tblcont.numAttributes == null ? new string[] { } : tblcont.numAttributes;
                string[] keyFigs = tblcont.keyFigures == null ? new string[] { } : tblcont.keyFigures;
 
                var AllFieldsList = new List<string>(textAttribs);
                AllFieldsList.AddRange(numAttribs);
                AllFieldsList.AddRange(keyFigs);
                TextVector AllFields = TextVector.CreateVectorWithElements(AllFieldsList.ToArray());
 
                // create and return MatrixTable
                return MatrixTable.CreateTableWithMatrices_B(md, AllFields, textVals, numVals, keyVals);
            }
            catch (Exception ex)
            {
                throw new Exception("ConvertToMatrixTable: \n" + ex.Message);
            }
        }
 
        // make a list of tables. Input argument TableNames can be set to null
        internal static IList<TableContent> MakeTableList(string[] TableNames, params MatrixTable[] tables)
        {
            if (tables == null || tables.Length == 0) return null;
 
            if (TableNames != null && TableNames.Length != tables.Length)
                throw new Exception("TableContent.MakeTableList: Lengths of Name and Table arrays must match unless TableNames = null!");
 
            try
            {
                IList<TableContent> TableList = new List<TableContent>();
 
                string TblName;
 
                for (int i = 0; i < tables.Length; i++)
                {
                    if (TableNames == null)
                        TblName = null;
                    else
                        TblName = TableNames[i];
 
                    TableList.Add(ConvertToTableContent(tables[i], TblName));
                }
 
                return TableList;
            }
            catch (Exception ex)
            {
                throw new Exception("MakeTableList: \n" + ex.Message);
            }
        }
 
        // define meta data (table fields) unless thy are already defined
        private static void CreateMetaData()
        {
            // define metadata
            if (md == null)
            {
                md = MetaData.CreateEmptyMetaData();
                MetaData.AddNewField(md, "category", FieldType.TextAttribute);
                MetaData.AddNewField(md, "product", FieldType.TextAttribute);
                MetaData.AddNewField(md, "brand", FieldType.TextAttribute);
                MetaData.AddNewField(md, "year", FieldType.IntegerAttribute);
                MetaData.AddNewField(md, "costs", FieldType.KeyFigure);
                MetaData.AddNewField(md, "price", FieldType.KeyFigure);
                MetaData.AddNewField(md, "margin", FieldType.KeyFigure);
            }
        }
 
        // create a single cost table
        private static MatrixTable CreateTable()
        {
            CreateMetaData();
 
            // create a MatrixTable
 
            // define meta data (all table fields)
 
            // define fields of CostTable
            var CostTableFields = TableFields.CreateEmptyTableFields(md);
            TableFields.AddNewField(CostTableFields, "category");
            TableFields.AddNewField(CostTableFields, "brand");
            TableFields.AddNewField(CostTableFields, "product");
            TableFields.AddNewField(CostTableFields, "year");
            TableFields.AddNewField(CostTableFields, "costs");
 
            // create CostTable with elements
            MatrixTable CostTable = MatrixTable.CreateTableWithElements_A(CostTableFields,
                "Notebook", "Ignor", "Ignor UX Notebook", 2010, 850.0,
                "Notebook", "Ignor", "Ignor AX Notebook", 2011, 950.0,
                "Notebook", "Euphor", "Euphor 5 Notebook", 2012, 1200.0,
                "Notebook", "Euphor", "Euphor 10 Notebook", 2013, 1450.0,
                "Desktop", "Ignor", "Ignor 4D Desktop", 2014, 650.0,
                "Desktop", "Ignor", "Ignor 6D Desktop", 2012, 800.0,
                "Desktop", "Euphor", "Euphor 2E Desktop", 2013, 1050.0,
                "Desktop", "Euphor", "Euphor 5E Desktop", 2015, 1300.0
                );
 
            // generate fractional numbers
            CostTable = CostTable * 1.03333334;
 
            return CostTable;
        }
 
        private static void Create_Cost_and_Margin_tables(out MatrixTable CostTable, out MatrixTable MarginTable1, out MatrixTable MarginTable2)
        {
            CreateMetaData();
 
            // define table structure for CostTable
            var CostTableFields = TableFields.CreateEmptyTableFields(md);
            TableFields.AddNewField(CostTableFields, "category");
            TableFields.AddNewField(CostTableFields, "brand");
            TableFields.AddNewField(CostTableFields, "product");
            TableFields.AddNewField(CostTableFields, "costs");
 
            // create CostTable with elements
            CostTable = MatrixTable.CreateTableWithElements_A(CostTableFields,
                "Notebook", "Ignor", "Ignor UX Notebook", 850.0,
                "Notebook", "Ignor", "Ignor AX Notebook", 950.0,
                "Notebook", "Euphor", "Euphor 5 Notebook", 1200.0,
                "Notebook", "Euphor", "Euphor 10 Notebook", 1450.0,
                "Desktop", "Ignor", "Ignor 4D Desktop", 650.0,
                "Desktop", "Ignor", "Ignor 6D Desktop", 800.0,
                "Desktop", "Euphor", "Euphor 2E Desktop", 1050.0,
                "Desktop", "Euphor", "Euphor 5E Desktop", 1300.0
                );
 
            // generate fractional numbers
            CostTable = CostTable * 1.03333334;
 
            // define table structure for MarginTable1
            var MarginTable1Fields = TableFields.CreateEmptyTableFields(md);
            TableFields.AddNewField(MarginTable1Fields, "category");
            TableFields.AddNewField(MarginTable1Fields, "margin");
 
            // create MarginTable1 with elements
            MarginTable1 = MatrixTable.CreateTableWithElements_A(MarginTable1Fields,
                "Notebook", 0.40,
                "Desktop", 0.30
                );
 
            // define table structure for MarginTable2
            var MarginTable2Fields = TableFields.CreateEmptyTableFields(md);
            TableFields.AddNewField(MarginTable2Fields, "category");
            TableFields.AddNewField(MarginTable2Fields, "brand");
            TableFields.AddNewField(MarginTable2Fields, "margin");
 
            // create MarginTable1 with elements
            MarginTable2 = MatrixTable.CreateTableWithElements_A(MarginTable2Fields,
                "Notebook", "Ignor", 0.40,
                "Desktop", "Ignor", 0.30,
                "Notebook", "Euphor", 0.45,
                "Desktop", "Euphor", 0.35
                );
        }
 
        #endregion "HELPER METHODS"
    }
}

 

TableContent.cs
Definition of model class TableContent.. Because Web Api does not support serialization (XML, JSON) and parameter binding for 2-dimensional arrays (included in MatrixTable), a MatrixTable object is first converted into a TableContent object with 1-dimensional arrays before transfering serialized data (as JSON or XML streams) to the web client. There is another helper method in TableController.cs which converts a TableContent object back to MatrixTable.

TableContent.cs (expand to see the code)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
 
namespace WebService_MatrixTable.Models
{
    public class TableContent
    {
        // table fields
        public string tableName { get; set; }               // optional table name
        public string[] textAttributes { get; set; }        // names of text attributes
        public string[] numAttributes { get; set; }         // names of numeric attributes
        public string[] keyFigures { get; set; }            // names of key figures (numbers)
        // table element values
        public string[] textMatrixVal { get; set; }         // values of text matrix
        public int[] numMatrixVal { get; set; }             // values of numeric matrix
        public double[] keyMatrixVal { get; set; }          // values of key figure (number) matrix
    }
}

 

WebApiConfig.cs The routing (URI-method mapping) is configured such that service methods are called by a web client directly by their names in the URI, like http://localhost:49690/api/table/GetMatrixTable

WebApiConfig.cs (expand to see the code)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web.Http;
 
namespace WebService_MatrixTable
{
    public static class WebApiConfig
    {
        public static void Register(HttpConfiguration config)
        {
            // RPC style URI
            config.Routes.MapHttpRoute(
                name: "RpcApi",
                routeTemplate: "api/{controller}/{action}/{id}",
                defaults: new { id = RouteParameter.Optional }
            );
 
            // conventional HTTP style URI
            /*
            config.Routes.MapHttpRoute(
                name: "DefaultApi",
                routeTemplate: "api/{controller}/{id}",
                defaults: new { id = RouteParameter.Optional }
            );
             * */
        }
    }
}

 

2) Install Finaquant Calcs (.net library with table-valued functions) directly from Visual Studio with its Nuget pack:

Visual Studio 2012>Tools>Library Package Manager>Package Manager Console>
PM> Install-Package FinaquantCalcs

3) Start web service (F5), and note the host url (like http://localhost:49690/) shown in your your browser. You will need this url address for configuring the URI address in your web client.

Web Client

Now that you have your web service ready, you can run the web client that will consume the callable methods of the web service. For web client basics you may visit this tutorial: Calling a Web API From a .NET Client

1) Download and open Visual Studio project WebClient_MatrixTable (Console Application Project)

Visual Studio project for Web Client

Code in C#:

Program.cs (expand to see the code)
// Finaquant Analytics - http://finaquant.com/
// Copyright © Finaquant Analytics GmbH
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using FinaquantCalcs;          // table-valued functions
using System.Net.Http;
using System.Net.Http.Headers;
using System.Threading.Tasks;
 
namespace ClientWebApiMatrixTable
{
    class Program
    {
        static void Main(string[] args)
        {
            using (var client = new HttpClient())
            {
                // update this address for your own computer
                client.BaseAddress = new Uri("http://localhost:49690/");
 
                client.DefaultRequestHeaders.Accept.Clear();
                client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
                HttpResponseMessage response;
                string msg;
 
                #region "GET A TABLE FROM WEB SERVICE"
                // Read a single table from web service
                response = client.GetAsync("api/table/GetMatrixTable", HttpCompletionOption.ResponseHeadersRead).Result;
                Console.WriteLine("{0} - {1}\n\n", (int)response.StatusCode, response.ReasonPhrase);
 
                msg = response.Content.ReadAsStringAsync().Result;
                Console.WriteLine("HTTP Content:\n{0}\n\n", msg);
 
                if (response.IsSuccessStatusCode)
                {
                    var tblcont = response.Content.ReadAsAsync<TableContent>().Result;
                    MatrixTable mt = TableMethods.ConvertToMatrixTable(tblcont);
                    Console.WriteLine("MatrixTable from web service GetMatrixTable:\n" + mt);
 
                    MatrixTable.View_MatrixTable(mt, "CostTable from web service GetMatrixTable");
                }
                #endregion "GET A TABLE FROM WEB SERVICE"
 
                Console.WriteLine("Press a key to get a list of tables from the web service..");
                Console.ReadKey();
 
                #region "GET A TABLE LIST FROM WEB SERVICE"
                // Read a list of tables from the web service
                response = client.GetAsync("api/table/GetTableList", HttpCompletionOption.ResponseHeadersRead).Result;
                Console.WriteLine("{0} - {1}\n\n", (int)response.StatusCode, response.ReasonPhrase);
 
                msg = response.Content.ReadAsStringAsync().Result;
                Console.WriteLine("HTTP Content:\n{0}\n\n", msg);
 
                if (response.IsSuccessStatusCode)
                {
                    var TblContList = response.Content.ReadAsAsync<IList<TableContent>>().Result;
                    MatrixTable mt;
 
                    foreach (var tblcont in TblContList)
                    {
                        mt = TableMethods.ConvertToMatrixTable(tblcont);
                        Console.WriteLine(tblcont.tableName + " from web service GetTableList:\n" + mt);
                        MatrixTable.View_MatrixTable(mt, tblcont.tableName + " from web service GetMatrixTable");
                    }
                }
                #endregion "GET A TABLE LIST FROM WEB SERVICE"
 
                Console.WriteLine("Press a key to get the result of table multiplication..");
                Console.ReadKey();
 
                #region "GET RESULT OF TABLE MULTIPLICATION"
                // SEND two input tables to web service, 
                // and GET the multiplication result (output table) from web service
 
                // ceate input tables
                MatrixTable CostTable, MarginTable1, MarginTable2;
                TableMethods.Create_Cost_and_Margin_tables(out CostTable, out MarginTable1, out MarginTable2);
 
                // create table list which is sent to web service as input
                IList<TableContent> TblList = TableMethods.MakeTableList(new string[] { "CostTable", "MarginTable1" },
                    CostTable, MarginTable1);
 
                // call service function named "TableMultiplication"
                response = client.PostAsJsonAsync<IList<TableContent>>
                   ("api/table/TableMultiplication?inkeyfig1=costs&inkeyfig2=margin&outkeyfig=price", TblList).Result;
                Console.WriteLine("{0} - {1}\n\n", (int)response.StatusCode, response.ReasonPhrase);
 
                msg = response.Content.ReadAsStringAsync().Result;
                Console.WriteLine("HTTP Content:\n{0}\n\n", msg);
 
                if (response.IsSuccessStatusCode)
                {
                    var TblCont = response.Content.ReadAsAsync<TableContent>().Result;
                    MatrixTable.View_MatrixTable(TableMethods.ConvertToMatrixTable(TblCont),
                        "Result of Matrix Multiplication");
                }
                #endregion "GET RESULT OF TABLE MULTIPLICATION"
            }
 
            Console.WriteLine("Press a key to quit the web client..");
            Console.ReadKey();
        }
    }
}

 

TableContent.cs (expand to see the code)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using FinaquantCalcs;
 
namespace ClientWebApiMatrixTable
{
    public class TableContent
    {
        // fields
        public string tableName { get; set; }               // optional table name
        public string[] textAttributes { get; set; }       // names of text attributes
        public string[] numAttributes { get; set; }       // names of numeric attributes
        public string[] keyFigures { get; set; }       // names of key figures (numbers)
 
        public string[] textMatrixVal { get; set; }         // values of text matrix
        public int[] numMatrixVal { get; set; }             // values of numeric matrix
        public double[] keyMatrixVal { get; set; }          // values of key figure (number) matrix
    }
 
    public class TableMethods
    {
        internal static MetaData md;
 
        // Convert a MatrixTable into TableContent
        internal static TableContent ConvertToTableContent(MatrixTable tbl, string TableName = "def")
        {
            var TblCont = new TableContent();
 
            try
            {
                // table name
                TblCont.tableName = TableName;
 
                // field names
                TblCont.textAttributes = (string[])tbl.TextAttributeFields.toArray.Clone();
                TblCont.numAttributes = (string[])tbl.NumAttributeFields.toArray.Clone();
                TblCont.keyFigures = (string[])tbl.KeyFigureFields.toArray.Clone();
 
                int nRows, nCols;
 
                // field values
                if (!tbl.TextAttribValues.IsEmpty)
                {
                    nRows = tbl.TextAttribValues.nRows;
                    nCols = tbl.TextAttribValues.nCols;
 
                    TblCont.textMatrixVal = new string[nRows * nCols];
 
                    for (int i = 0; i < nRows; i++)
                    {
                        for (int j = 0; j < nCols; j++)
                        {
                            TblCont.textMatrixVal[i * nCols + j] = tbl.TextAttribValues[i, j];
                        }
                    }
                }
 
                if (!tbl.NumAttribValues.IsEmpty)
                {
                    nRows = tbl.NumAttribValues.nRows;
                    nCols = tbl.NumAttribValues.nCols;
 
                    TblCont.numMatrixVal = new int[nRows * nCols];
 
                    for (int i = 0; i < nRows; i++)
                    {
                        for (int j = 0; j < nCols; j++)
                        {
                            TblCont.numMatrixVal[i * nCols + j] = tbl.NumAttribValues[i, j];
                        }
                    }
                }
 
                if (!tbl.KeyFigValues.IsEmpty)
                {
                    nRows = tbl.KeyFigValues.nRows;
                    nCols = tbl.KeyFigValues.nCols;
 
                    // TblCont.keyMatrixVal = new string[nRows * nCols];
                    TblCont.keyMatrixVal = new double[nRows * nCols];
 
                    for (int i = 0; i < nRows; i++)
                    {
                        for (int j = 0; j < nCols; j++)
                        {
                            // TblCont.keyMatrixVal[i * nCols + j] = tbl.KeyFigValues[i, j].ToString("r");
                            TblCont.keyMatrixVal[i * nCols + j] = tbl.KeyFigValues[i, j];
                        }
                    }
                }
                return TblCont;
            }
            catch (Exception ex)
            {
                throw new Exception("ConvertToTableContent: \n" + ex.Message);
            }
        }
 
        // Convert a TableContent into MatrixTable
        internal static MatrixTable ConvertToMatrixTable(TableContent tblcont)
        {
            int nRows, nCols;
            try
            {
                // create text attribute matrix
                TextMatrix textVals = TextMatrix.CreateEmptyMatrix();
 
                if (tblcont.textAttributes != null && tblcont.textAttributes.Length > 0)
                {
                    nCols = tblcont.textAttributes.Length;
                    nRows = tblcont.textMatrixVal.Length / nCols;
 
                    textVals = TextMatrix.CreateConstantMatrix(nRows, nCols);
 
                    // assign values
                    for (int i = 0; i < nRows; i++)
                    {
                        for (int j = 0; j < nCols; j++)
                        {
                            textVals[i, j] = tblcont.textMatrixVal[i * nCols + j];
                        }
                    }
                }
 
                // create numeric attribute matrix
                NumMatrix numVals = NumMatrix.CreateEmptyMatrix();
 
                if (tblcont.numAttributes != null && tblcont.numAttributes.Length > 0)
                {
                    nCols = tblcont.numAttributes.Length;
                    nRows = tblcont.numMatrixVal.Length / nCols;
 
                    numVals = NumMatrix.CreateConstantMatrix(nRows, nCols);
 
                    // assign values
                    for (int i = 0; i < nRows; i++)
                    {
                        for (int j = 0; j < nCols; j++)
                        {
                            numVals[i, j] = tblcont.numMatrixVal[i * nCols + j];
                        }
                    }
                }
 
 
                // create key figure (numbers) matrix
                KeyMatrix keyVals = KeyMatrix.CreateEmptyMatrix();
 
                if (tblcont.keyFigures != null && tblcont.keyFigures.Length > 0)
                {
                    nCols = tblcont.keyFigures.Length;
                    nRows = tblcont.keyMatrixVal.Length / nCols;
 
                    keyVals = KeyMatrix.CreateConstantMatrix(nRows, nCols);
 
                    // assign values
                    for (int i = 0; i < nRows; i++)
                    {
                        for (int j = 0; j < nCols; j++)
                        {
                            keyVals[i, j] = tblcont.keyMatrixVal[i * nCols + j];
                        }
                    }
                }
 
                // create meta data
                CreateMetaData();
 
                // get all ordered table fields
                string[] textAttribs = tblcont.textAttributes == null ? new string[] { } : tblcont.textAttributes;
                string[] numAttribs = tblcont.numAttributes == null ? new string[] { } : tblcont.numAttributes;
                string[] keyFigs = tblcont.keyFigures == null ? new string[] { } : tblcont.keyFigures;
 
                var AllFieldsList = new List<string>(textAttribs);
                AllFieldsList.AddRange(numAttribs);
                AllFieldsList.AddRange(keyFigs);
                TextVector AllFields = TextVector.CreateVectorWithElements(AllFieldsList.ToArray());
 
                // create and return MatrixTable
                return MatrixTable.CreateTableWithMatrices_B(md, AllFields, textVals, numVals, keyVals);
            }
            catch (Exception ex)
            {
                throw new Exception("ConvertToMatrixTable: \n" + ex.Message);
            }
        }
 
        // make a list of tables. Input argument TableNames can be set to null
        internal static IList<TableContent> MakeTableList(string[] TableNames, params MatrixTable[] tables)
        {
            if (tables == null || tables.Length == 0) return null;
 
            if (TableNames != null && TableNames.Length != tables.Length)
                throw new Exception("TableContent.MakeTableList: Lengths of Name and Table arrays must match unless TableNames = null!");
 
            try
            {
                IList<TableContent> TableList = new List<TableContent>();
 
                string TblName;
 
                for (int i = 0; i < tables.Length; i++)
                {
                    if (TableNames == null)
                        TblName = null;
                    else
                        TblName = TableNames[i];
 
                    TableList.Add(ConvertToTableContent(tables[i], TblName));
                }
 
                return TableList;
            }
            catch (Exception ex)
            {
                throw new Exception("MakeTableList: \n" + ex.Message);
            }
        }
 
        // define meta data (table fields) unless thy are already defined
        internal static void CreateMetaData()
        {
            // define metadata
            if (md == null)
            {
                md = MetaData.CreateEmptyMetaData();
                MetaData.AddNewField(md, "category", FieldType.TextAttribute);
                MetaData.AddNewField(md, "product", FieldType.TextAttribute);
                MetaData.AddNewField(md, "brand", FieldType.TextAttribute);
                MetaData.AddNewField(md, "year", FieldType.IntegerAttribute);
                MetaData.AddNewField(md, "costs", FieldType.KeyFigure);
                MetaData.AddNewField(md, "price", FieldType.KeyFigure);
                MetaData.AddNewField(md, "margin", FieldType.KeyFigure);
            }
        }
 
        // create a single cost table
        internal static MatrixTable CreateTable()
        {
            CreateMetaData();
 
            // create a MatrixTable
 
            // define meta data (all table fields)
 
            // define fields of CostTable
            var CostTableFields = TableFields.CreateEmptyTableFields(md);
            TableFields.AddNewField(CostTableFields, "category");
            TableFields.AddNewField(CostTableFields, "brand");
            TableFields.AddNewField(CostTableFields, "product");
            TableFields.AddNewField(CostTableFields, "year");
            TableFields.AddNewField(CostTableFields, "costs");
 
            // create CostTable with elements
            MatrixTable CostTable = MatrixTable.CreateTableWithElements_A(CostTableFields,
                "Notebook", "Ignor", "Ignor UX Notebook", 2010, 850.0,
                "Notebook", "Ignor", "Ignor AX Notebook", 2011, 950.0,
                "Notebook", "Euphor", "Euphor 5 Notebook", 2012, 1200.0,
                "Notebook", "Euphor", "Euphor 10 Notebook", 2013, 1450.0,
                "Desktop", "Ignor", "Ignor 4D Desktop", 2014, 650.0,
                "Desktop", "Ignor", "Ignor 6D Desktop", 2012, 800.0,
                "Desktop", "Euphor", "Euphor 2E Desktop", 2013, 1050.0,
                "Desktop", "Euphor", "Euphor 5E Desktop", 2015, 1300.0
                );
 
            return CostTable;
        }
 
        // Create cost and margin tables
        internal static void Create_Cost_and_Margin_tables(out MatrixTable CostTable, out MatrixTable MarginTable1, out MatrixTable MarginTable2)
        {
            CreateMetaData();
 
            // define table structure for CostTable
            var CostTableFields = TableFields.CreateEmptyTableFields(md);
            TableFields.AddNewField(CostTableFields, "category");
            TableFields.AddNewField(CostTableFields, "brand");
            TableFields.AddNewField(CostTableFields, "product");
            TableFields.AddNewField(CostTableFields, "costs");
 
            // create CostTable with elements
            CostTable = MatrixTable.CreateTableWithElements_A(CostTableFields,
                "Notebook", "Ignor", "Ignor UX Notebook", 850.0,
                "Notebook", "Ignor", "Ignor AX Notebook", 950.0,
                "Notebook", "Euphor", "Euphor 5 Notebook", 1200.0,
                "Notebook", "Euphor", "Euphor 10 Notebook", 1450.0,
                "Desktop", "Ignor", "Ignor 4D Desktop", 650.0,
                "Desktop", "Ignor", "Ignor 6D Desktop", 800.0,
                "Desktop", "Euphor", "Euphor 2E Desktop", 1050.0,
                "Desktop", "Euphor", "Euphor 5E Desktop", 1300.0
                );
 
            CostTable.SetFieldValue("costs", 0, 850.0 + 2.333333334);
 
            // define table structure for MarginTable1
            var MarginTable1Fields = TableFields.CreateEmptyTableFields(md);
            TableFields.AddNewField(MarginTable1Fields, "category");
            TableFields.AddNewField(MarginTable1Fields, "margin");
 
            // create MarginTable1 with elements
            MarginTable1 = MatrixTable.CreateTableWithElements_A(MarginTable1Fields,
                "Notebook", 0.40,
                "Desktop", 0.30
                );
 
            // define table structure for MarginTable2
            var MarginTable2Fields = TableFields.CreateEmptyTableFields(md);
            TableFields.AddNewField(MarginTable2Fields, "category");
            TableFields.AddNewField(MarginTable2Fields, "brand");
            TableFields.AddNewField(MarginTable2Fields, "margin");
 
            // create MarginTable1 with elements
            MarginTable2 = MatrixTable.CreateTableWithElements_A(MarginTable2Fields,
                "Notebook", "Ignor", 0.40,
                "Desktop", "Ignor", 0.30,
                "Notebook", "Euphor", 0.45,
                "Desktop", "Euphor", 0.35
                );
        }
    }
}

 

2) Install Finaquant Calcs directly from Visual Studio:

Visual Studio 2012>Tools>Library Package Manager>Package Manager Console>
PM> Install-Package FinaquantCalcs

3) Install WebApi Client Library:
Visual Studio 2012>Tools>Library Package Manager>Package Manager Console>
Install-Package Microsoft.AspNet.WebApi.Client -Version 4.0.20710 (for .NET 4.0)

4) Update URI address in Program.cs for your own computer and web service (check 3. step for web service above)

5) Run web client (F5)

Any questions or comments? Please direct them to this forum thread.

Video

Video: Steps for Building the Web Service

Copyright secured by Digiprove © 2014 Tunc Ali Kütükcüoglu
This entry was posted in Calculation engine and tagged , , , , . Bookmark the permalink.

Leave a Reply