Click here to Skip to main content
15,867,568 members
Articles / Web Development / HTML
Article

Rapid Development of Engineeging Web Site

Rate me:
Please Sign up or sign in to vote.
4.95/5 (10 votes)
1 Nov 2012CPOL12 min read 20.8K   326   19   2
From desktop to Web
Image 1

Useful links

1. Introduction

At 2002 I have predicted that my software projects should have Web versions. Recently (October 2012) I have begun implement this idea. However during ten years I developed software such that it can be easily adopted for Web. So I once again
reinvented
The time machine. My idea of engineering web applications rapid development is similar to LabVIEW idea. LabVIEW supports graphical programming for both business logics and user interface.
 


LabVIEW Graphical Programming

My approach is the same. Following picture shows this fact.

Bisiness + UI

Desktop windows application enables us develop business logic. Then XAML designer yields interoperability of business logic with Silverlight user interface. So this soft contains desktop windows application and Web one. Both of them are developed for evaluation purposes only. Therefore Visual Studio Express 2012 for Windows Desktop
and Visual Studio Express 2012 for Web are used for development of these applications.   Evaluation Web client is a frame of the original article. Original article contains desktop application source code and other useful resources.

2. Background

Here we will consider general elements of business logic and corresponding Silverlight UI elements

2.1 Exception handling

A lot of software contains code which looks like

void z_error (char *m)
{ 
         fprintf(stderr, "%s\n", m); 
         exit(1); 
} 

or

 try
{
    // Do something ...
}
catch (Exception exception)
{
    MessageBox.Show(exception.Message);
}

Above code is not flexible and could not be easy used for Web applications. So I prefer construction which has a pure abstract exception handling and extension method.

     /// <summary>
    /// The error handler
    /// </summary>
    public interface IErrorHandler
    {
        /// <summary>
        /// Shows error
        /// </summary>
        /// <param name="exception">Exception</param>
        /// <param name="obj">Attached object</param>
        void ShowError(Exception exception, object obj);
 
        /// <summary>
        /// Shows message
        /// </summary>
        /// <param name="message">The message to show</param>
        /// <param name="obj">Attached object</param>
        void ShowMessage(string message, object obj);
    }     

 

 /// <summary>
/// Shows exception (extension method)
/// </summary>
/// <param name="exception">Exception</param>
/// <param name="obj">Attached object</param>
static public void ShowError(this Exception exception, object obj = null)
{
    if (errorHandler != null) // Static exception handler
    {
        errorHandler.ShowError(exception, obj);
    }
}

Now exception handling looks like

 try
{
    // Do something ...
}
catch (Exception exception)
{
      exception.ShowError();
}

Desktop applications can have following implementation of IErrorHandler interface

 void IErrorHandler.ShowError(Exception exception, object obj)
{
    MessageBox.Show(this, exception.Message);
}

However I prefer error handling with following UI

Error windows message

Web version of above error handling looks like:

<>
N Level Message Stack trace
1 10 NaN at EngineeringInitializer.BasicEngineeringInitializer.<initializeapplication>b__0(Object o) in c:\AUsers\1MySoft\CSharp\src\src\EngineeringInitializer\BasicEngineeringInitializer.cs:line 72 at Calculation.Calculate.Update() in c:\DWASFiles\sites\orbitalforecast\Temp\agffdids.0.cs:line 90 at DataPerformer.DifferentialEquationSolver.CalculateDerivations()
2 10 NaN at Diagram.UI.StaticExtensionDiagramUI.Throw(Object o, Exception exception) at DataPerformer.DataConsumer.UpdateChildrenData() at DataPerformer.VectorFormulaConsumer.UpdateMeasurements()
3 10 NaN at Diagram.UI.StaticExtensionDiagramUI.Throw(Object o, Exception exception) at DataPerformer.DataConsumer.UpdateChildrenData() at DataPerformer.VectorFormulaConsumer.UpdateMeasurements()
4 10 NaN at Diagram.UI.StaticExtensionDiagramUI.Throw(Object o, Exception exception) at DataPerformer.DataConsumer.UpdateChildrenData() at DataPerformer.VectorFormulaConsumer.UpdateMeasurements()

This error handling has server and client tiers. Following code is implenentation of server tier.

Following code contains server side implementation
         /// <summary>
        /// List of exceptions
        /// </summary>
        private List<object[]> exceptions = new List<object[]>();
 
          
         #region IErrorHandler Menbers
 
        /// <summary>
        /// Shows error
        /// </summary>
        /// <param name="exception">Exception</param>
        /// <param name="obj">Attached object</param>
        public virtual void ShowError(Exception exception, object obj)
        {
            exceptions.Add(new object[] { exception, obj + "" });
            onException(exception, obj);
        }
 
        #endregion
 
        /// <summary>
        /// Creates error report
        /// </summary>
        /// <param name="doc">report doocument</param>
        public void CreateErrorReport(XmlDocument doc)
        {
            if (exceptions.Count != 0)
            {
                XmlElement el = doc.CreateElement("Exceptions");
                doc.DocumentElement.AppendChild(el);
                foreach (object[] o in exceptions)
                {
                    XmlElement e = doc.CreateElement("Exception");
                    el.AppendChild(e);
                    XmlElement eo = doc.CreateElement("Object");
                    eo.InnerText = o[1] + "";
                    e.AppendChild(eo);
                    XmlElement eex = doc.CreateElement("StackTrace");
                    e.AppendChild(eex);
                    eex.InnerText = (o[0] as Exception).StackTrace;
                    XmlElement em = doc.CreateElement("ExceptionMessage");
                    e.AppendChild(em);
                    em.InnerText = (o[0] as Exception).Message;
                    XmlElement et = doc.CreateElement("ExceptionType");
                    e.AppendChild(et);
                    et.InnerText = (o[0] as Exception).GetType() + "";
                }
                exceptions.Clear(); // Clears list of exceptions
            }
        }

Serer side collects exceptions on list, then information about exceptions is appended to XML document. Then document is sent to client.
Client side also contains own error handling interface:

 /// <summary>
/// Shows errors
/// </summary>
public interface IErrorHandler
{
    /// <summary>
    /// Shows errors
    /// </summary>
    /// <param name="x">Errors</param>
    void ShowErrorReport(XElement x);
}
 

Every client object which implements this interface shows report about errors. Following code contains an implementation of this interface.

     /// <summary>
    /// HTML Error hander
    /// </summary>
    public partial class SilverlightControlHtmlErrorHandler : UserControl, IErrorHandler
    {
        #region Fields
 
        /// <summary>
        /// Id of html element
        /// </summary>
        string elementID;
 
        /// <summary>
        /// Name of script function
        /// </summary>
        string scriptFunction;
 
        #endregion
 
        #region Ctor
 
        /// <summary>
        /// Constructor
        /// </summary>
        public SilverlightControlHtmlErrorHandler()
        {
            InitializeComponent();
        }
 

        #endregion
 
        #region IErrorHandler Members
 
        void IErrorHandler.ShowErrorReport(XElement x)
        {
            XElement xe = x.Element("Exceptions");
            if (xe == null)
            {
                return;
            }
            IEnumerable<XElement> l = xe.Elements("Exception");
            // Creates table text
            string text = "<table border=\"1\"><tr><td>N</td><td>Level</td><td>Message</td><td>Stack trace</td></tr>";
            int i = 1;
            foreach (XElement e in l)
            {
                text += "<tr><td>" + i + "</td><td>" + e.Element("Object").Value + "</td><td>" + 
                    e.Element("ExceptionMessage").Value + "</td><td>" + e.Element("StackTrace").Value + "</td></tr>";
                ++i;
            }
            text += "</table>";
            Action<string> acttext = WriteText; // If script function does not exist
            if (scriptFunction != null)
            {
                if (scriptFunction.Length > 0)
                {
                    acttext = WriteScript; // If script function exists 
                }
            }
           Action act = () =>
                {
                    acttext(text);
                };
            Dispatcher.BeginInvoke(act);
 
        }
 
        #endregion
 
        #region Members
 
        #region Public
 
        /// <summary>
        /// Script Function
        /// </summary>
        public string ScriptFunction
        {
            get
            {
                return scriptFunction;
            }
            set
            {
                scriptFunction = value;
            }
        }
 

 
        /// <summary>
        /// Id of HTML output
        /// </summary>
        public string HtmlId
        {
            get
            {
                return elementID;
            }
            set
            {
                elementID = value;
            }
        }
 
        #endregion
 
        #region Private
 
        /// <summary>
        /// Writes inner HTML
        /// </summary>
        /// <param name="text">Text to write</param>
        void WriteText(string text)   
        {
            HtmlDocument doc = HtmlPage.Document;
            HtmlElement element = doc.GetElementById(elementID);
            if (element != null)
            {
                element.SetAttribute("innerHTML", text);
            }
        }
        
        /// <summary>
        /// Calls script function
        /// </summary>
        /// <param name="text">Argument of function</param>
        void WriteScript(string text)
        {
            HtmlPage.Window.Invoke(scriptFunction, text);
        }
 
        #endregion
 
        #endregion

This component shows exception report as inner HTML or calls script function. Following snippet contains example of error handler function.

  <script type="text/javascript">
 
      // Shows error 
      // text is error text
      function showScriptError(text) {
          var div_preview = document.getElementById("Errors");
          div_preview.innerHTML = text;
      }
</script>
 

<div id="Errors"></div>
 
Some Web client elements should be associated with error handlers. These elements implement following interface.
 /// <summary>
/// Consumer of error handler
/// </summary>
public interface IErrorHandlerConsumer
{
    /// <summary>
    /// Consumer of error handler
    /// </summary>
    IErrorHandler ErrorHandler
    {
        get;
        set;
    }
}
 

Developer should not explicitly associate error handler. This operation is performed implicitly by following functions

         /// <summary>
        /// Recursive action
        /// </summary>
        /// <typeparam name="T">Type</typeparam>
        /// <param name="obj">Object</param>
        /// <param name="action">Action</param>
        public static void RecursiveAction<T>(this DependencyObject obj, Action<T> action) where T : class
        {
            if (obj is T)
            {
                action(obj as T);
            }
            int childrenCount = VisualTreeHelper.GetChildrenCount(obj);
            for (int i = 0; i < childrenCount; i++)
            {
                var child = VisualTreeHelper.GetChild(obj, i);
                if (child is DependencyObject)
                {
                    (child as DependencyObject).RecursiveAction<T>(action);
                }
            }
        }
 
        /// <summary>
        /// Gets root of objet
        /// </summary>
        /// <param name="element">The element</param>
        /// <returns>The root</returns>
        public static DependencyObject GetRoot(this DependencyObject element)
        {
            if (element is FrameworkElement)
            {
                DependencyObject dob = (element as FrameworkElement).Parent;
                if (!(dob is FrameworkElement))
                {
                    return element;
                }
                return GetRoot(dob);
            }
            return null;
        }
 
                              /// <summary>
        /// Root Recursive action
        /// </summary>
        /// <typeparam name="T">Type</typeparam>
        /// <param name="obj">Object</param>
        /// <param name="action">Action</param>
        public static void RootRecursiveAction<T>(this DependencyObject obj, Action<T> action)
            where T : class
        {
            DependencyObject d = obj.GetRoot();
            d.RecursiveAction<T>(action);
        }
                       /// <summary>
        /// Finds error handler
        /// </summary>
        /// <param name="consumer">Consumer of error handler</param>
        public static void FindErrorHandler(this ) consumer)
        {
            DependencyObject dob = consumer as DependencyObject;
            IErrorHandler eh = null;
            Action<IErrorHandler> find = (IErrorHandler h) =>
            {
                if (eh == null)
                {
                    eh = h;
                    return;
                }
            };
            dob.RootRecursiveAction<IErrorHandler>(find);
            if (eh != null)
            {
                consumer.ErrorHandler = eh;
            }
        } 

Following XAML code

<UserControl xmlns:SilverlightDiagramUI="clr-namespace:Diagram.UI.SilverlightDiagramUI;
    assembly=Diagram.UI.SilverlightDiagramUI" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:local="clr-namespace:DataPerformer.UI.SilverlightDataPerformer" 
    x:Class="DataPerformer.UI.SilverlightDataPerformer.SilverlightControlChartInputOutput"
    mc:Ignorable="d"
    d:DesignHeight="300" d:DesignWidth="400"><StackPanel>
         <Grid x:Name="LayoutRoot" ShowGridLines="True">
            <Grid.RowDefinitions>
                <RowDefinition/>
                <RowDefinition/>
                <RowDefinition/>
            </Grid.RowDefinitions>
            <Grid.ColumnDefinitions>
                <ColumnDefinition/>
            </Grid.ColumnDefinitions>
             <SilverlightDiagramUI:SilverlightControlAlias x:Name="Aliases" Grid.Column="0" 
             Grid.Row="0"  HorizontalAlignment="Stretch" Margin="0,0,0,0" />
            <local:SilverlightControlHtmlOutput x:Name="Chart"  Grid.Column="0" Grid.Row="1" />
            <Button click="Button_Click" content="Start" grid.row="2" 
            horizontalalignment="Stretch" margin="0,0,0,0" width="75" x:name="Start"/>
            <local:SilverlightControlHtmlErrorHandler x:Name="Errors" 
            HorizontalAlignment="Left" Height="0" Grid.Row="2" Width="0" Visibility="Collapsed"/>
        </Grid>
    </StackPanel>
</UserControl>

contains one IErrorHandler (it is SilverlightControlHtmlErrorHandler) and two IErrorHandlerConsumer objects (SilverlightControlAlias and SilverlightControlHtmlOutput. Both consumers automatically associated with error handler because all three elements have common root. Following picture represents interoperability between IErrorHandler and IErrorHandlerConsumer. Following sequence diagram explains usage of exception handler.

Error handler sequence

2.2 Client interfaces

2.2.1 Initialization interface

Some UI elements should be initialized after their appearance. Following schema represents such initialization

Initialization sequence

All objects which require such initialization implement IPostLoadService interface.

2.2.2 Additional information interface

A lot of user controls contains child controls. Usually request for server contains information which is contained in all children. Following control

Children controls

has two children. "Green" child generates following XML

<Aliases Desktop="Exponent.cfa">
   <Alias>
     <Name>Exp.a</Name>
     <Value>0.7</Value>
     <Type>System.Double</Type>
   </Alias>
   <Alias>
     <Name>Exp.b</Name>
     <Value>0.3</Value>
     <Type>System.Double</Type>
   </Alias>
 </Aliases>

"Blue" component generates:

<ChartDocument Chart="ExponentChart.xml" Desktop="Exponent.cfa">
  <Parameters>
    <Start>0</Start>
    <Step>1000</Step>
    <Finish>20000</Finish>
    <Xslt>Exponent.xslt</Xslt>
  </Parameters>
</ChartDocument>
In result following XML is sent to server:
<ChartDocument Chart="ExponentChart.xml" Desktop="Exponent.cfa">
  <Aliases Desktop="Exponent.cfa">
    <Alias>
      <Name>Exp.a</Name>
      <Value>0.7</Value>
      <Type>System.Double</Type>
    </Alias>
    <Alias>
      <Name>Exp.b</Name>
      <Value>0.3</Value>
      <Type>System.Double</Type>
    </Alias>
  </Aliases>
  <Parameters>
    <Start>0</Start>
    <Step>1000</Step>
    <Finish>20000</Finish>
    <Xslt>Exponent.xslt</Xslt>
  </Parameters>
</ChartDocument>

So information from "blue" control is appended to information of "green" control. "Blue control implements following interface

 /// <summary>
/// Adds information to request
/// </summary>
public interface IAddRequest
{
    /// <summary>
    /// Adds request
    /// </summary>
    /// <param name="x">Request element</param>
    void Add(XElement x);
}

All IAddRequest objects add information to request. Following diagram illustrates logics of request:

IAddRequest Business Logic

Note that add request operation should not be called explicitly. It is called implicitly by following function

/// <summary>
/// Adds information for request
/// </summary>
/// <param name="obj">Object</param>
/// <param name="x">Request Xml</param>
public static void AddRequest(this DependencyObject obj, XElement x)
{
    Action<IAddRequest> action = (IAddRequest a) => { a.Add(x);};
    obj.RootRecursiveAction<IAddRequest>(action);
}

2.3 Constant input

As rule every engineering task have input constants. For example calculation of f(t)=aebt function has two parameters a and b which can be regarded as constants. Software should support constant input.

2.3.1 Business logic

Following picture represents business logic of above task.

Simple Business Logic

Where Exp component calculates f(t)=aebt. Whole above picture is named Desktop. Any desktop correspond to object which implemens IDesktop interface. Properties of Exp are presented below.

Exp properties

Bottom right part of above window contains editor of a and b constants. The Exp object implements following interface:

     /// <summary>
    /// Collection on named data units
    /// </summary>
    public interface IAlias : IAliasBase
    {
        /// <summary>
        /// Names of all data units
        /// </summary>
        IList<string> AliasNames
        {
            get;
        }
 
        /// <summary>
        /// Access to data unit by name
        /// </summary>
        object this[string name]
        {
            get;
            set;
        }
 
        /// <summary>
        /// Gets unit type
        /// </summary>
        /// <param name="name">Unit name</param>
        /// <returns>Type of unit</returns>
        object GetType(string name);
    }

Following code explains usage of this interface.

IAlias alias = Exp as IAlias;
IList<string> names = alias.AliasNames; // {"a", "b"};
object a = alias["a"]; // a = 0.7 {double}
object b = alias["b"]; // a = 0.3 {double}
object t = alias.GetType("a"); // t = (double)0;
double x = 0.8;
alias["a"] = x;
a = alias["a"]; // a = 0.8 {double}

Aliases can be accessed from desktop by following way.

IDesktop desktop = ...;
object a = desktop.GetAliasValue("Exp.a"); // a = 0.7 {double}
object t = desktop.GetAliasType("Exp.a");  // t = (double)0;
double x = 0.8;
desktop.SetAliasValue("Exp.a", x);
a = desktop.GetAliasValue("Exp.a");         // a = 0.8 {double}

Also one can set aliases by following function

/// <summary>
/// Set aliases of desktop
/// </summary>
/// <param name="desktop">Desktop</param>
/// <param name="document">Document</param>
public static void SetAliases(this IDesktop desktop, XmlDocument document)

If document (second argument of above function) contains following element:

<Aliases Desktop="Exponent.cfa">
  <Alias>
    <Name>Exp.a</Name>
    <Value>0.7</Value>
    <Type>System.Double</Type>
  </Alias>
  <Alias>
    <Name>Exp.b</Name>
    <Value>0.3</Value>
    <Type>System.Double</Type>
  </Alias>
</Aliases>

then call of this function is equivalent to following code:

desktop.SetAliasValue("Exp.a", (double)0.7);
desktop.SetAliasValue("Exp.b", (double)0.3);

Business of constant input is call of SetAliases function with proper arguments.

2.3.2 Client component

Following user control implicitly performs remote call SetAliases. The term "implicitly" means that this task is not independent. Setting of aliases every time is subtask of major task.

 /// <summary>
/// Alias control
/// </summary>
public partial class SilverlightControlAlias : UserControl, IPostLoadService,
        IAddRequest, IErrorHandlerConsumer

It has following key properties

<SilverlightDiagramUI:SilverlightControlAlias Desktop="Exponent.cfa" Aliases="ExponentAliases.xml"  />

Where Desktop="Exponent.cfa" (resp. Aliases="ExponentAliases.xml") is file name of desktop (resp. aliases). As IPostLoadService it sends following initialization request.

<Aliases Desktop="Exponent.cfa" Aliases="ExponentAliases.xml" />

From content of files "Exponent.cfa", ExponentAliases.xml" server generates following response

<Aliases>
    <Item>
        <Number>1</Number>
        <Name> The "a" coefficient </Name>
        <Alias>Exp.a</Alias>
        <Value>0.7</Value>
        <Type>System.Double</Type>
    </Item>
    <Item>
        <Number>2</Number>
        <Name> The "b" coefficient </Name>
        <Alias>Exp.b</Alias>
        <Value>0.3</Value>
        <Type>System.Double</Type>
    </Item>
</Aliases>

Then user control receives initialization response and its appearance is changed by following way:

UI initialization


This component implements IAddRequest interface. So it provides information about values of aliases for major task. Additional information  is considered in 2.2.2.



2.3 Output of chart

2.3.1 Business logic

Our sample

SimpleBusinessLogic

contains Chart component. Besides graphical mode it has text one.

Chart text mode

This mode generates following XML:

<Root>
  <Parameters>
    <Parameter Name="Value" Value="0.7" />
    <Parameter Name="Argument" Value="0" />
  </Parameters>
  <Parameters>
    <Parameter Name="Value" Value="0.702103153152364" />
    <Parameter Name="Argument" Value="0.01" />
  </Parameters>
  <Parameters>
    <Parameter Name="Value" Value="0.704212625237845" />
    <Parameter Name="Argument" Value="0.02" />
  </Parameters>
  <Parameters>
    <Parameter Name="Value" Value="0.706328435241708" />
    <Parameter Name="Argument" Value="0.03" />
  </Parameters>
</Root>

This XML is returned by following function

/// <summary>
/// Creates Xml document
/// </summary>
/// <param name="desktop">Desktop</param>
/// <param name="input">Input</param>
/// <returns>Document</returns>
static public XmlDocument CreateXmlDocument(this IDesktop desktop, XmlDocument input)

where input is represented by following text.

  <ChartDocument>
        <Interval>
            <Start>0</Start>
            <Step>0.01</Step>
            <Finish>0.03</Finish></Interval>
     <ChartName>Chart</ChartName>
     <Parameters>
         <Parameter>
             <Name>Exp.Formula_1</Name>
             <Value>Value</Value>
        </Parameter>
         <Parameter>
             <Name>Exp.Formula_2</Name>
             <Value>Argument</Value>
         </Parameter>
     </Parameters>
</ChartDocument>
 
<pso>


2.3.2 Client componentt

Client has following user control

  /// <summary>
/// Html output of chart
/// </summary>
public partial class SilverlightControlHtmlOutput : UserControl, IRequest,
    IErrorHandlerConsumer, IPostLoadService

This control has following key properties:

<SilverlightControlHtmlOutput  Desktop="Exponent.cfa" Xslt="Exponent.xslt" 
    Chart="Exponent.xml" ScriptFunction="showOutput" />

Here Desktop="Exponent.cfa" is filename of serialized desktop. The Exponent.xml

<WriteText>;
  <Interval>
    <Start>0</Start>
    <Step>500</Step>
    <Finish>20000</Finish>
  </Interval>
  <ChartName>Chart</ChartName>
  <Argument>Time</Argument>
  <Parameters>
    <Parameter>
      <Name>Exp.Formula_1</Name>
      <Value>Value</Value>
    </Parameter>
    <Parameter>
      <Name>Exp.Formula_2</Name>
      <Value>Argument</Value>
    </Parameter>
  </Parameters>
</WriteText>

 

This XML is responsible for initial appearance of user control
 

and call of CreateXmlDocument function. These so this XML document structure of output document.

<>
NOutput parameterName in output XML
1Exp.Formula_1Value
1Exp.Formula_2Argument

Class SilverlightControlHtmlOutput as  IPostLoadService sends following request to server:

<Chart>ExponentChart.xml</Chart>

Server response is content of ExponentChart.xml. In result of this initialization user control obtains following visual appearance:

Chart initial

This class also implements following interface:

/// <summary>
/// Request object
/// </summary>
public interface IRequest
{
    /// <summary>
    /// Request
    /// </summary>
    void Request();
}

The Request sends to server following request.

 
<ChartDocument Chart="ExponentChart.xml" ShowFunction="showOutput" Desktop="Exponent.cfa">
  <Parameters>
    <Start>0</Start>
    <Step>1000</Step>
    <Finish>20000</Finish>
    <Xslt>Exponent.xslt</Xslt>
  </Parameters>
</ChartDocument>

This request and content of "ExponentChart.xml" generate following XML:

<ChartDocument Chart="ExponentChart.xml" Desktop="Exponent.cfa">
    <Interval>
        <Start>0</Start>
        <Step>1000</Step>
        <Finish>20000</Finish>
        <Xslt>Exponent.xslt</Xslt>
    </Interval>
    <ChartName>Chart</ChartName>
    <Parameters>
        <Parameter>
            <Name>Exp.Formula_1</Name>
            <Value>Value</Value>
        </Parameter>
        <Parameter>
            <Name>Exp.Formula_2</Name>
            <Value>Argument</Value>
        </Parameter>
    </Parameters>
</ChartDocument>

This XML is used as argument of CreateXmlDocument function which returns following document:

<Root>
    <Parameters>
        <Parameter Name="Value" Value="0.7" />
        <Parameter Name="Argument" Value="0" />
    </Parameters>
    <Parameters>
        <Parameter Name="Value" Value="1.35969847666886E+130" />
        <Parameter Name="Argument" Value="1000" /></Parameters>
    <Parameters><Parameter Name="Value" Value="2.64111421065087E+260" />
        <Parameter Name="Value" Value="2.64111421065087E+260" />
        <Parameter Name="Argument" Value="2000" />
    </Parameters>
</Root>

Then this XML is transformed by XSLT which is contained in Exponent.xslt
file:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:msxsl="urn:schemas-microsoft-com:xslt"
	xmlns:user="urn:my-scripts">
  <xsl:key name="parameter-search" match="Parameter" use="@Name"/>
  <xsl:template match="/">
    <text>
      <h1>
        Table of <em>
          ae<sup>bx</sup>
        </em>
      </h1>
      <table border="1">
        <tr>
          <td>
            <em>x</em>
          </td>
          <td>
            <em>
              ae<sup>bx</sup>
            </em>
          </td>
        </tr>
        <xsl:apply-templates/>
      </table>
    </text>
  </xsl:template>
  <xsl:template match="Parameters">
        <tr>
          <td>
            <xsl:value-of select="Parameter[2]/@Value"/>
          </td>
          <td>
            <xsl:value-of select="Parameter[1]/@Value"/>
          </td>
        </tr>
  </xsl:template>
</xsl:stylesheet>

Transformation result is presented below:

<text>
    <h1>Table of <em>ae<sup>bx</sup></em></h1>
        <table border="1">
            <tr><td><em>x</em></td><td><em>ae<sup>bx</sup></em></td></tr>
            <tr><td>0</td><td>0.7</td></tr>
            <tr><td>1000</td><td>1.35969847666886E+130</td></tr>
            <tr><td>2000</td><td>2.64111421065087E+260</td></tr>
        </table>
</text>
 

Server also generates error report. Result response contains calculation result
and exception report.

<Root>
    <Text><![CDATA[<h1>Table of <em>ae<sup>bx</sup></em></h1>
        <table border="1">
            <tr><td><em>x</em></td><td><em>ae<sup>bx</sup></em></td></tr>
            <tr><td>0</td><td>0.7</td></tr>
            <tr><td>1000</td><td>1.35969847666886E+130</td></tr>
            <tr><td>2000</td><td>2.64111421065087E+260</td></tr>
        </table>]]>
    </Text>
    <Exceptions>
        <Exception>
            <Object>10</Object>
            <StackTrace>   at EngineeringInitializer.BasicEngineeringInitializer.<InitializeApplication>b__0(Object o) 
                at c:\AUsers\1MySoft\CSharp\src\src\EngineeringInitializer\BasicEngineeringInitializer.cs:line 68
                at Calculation.Calculate.Update() at c:\Users\3D_MONSTR\AppData\Local\Temp\ewmveptb.0.cs:line 33
                at DataPerformer.VectorFormulaConsumer.UpdateMeasurements() 
                at c:\AUsers\1MySoft\CSharp\src\src\DataPerformer\VectorFormulaConsumer.cs:line 401
            </StackTrace>
            <ExceptionMessage>Infinity</ExceptionMessage>
            <ExceptionType>System.Exception</ExceptionType>
        </Exception>
        <Exception>
            <Object>10</Object>
            <StackTrace>   
                at OrbitalService.ServiceOrbital.<AppllicactionInitialize>b__0(Object o) 
                at c:\AUsers\1MySoft\CSharp\src\WCF\OrbitalService\ServiceOrbital.svc.cs:line 43
                at DataPerformer.StaticExtensionDataPerformerAdvanced.<>c__DisplayClass5.<CreateXmlDocument>b__3() 
                at c:\AUsers\1MySoft\CSharp\src\src\DataPerformer\StaticExtensionDataPerformerAdvanced.cs:line 301
                at DataPerformer.StaticExtensionDataPerformerBase.PerformFixed(IDataConsumer consumer,
                 Double start, Double step, Int32 count, ITimeMeasureProvider provider, IDifferentialEquationProcessor processor, 
                 IComponentCollection collection, Int32 priority, Action action) 
                at c:\AUsers\1MySoft\CSharp\src\src\DataPerformer
                 \DataPerformer.Base\DataPerformer.Base\StaticExtensionDataPerformerBase.cs:line 1723
            </StackTrace>
            <ExceptionMessage>Infinity</ExceptionMessage>
            <ExceptionType>System.Exception</ExceptionType>
        </Exception>
    </Exceptions>
</Root>

Content of Text tag contains output HTML. Property ScriptFunction = "showOutput" means that
showOutput script is called.

<script type="text/javascript">
 
             // Shows output
             // text is output text
             function showOutput(text) {
                 var div_preview = document.getElementById("Output");
                 div_preview.innerHTML = text;
             }
</script>
<!--...-->
<div id="Output"></div>

Call of this script shows following:

+++++++++++++++++++++++++++++++

Table of aebx

<>
xaebx
00.7
10001.35969847666886E+130
20002.64111421065087E+260

+++++++++++++++++++++++++++++++

2.4 Combination of user controls

It is clear that any of above component is useless as itself. For example exception handler never handles exceptions without substantial task. Following XAML code contains useful combination of user contrlos.

<UserControl xmlns:SilverlightDiagramUI="clr-namespace:Diagram.UI.SilverlightDiagramUI;
    assembly=Diagram.UI.SilverlightDiagramUI" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:local="clr-namespace:DataPerformer.UI.SilverlightDataPerformer" 
    x:Class="DataPerformer.UI.SilverlightDataPerformer.SilverlightControlChartInputOutput"
    mc:Ignorable="d"
    d:DesignHeight="300" d:DesignWidth="400"><StackPanel>
         <Grid x:Name="LayoutRoot" ShowGridLines="True">
            <Grid.RowDefinitions>
                <RowDefinition/>
                <RowDefinition/>
                <RowDefinition/>
            </Grid.RowDefinitions>
            <Grid.ColumnDefinitions>
                <ColumnDefinition/>
            </Grid.ColumnDefinitions>
             <SilverlightDiagramUI:SilverlightControlAlias x:Name="Aliases" Grid.Column="0" 
             Grid.Row="0"  HorizontalAlignment="Stretch" Margin="0,0,0,0" />
            <local:SilverlightControlHtmlOutput x:Name="Chart"  Grid.Column="0" Grid.Row="1" />
            <Button click="Button_Click" content="Start" grid.row="2" 
            horizontalalignment="Stretch" margin="0,0,0,0" width="75" x:name="Start"/>
            <local:SilverlightControlHtmlErrorHandler x:Name="Errors" 
            HorizontalAlignment="Left" Height="0" Grid.Row="2" Width="0" Visibility="Collapsed"/>
        </Grid>
    </StackPanel>
</UserControl>
Following sequence diagram explains logic of this user control.

 

Full sequence diagram

This component appends aliases to chart request.st.

<ChartDocument Chart="ExponentChart.xml" Desktop="Exponent.cfa">
  <Aliases Desktop="Exponent.cfa">
    <Alias>
      <Name>Exp.a</Name>
      <Value>0.7</Value>
      <Type>System.Double</Type>
    </Alias>
    <Alias>
      <Name>Exp.b</Name>
      <Value>0.3</Value>
      <Type>System.Double</Type>
    </Alias>
  </Aliases>
  <Parameters>
    <Start>0</Start>
    <Step>1000</Step>
    <Finish>20000</Finish>
    <Xslt>Exponent.xslt</Xslt>
  </Parameters>
</ChartDocument>

If value of exponent become too big then program throws exceptions

Error message

Full picture of UI is presented below:

Exp UI

It contains aliases, parameters of interval, output html, error report.


3. Realistic sample. Artificial Earth's Satellite Motion Forecast

3.1 Business Logicgic


Business Logic of the this sample is already described hereere. But I have copied text for easy reading.

 

3.1.1 Motion model

The motion model of an artificial satellite is a system of ordinary differential equations that describe the motion in a Greenwich reference frame:

Motion equations

where
Motion parameters are the coordinates and components of velocity respectively,
Omega is angular velocity of Earth, and
Omega are components of the summary external acceleration. The current model contains gravitational force and the aerodynamic one. These accelerations can be defined by the following formulae:

Acceleration formulae

The following table contains meaning of these parameters:

Parameters

Component of ordinary differential equations is used for above equations. This component does not have a rich system of symbols and uses lower case variables only. However this component supports rich system of comments which is presented below:

Parameters

These comments can contain mappings between variables and physical parameters. Independent variables of equations (x, y, z, u, v, w) are checked in right part. Mapping between these variables and

Parameters

The component represents differential equations in the following way:

Parameters

Besides independent variables equations contain additional parameters. The following table contains mapping of these parameters:

Parameters

Some of these parameters are constants. Other parameters should be exported. Constants are checked and exported parameters are not checked below:

Parameters

Exported parameters concern with gravity and atmosphere models. These models are contained in external libraries. The following picture contains components of motion model.

Motion model

The Motion equations component is considered above component of ordinary differential equations. These equations have feedback. Right parts of equations depend on gravitational forces. Otherwise gravitational forces depend on coordinates of the satellite. The Vector component is used as feedback of Motion equations.

FeedBack

This picture has the following meaning. Variables x, y, z, u, v, w of Vector component are assigned to x, y, z, u, v, w variables of Motion equations. Input and output parameters of Vector are presented below:

Pareameters of Vector object

Components Gravity, Atmosphere are objects obtained from external libraries which calculate Gravity of Earth and Earth's atmosphere respectively. Both these objects implement IObjectTransformer interface. The G-transformation and A-transformation objects are helper objects which are used for application of Gravity, Atmosphere objects respectively. Properties of G-transformation are presented below:

Pareameters of Vector object

The above picture has the following meaning. The G-transformation is connected to Gravity object. This object corresponds to exported Gravity class (code of Gravity class is above this text). The Gravity class implements IObjectTransformer interface. Input parameters of Gravity are coordinates which are labeled by "x", "y", "z" labels. So above comboboxes are labeled by x", "y", "z labels. The above picture means that parameters x", "y", "z" are assigned to Formula_1, Formula_2, Formula_3 of Vector component. Otherwise Formula_1, Formula_2, Formula_3 of Vector are assigned to x, y, z of Motion equations. However Motion equations component uses parameters of G-transformation:

Parameters of Vector object

This picture means that parameters a, b, c of a, of Motion equations are assigned to parameters Gx, Gy, Gz of G-transformation. So of Earth's Gravity function is exported to G-transformation. The Earth's atmosphere is exported in a similar way.

3.1.2 Generation of document

In this sample actual function f is used. However this function has another argument. This argument is Z- coordinate of the satellite.

Besides calculation, any software needs generation of documents. Facilities generation of documents are exhibited on forecast problem. Forecast document contains parameters of satellite motion in times of equator intersections. The following picture explains the forecast problem:

Forecast picture

Satellite moves along its orbit. Parameters of motion correspond to the time when it moves from South to North and intersects equator. Satellite intersects equator when its Z - coordinate is equal to 0. If we have coordinates and time as function of Z, then we can see necessary parameters are values of these functions where Z = 0. The following picture represents a solution of this task.

Forecast algorithm

The Delay component has FunctionAccumulator type. This type is very similar to Transport delay of Simulink. However FunctionAccumulator is more advanced. Properties of Delay are presented below:

Delay

The Delay component is connected to Data to data one. It stores latest output values of Data. The Step count = 4 means that Delay stores 4 last values of each output parameters. The Formula_4 of data is Z coordinate of satellite. So all parameters of Delay are considered as functions of Z. Let us consider all components of forecast. The Satellite component is a container which contains Motion equations of the satellite. The Data component is connected to Motion equations and adds time parameters to motion parameters. Properties of Data are presented below:

Data.

The Recursive component is similar to Memory component of Simulink. This component calculates time delay of Z coordinate. Properties of the Recursive element are presented below:

Recursve

The Condition element is used for determination of time of equator intersection. Properties of Condition are presented below:

Condition

Meaning of parameters of this component is contained in comments:

Condition

And at last, Output component contains calculation of forecast parameters. It has the following formulae:

Output Formulae

The 86 400 number is number of seconds in a day. The time function converts double variable to DateTime. The b is condition of equator intersection. Input parameters are motion parameters as functions of Z. Full list of parameters is contained in the following comments:

Output

And at last, Chart component has the following properties:

Chart

These properties have the following meaning. Output is performed when condition variable is true. In this case, condition is Formula_1 of Condition object. It is condition of equator intersection. Output parameters are Formula_1 - Formula_7 of Output object. Labels X, Y, Z, Vx, Vy, Vz are labels which are reflected in XML document. The XML document is presented below:

XML
<Root>
  <Parameters>
    <Parameter Name="T" Value="Monday, June 28, 1999 11:17:05 PM.457" />
    <Parameter Name="X" Value="-6595.47050815637" />
    <Parameter Name="Y" Value="-2472.05799683873" />
    <Parameter Name="Z" Value="0" />
    <Parameter Name="Vx" Value="-0.541295154046453" />
    <Parameter Name="Vy" Value="1.46945520971716" />
    <Parameter Name="Vz" Value="7.45051367374592" />
  </Parameters>
  <Parameters>
    <Parameter Name="T" Value="Tuesday, June 29, 1999 12:55:08 AM.068" />
    <Parameter Name="X" Value="-7026.76544757067" />
    <Parameter Name="Y" Value="487.053173194772" />
    <Parameter Name="Z" Value="0" />
    <Parameter Name="Vx" Value="0.117122882887633" />
    <Parameter Name="Vy" Value="1.56173832654579" />
    <Parameter Name="Vz" Value="7.45055871464937" />
  </Parameters>
 <Root>

The first parameter has DateTime type and the other ones have double type. The following code contains XSLT file.

XML
<xsl:stylesheet version="1.0" xmlns:xsl=http://www.w3.org/1999/XSL/Transform 
    xmlns:msxsl="urn:schemas-microsoft-com:xslt"
    xmlns:user="urn:my-scripts">
  <xsl:template match="/">
    <html>
      <body>
        <p>
          <h1>Forecast</h1>
        </p>
        <xsl:apply-templates />
      </body>
    </html>
  </xsl:template>
  <xsl:template match="Parameters">
    <p></p>
    <p>
      <table border="1">
        <xsl:apply-templates />
      </table>
    </p>
  </xsl:template>
  <xsl:template match="Parameter">
    <xsl:apply-templates />
    <tr>
      <td>
        <xsl:value-of select="@Name" />
      </td>
      <td>
        <xsl:value-of select="@Value" />
      </td>
    </tr>
  </xsl:template>
</xsl:stylesheet>

This XSLT code provides the following HTML document.

<>
T Monday, June 28, 1999 11:17:05 PM.457
X -6595.47050815637
Y -2472.05799683873
Z 0
Vx -0.541295154046453
Vy 1.46945520971716
Vz 7.45051367374592
T Tuesday, June 29, 1999 12:55:08 AM.068
X -7026.76544757067
Y 487.053173194772
Z 0
Vx 0.117122882887633
Vy 1.56173832654579
Vz 7.45055871464937

3.2 Web Version

As Web application this project is not principallly differerent from elementary project described in section 1. This project has output condition and this fact is reflected in following XML.

<WriteText>
  <Interval>
    <Start>1770457394</Start>
    <Step>10</Step>
    <Finish>1770460394</Finish>
  </Interval>
  <ChartName>Forecast</ChartName>
  <Condition>Condition.Formula_1</Condition>
  <Argument>Time</Argument>
  <Parameters>
    <Parameter>
      <Name>Output.Formula_1</Name>
      <Value>T</Value>
    </Parameter>
    <Parameter>
      <Name>Output.Formula_2</Name>
      <Value>X</Value>
    </Parameter>
    <Parameter>
      <Name>Output.Formula_3</Name>
      <Value>Y</Value>
    </Parameter>
    <Parameter>
      <Name>Output.Formula_4</Name>
      <Value>Vx</Value>
    </Parameter>
    <Parameter>
      <Name>Output.Formula_5</Name>
      <Value>Vy</Value>
    </Parameter>
    <Parameter>
      <Name>Output.Formula_6</Name>
      <Value>Vz</Value>
    </Parameter>
  </Parameters>
</WriteText>

Expression <Condition>Condition.Formula_1</Condition> that output condition Formula_1 of Condition object. Following XML persents aliases:

<Root>
  <Item>
    <Number>1</Number>    <Name> X - coordinate of the satellite (x) , km </Name>
    <Alias>Motion equations/Motion equations.x</Alias>
    <Type>System.Double</Type>
  </Item>
  <Item>
    <Number>2</Number>
    <Name> Y - coordinate of the satellite (y), km </Name>
    <Alias>Motion equations/Motion equations.y</Alias>
    <Type>System.Double</Type>
  </Item>
  <Item>
    <Number>3</Number>
    <Name> Z - coordinate of the satellite (z), km </Name>
    <Alias>Motion equations/Motion equations.z</Alias>
    <Type>System.Double</Type>
  </Item>
  <Item>
    <Number>4</Number>
    <Name> X - component of velicity of the satellite (Vx), km/s </Name>
    <Alias>Motion equations/Motion equations.u</Alias>
    <Type>System.Double</Type>
  </Item>
  <Item>
    <Number>5</Number>
    <Name> Y - component of velicity of the satellite (Vy), km/s </Name>
    <Alias>Motion equations/Motion equations.v</Alias>
    <Type>System.Double</Type>
  </Item>
  <Item>
    <Number>6</Number>
    <Name> Z - component of velicity of the satellite (Vz), km/s </Name>
    <Alias>Motion equations/Motion equations.w</Alias>
    <Type>System.Double</Type>
  </Item>
</Root>gt;

These alises are initial conditions of differetial equation system.

Initial conditions


Acting web client is placed at begin of this article.

Points of Interest


My very blue dream is invention of new time machine. I would like to develop online designer which is similar to Code Project one.

Time machine Code Project

However my designer shall be a toolkit for developers of science and engineering portals.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Architect
Russian Federation Russian Federation
Ph. D. Petr Ivankov worked as scientific researcher at Russian Mission Control Centre since 1978 up to 2000. Now he is engaged by Aviation training simulators http://dinamika-avia.com/ . His additional interests are:

1) Noncommutative geometry

http://front.math.ucdavis.edu/author/P.Ivankov

2) Literary work (Russian only)

http://zhurnal.lib.ru/editors/3/3d_m/

3) Scientific articles
http://arxiv.org/find/all/1/au:+Ivankov_Petr/0/1/0/all/0/1

Comments and Discussions

 
GeneralMy vote of 5 Pin
D V L30-Sep-15 19:37
professionalD V L30-Sep-15 19:37 
QuestionMy Vote of 5 Pin
Manikandan102-Jun-14 21:52
professionalManikandan102-Jun-14 21:52 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.