Rapid Development of Engineeging Web Site






4.95/5 (10 votes)
From desktop to Web

Useful links
- Original article
- Visual Studio Express 2012 for Windows Desktop
- Visual Studio Express 2012 for Web
- Home: Silverlight.NET
- Windows Azure. A rock-solid cloud platform for blue-sky thinking
- Home: Mathframe
- Home: AstroFrame
- Home: Weifen Luo
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.
My approach is the same. Following picture shows this fact.
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
Web version of above error handling looks like:
N | Level | Message | Stack trace |
1 | 10 | NaN | at EngineeringInitializer.BasicEngineeringInitializer. |
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.
2.2 Client interfaces
2.2.1 Initialization interface
Some UI elements should be initialized after their appearance. Following schema represents such initialization
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
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:
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.
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.
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:
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
contains Chart component. Besides graphical mode it has text one.
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>
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.
N | Output parameter | Name in output XML |
1 | Exp.Formula_1 | Value |
1 | Exp.Formula_2 | Argument |
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:
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
x | aebx |
0 | 0.7 |
1000 | 1.35969847666886E+130 |
2000 | 2.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.
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
Full picture of UI is presented below:
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:
where
are the coordinates and components of velocity respectively,
is angular velocity of Earth, and
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:

The following table contains meaning of these 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:

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

The component represents differential equations in the following way:

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

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

Exported parameters concern with gravity and atmosphere models. These models are contained in external libraries. The following picture contains components of 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.

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:

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:

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:

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:

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.

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:

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:

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:

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

Meaning of parameters of this component is contained in comments:

And at last, Output component contains calculation of forecast parameters. It has the following 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:

And at last, Chart component has the following properties:

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:
<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.
<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.
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.
However my designer shall be a toolkit for developers of science and engineering portals.