Sharp-Expressions
- The programming language C#
- General structure of a C# program
- Basic syntax
- Standard data types (selection)
- Use of Sharp-Expressions
- Expression Parser
Sharp-Expressions can be used for various applications on the 446 Plattform®. This makes sense where the user interface is the only way to display a complex situation that is not or only partially represented. The full scope of the programming language C# can be used.
Note:
The Sharp-Expressions of the 446 Plattform® support the syntax of version C#8.0.
C# programs can consist of one or more files. Each file can contain zero or more namespaces. A namespace can contain types such as classes, structs, interfaces, enumerations, and delegates, in addition to other namespaces. The following is the skeleton of a C# program that contains all of these elements.
/* A skeleton of a C# program */
using System;
namespace YourNamespace
{
class YourClass
{
}
struct YourStruct
{
}
interface IYourInterface
{
}
delegate int YourDelegate();
enum YourEnum
{
}
namespace YourNestedNamespace
{
struct YourStruct
{
}
}
class YourMainClass
{
static void Main(string[] args)
{
/* Your program starts here... */
}
}
}
Example: Simple MessageBox in C#
using System;
using System.Windows.Forms;
class Program
{
public static void Main()
{
MessageBox.Show("Text", "Titel", MessageBoxButtons.OK, MessageBoxIcon.Hand);
}
}
- Empty Entities
The null keyword is a literal that represents a null reference, one that does not refer to any object. It stands for does not exist or not set.
For Sharp-Expressions, the keyword must be written completely in lower case for comparisons with null.
For legacy expressions: Writing in upper case NULL
- {#Ticket.OwnerUser != null#}
Returns True if the ticket has an owner, otherwise False.
- {# Ticket.OwnerUser != null ? Ticket.OwnerUser.FullName : Ticket.OwnerGroup.Name #}
Returns the FullName of the person who is the current ticket owner. If the ticket has no current owner, the name of the current owner group is returned.
- {# Ticket.Fields["servicearticleline"]
.Text != String.Empty #}
Returns True if the ticket has the ticket field servicearticleline and its text content is not empty. A ticket does not have all fields defined in the schema, but only those that have content. To check whether a ticket has a ticket field, you can proceed like this:
{# Ticket.Fields.ContainsKey("servicearticleline") #}
This can also be combined:
{# Ticket.Fields.ContainsKey("servicearticleline") && Ticket.Fields["servicearticleline"].Text != String.Empty #}
From
there will be a simplification for this:
{# Ticket.GetFieldText("servicearticleline") #}
Returns the text content of the specified ticket field, or NULL.
- {# Ticket.ExternalSolution == String.Empty #}
Returns True if the external solution is not empty, otherwise False.
- {# WorkflowItem.Fields["ee"].Text == null #}
Similar to the ticket field: Returns True if the workflow item has the field ee and its text content is not empty. A workflow item generally only has fields that also have a content. If an empty text is assigned to a field, the field is effectively deleted. To check whether a workflow item has a particular field, you can proceed in this way:
{# WorkflowItem.Fields["ee"] != null #}
This can also be combined (but the check for String.Empty is unnecessary and redundant for the reason mentioned above):
{# WorkflowItem["ee"] != null && WorkflowItem["servicearticleline"].Text != String.Empty #}
From
there will be a simplification for this:
{# WorkflowItem.GetFieldText("servicearticleline") #}
Returns the text contents of the specified field or NULL.
Note:
For problems accessing ticket fields see also example 3.
- Functions
{#
int add(int i, int j)
{
return i+j;
}
add(1,2)
#}
- Times
- {# General.CurrentDateTime.UtcDateTime #}
Returns the current timestamp in the neutral time zone.
- {# DateTime.Parse("11.10.2019 08:24:28").ToLocalTime() #}
In this example please note:
The specified string often does not work because of the different formatting (US/GB/DE...) and the regional settings of the server.
ToLocalTime uses the current time zone of the server. This may be desirable in theory if you don't have a context user (e.g. within the workflow), but is rather an unusual use case.
- String operations
Split - Search within a string:
{#
var c = WorkflowItem.Fields["AllUploaded
LeaseDocuments"].Text; c.Split(new string[] { "\"elid\" : \"" }, StringSplitOptions.None)[1].Split('\"')[0]
#}
Returns the left part of an e-mail address.
Contains:
{#WorkflowItem.Fields["REST_returnData"]
Returns True if the field content contains the specified text.
Warning:
Note upper and lower case (see also section 4.c on strings).
More details: MSDN
- Dynamic access to ticket field
{# Ticket.Fields[WorkflowItem.Fields
- JavaScript Encode
{#Ticket.Fields["Radio_Comment"]
- List
A block-level flow content element that provides facilities for presenting content in an ordered or unordered list.
Some expressions have a List as return value. This can be recognized by the type List<...> (e.g. List<CxFile> for the expression Ticket.Attachments. It is also possible to go through such lists as follows:
foreach(var file in Ticket.Attachments)
{
/*The variable file is now of type CxFile, and allows access to all its properties.*/
}
More details: MSDN
- Dictionary
Represents a collection of keys and values.
Some expressions have a Dictionary as return value. These are list elements that are each assigned to a unique name. You can recognize this by the type Dictionary<[name],[element]>.
For example: Dictionary<String,CxTicketFieldValue> in expression Ticket.Fields.
It is also possible to go through such lists as follows:
foreach(var fieldName in Ticket.Fields.Keys)
{
/*The variable fieldName is now of type String, and allows all string operations. At the same time it is used to access the actual ticket field:*/
var field = Ticket.Fields[fieldName];
/*The variable field is now of type CxTicketFieldValue and allows access to all properties of this type. It is also possible to go directly through the Ticket.Fields.Values, but you would not have a variable with the name of the ticket field.*/
}
More details: MSDN
A string is a sequential collection of characters that is used to represent text. A String object is a sequential collection of System.Char objects that represent a string; a System.Char object corresponds to a UTF-16 code unit. The value of the String object is the content of the sequential collection of System.Char objects, and that value is immutable (that is, it is read-only).
The Sharp-Expressions support all string functions that C# supports with .NET. Among them are for example:
myString.ToUpper() /*Converts all characters to upper case.*/
myString.Contains("test") /*Returns True if the string contains test (case sensitive).*/
myString.Length /*Returns the string length.*/
myString.Replace("19%", "20%") /*Replaces all occurrences of 19% with 20%.*/
myString.StartsWith("Test") /*Returns True if the string starts with Test (case sensitive).*/
myString.SubString(10) /*Returns all characters of the string starting from its 10th position.*/
myString.IndexOf("test") /*Returns the position where test first occurs (useful for the SubString method).*/
More details: MSDN
- Int32
Represents a 32-bit signed integer.
public struct Int32: IComparable, IComparable<int>, IConvertible, IEquatable<int>, IFormattable
Int32 is an immutable value type that represents signed integers with values that range from negative 2,147,483,648 through positive 2,147,483,647.
More details: MSDN
- Decimal
Represents a decimal floating-point number.
public struct Decimal: IComparable, IComparable<decimal>, IConvertible, IEquatable<decimal>, IFormattable, System.Runtime.Serialization.
The Decimal value type represents decimal numbers ranging from positive 79,228,162,514,264,337,593,543,950,335 to negative 79,228,162,514,264,337,593,543,950,335. The default value of a Decimal is 0.
More details: MSDN
- TimeSpan/DateTime
A TimeSpan object represents a time interval (duration of time or elapsed time) that is measured as a positive or negative number of days, hours, minutes, seconds, and fractions of a second. The TimeSpan structure can also be used to represent the time of day, but only if the time is unrelated to a particular date. Otherwise, the DateTime or DateTimeOffset structure should be used instead.
The Sharp-Expressions support all DateTime functions that C# supports with .NET. Among them are for example:
myDateTime.AddMinutes(10) /*Adds 10 minutes*/
DateTime.Now /*Returns the current date and time in the server local time zone.*/
DateTime.UtcNow /*Returns the current timestamp in the neutral time zone.*/
DateTime myDateTime = DateTime.Parse("23.04.2019 11:30:12") /*Converts the specified string into a DateTime object (may fail due to the format string).*/
DateTime myDateTime = DateTime.Parse("2019-04-23T11:30:12") /*The sortable format works reliably when converting to a DateTime object.*/
More details: MSDN
With the 446 Plattform®, Sharp-Expressions can be used as placeholders for evaluations, messages, escalation times and more. The statements must be opened with the prefix {# and ended with the suffix #}. Any C# expression can be used in between.
{#/* Prefix */
/* Declarations of variables */
string output = string.Empty;
{
/* Instructions */
output = Ticket.FullId;
}
/* Output */
output /* Last statement without semicolon */
#}/* Sufix */
The methods can be accessed by entering a point after the corresponding object.
Ticket.SuccessorTickets[i].FullId
Tip:
An overview of the available methods can be found here:
In the declaration, it is possible to use the implicit type var for each variable type declared in the method area:
Int32 output = Ticket.IdNumber or
var output = Ticket.IdNumber
Note:
No semicolon may be set for a single-line statement or for the last statement of the Sharp-Expressions.
For the configuration of ticket actions, for example, all available Sharp-Expressions can be used. In the Expression clause tab it is possible to enter statements that cause the action to be displayed only if True is returned.
The {# Ticket.Comments.Count < 5 #} statement returns True if there are less than five comments stored in the corresponding ticket. So the action will be displayed (if you try to add the sixth comment, the action will not be displayed).
Administrators can use the 446 Plattform® Expression Parser (Expressions Debugger) to test expressions. First, an object ID is entered as the context object and the Sharp-Expression to be tested in the field below it. Compile can be used for syntactic checking. By Parse or Parse/Analyze the expression is executed and the result is displayed.
Chapters
C# is a general-purpose, multi-paradigm programming language encompassing strong typing, lexically scoped, imperative, declarative, functional, generic, object-oriented (class-based), and component-oriented programming disciplines. It was developed around 2000 by Microsoft within its .NET initiative. Microsoft refers to its implementation as Visual C#.
The C# syntax is simple and easy to learn despite its expressiveness. The C# syntax with curly braces is immediately recognizable for all users who are familiar with C, C++ or Java. Developers who are familiar with one of these languages can usually get C# up and running in no time.
As an object-oriented language, C# supports the concepts of encapsulation, inheritance and polymorphism. All variables and methods, including the Main method, which is the entry point to the application, are encapsulated within the class definition. A class can inherit directly from a parent class, but it can also implement any number of interfaces. Methods that override virtual methods in a parent class require the override keyword as a way to prevent accidental redefinition. In C#, a structure behaves like a simplified class.
C# programs run on the basis of .NET Framework, an integral Windows component that includes a virtual execution system called the Common Language Runtime (CLR) and a unified set of class libraries.
C# Guide: docs.microsoft.com/en-us/dotnet/csharp
[Source: Wikipedia, docs.microsoft.com]