As you will see below, it is quite easy to build a web service with the Web API Framework (ASP.NET), which:
- receives data tables from a web client as input parameters,
- makes some analytical operations on these input tables using table-valued functions,
- returns some resultant (output) tables to web client as output parameters.
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:
- 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.
- 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.
- 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
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://software.tuncalik.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(HttpStatusCode.OK, ConvertToTableContent(CostTable)); return response; } catch (Exception ex) { var response = Request.CreateResponse(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>(HttpStatusCode.OK, TblContList); return response; } catch (Exception ex) { var response = Request.CreateResponse<IList>(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 tblList, string inkeyfig1, string inkeyfig2, string outkeyfig) { HttpResponseMessage response; if (tblList == null || tblList.Count != 2) { response = Request.CreateResponse<IList>(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(HttpStatusCode.OK, outTblCont); return response; } catch (Exception ex) { response = Request.CreateResponse(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(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 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 TableList = new List(); 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.
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
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)
Code in C#:
Program.cs (expand to see the code)// Finaquant Analytics - http://software.tuncalik.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().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>().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 TblList = TableMethods.MakeTableList(new string[] { "CostTable", "MarginTable1" }, CostTable, MarginTable1); // call service function named "TableMultiplication" response = client.PostAsJsonAsync<IList> ("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().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(); } } } |
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(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 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 TableList = new List(); 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)