-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathApi.cs
More file actions
200 lines (160 loc) · 5.25 KB
/
Copy pathApi.cs
File metadata and controls
200 lines (160 loc) · 5.25 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
using System.Collections.Concurrent;
using CodeEffects.Rule.Common.Attributes;
using CodeEffects.Rule.Common.Models;
using CodeEffects.Rule.Editor;
using CodeEffects.Rule.Editor.Models;
using CodeEffects.Rule.Engine;
using Microsoft.AspNetCore.Mvc;
namespace CodeEffects.Demo.Asp;
public static class Api
{
// Simple in-memory rule storage for the sake of this demo
private static readonly ConcurrentDictionary<string, Rule> Storage = new();
// Set the license file path here if you are using the Engine Subscription edition
//Evaluator.LicenseFileFullPath = "C:\\YourFolder\\codeeffects.ce";
public static void MapEndpoints(this WebApplication app)
{
// Returns client settings for the editor
app.MapGet("/api/settings", () =>
{
var settings = new Settings();
var editor = GetControl(settings);
// Set all evaluation type rules to be used by the
// editor as bool properties (i.e. reusable rules) in menus
editor.ContextMenuRules = [.. Storage
.Where(r => r.Value.Eval)
.Select(r => new MenuItem(r.Key, r.Value.Name))];
if(settings.Toolbar)
{
// Load all available rules into the Rules menu of the Toolbar
editor.ToolBarRules = [.. Storage.Select(r => new MenuItem(r.Key, r.Value.Name))];
}
// Set UI settings for the editor (Help String, etc)
settings.GlobalData = editor.GetGlobalData();
// Set the source-related settings for the editor
settings.EditorData = editor.GetEditorData();
return Results.Ok(settings);
});
// Loads a rule by its ID
app.MapGet("/api/load/{ruleId}", (string ruleId) =>
{
Storage.TryGetValue(ruleId, out var value);
var editor = GetControl(new Settings());
editor.LoadRuleXml(value?.Xml);
return Results.Ok(editor.GetRuleData());
});
app.MapPost("/api/save", ([FromBody] string rule) =>
{
var editor = GetControl(new Settings());
editor.LoadRuleData(rule);
var response = new Response();
if(editor.IsEmpty)
{
response.IsRuleEmpty = true;
}
else if(!editor.IsValid)
{
response.IsRuleValid = false;
// Load invalid elements into the editor
response.ClientInvalidData = editor.GetInvalidData();
}
else
{
Storage[editor.Rule.ID] = new Rule
{
Eval = editor.Rule.IsEvalType.HasValue && editor.Rule.IsEvalType.Value,
Name = editor.Rule.Name,
Xml = editor.GetRuleXml()
};
response.Output = editor.Rule.ID;
}
return Results.Ok(response);
});
app.MapPost("/api/delete", ([FromBody] string ruleId) =>
{
Storage.TryRemove(ruleId, out _);
});
app.MapPost("/api/evaluate", (Request req) =>
{
var editor = GetControl(new Settings());
editor.RuleNameIsRequired = false; // No need to validate the rule name
editor.LoadRuleData(req.Rule); // Load the rule into the editor
var response = new Response();
if(editor.IsEmpty)
{
response.IsRuleEmpty = true;
response.Output = "The rule is empty";
}
else if(!editor.IsValid)
{
response.IsRuleValid = false;
response.Output = "The rule is invalid";
// Load invalid rule elements into the editor
response.ClientInvalidData = editor.GetInvalidData();
}
else
{
// Get the rule XML
var ruleXml = editor.GetRuleXml();
// Create an instanve of the Evaluator.
// This compiles your rule into IL
var ev = new Evaluator<SourceObject>(ruleXml);
// Evaluate the rule
bool success = ev.Evaluate(req.Source);
// Output the evaluation result
response.Output = success ?
"The rule evaluated to TRUE" :
"The rule evaluated to FALSE";
response.Source = req.Source;
}
return Results.Ok(response);
});
}
private static Control GetControl(Settings settings)
{
// Use the ID of the div element that contains the editor
var editor = new Control("divEditor");
// Set the editor to use the source object
editor.SourceType = typeof(SourceObject);
editor.EvaluationMode = settings.Mode;
editor.ShowHelpString = settings.HelpString;
editor.ShowToolBar = settings.Toolbar;
editor.ShowLineDots = settings.Dots;
return editor;
}
}
public class SourceObject
{
public int Id { get; set; } = 0;
public string? Name { get; set; }
[Field(DisplayName = "Date of Birth", DateTimeFormat = "MMM dd, yyyy")]
public DateTime? Dob { get; set; }
}
public class Rule
{
public bool Eval { get; set; } = false;
public string? Name { set; get; }
public string? Xml { get; set; }
}
public class Settings
{
public string? GlobalData { get; set; }
public string? EditorData { get; set; }
public bool Toolbar { get; set; } = true;
public bool HelpString { get; set; } = true;
public bool Dots { get; set; } = false;
public EvaluationMode Mode { get; set; } = EvaluationMode.Execution;
}
public class Request
{
public string? Rule { get; set; }
public SourceObject Source { get; set; } = new SourceObject();
}
public class Response
{
public bool IsRuleEmpty { get; set; } = false;
public bool IsRuleValid { get; set; } = true;
public string? Output { get; set; }
public string? ClientInvalidData { get; set; }
public SourceObject Source { set; get; } = new SourceObject();
}