NVelocity (or Velocity) as a stand-alone formula evaluator - c#

I am using NVelocity in my application to generate html emails. My application has an event-driven model, where saving and/or updating of objects causes these emails to be sent out. Each event can trigger zero, one or multiple multiple emails.
I want to be able to configure which emails get sent out at run-time without having to modify code. I was thinking I could leverage the NVelocity #if() directive to do this. Here is my idea...
Step 1) Prior to email sending, the administrator must configure a formula for NVelocity to evaluate. For example:
$User.FirstName == "Jack"
Step 2) When an object is saved or created, build an NVelocity template in memory based on the input formula. For example:
String formula = GetFormulaFromDB(); // $User.FirstName == "Jack"
String templ = "#if( " + formula + ") 1 #else 0 #end";
Step 3) Execute the NVelocity engine in memory against the template. Check the results to see if we have to send the email:
String result = VelocityMerge(templ); // utility function
if( result.Trim() == "1" )
{
SendEmail();
}
I know this is not exactly what NVelocity was intended to do, but I think it just might work :) One of the benefits of doing things this way is that the same syntax can be used for the formula as is used inside the template.
Does anybody have any words of caution or suggestions? Is there a way to execute the #if() directive without jumping through hoops like I have above? Is there a recommended way to validate the formula syntax ahead of time?
Thanks.

If a non-technical end-user is the one that changes the criteria, I'd be very careful to validate his input. You could easily validate it by running the template (i.e. your VelocityMerge() method) against the input, if NVelocity complains you reject the input, otherwise save it to the database.
Another limitation is that you'd have to know upfront all the variables that can be present on the criteria, as serg555 commented. Some mail template might need a variable that no other mail needs, but still you'd have to make it available to all templates. Whether this is a real limitation or not depends on the homogeneity (?) of your mail templates.
Also the end-user that defines the criteria would have to know all available variables (e.g. $User) and the properties of each variable (e.g. FirstName, LastName, etc). Some help screen that lists them, perhaps.

Related

Is there a way to convert C# code to JSON

is there a way to convert C# code to any block representation and back?
Something like this:
int foo(int a){return a+1;}
to
{function:{name:"foo", return:"int", args:[{type:"int", name:"a"}], operations:[{type:"return", operations:[{type:"add", args:[{type:"vairable", value:"a"},{type:"const", value: 1}]}]}]}}
Does not have to be JSON, but I need it to be split to smallest parts.
UPDATE:
Lets say I generate a function that fills a structure based on a data from database:
public Person GetPerson(int id)
{
try { // <-- entire block added by user
using (var query = db.GetPerson(id))
{
return new Person(){
/*0*/name = query['name'], // /*#*/ is my mark of generated line
/*1*/age = query['age']
};
}
}
...
}
Assume that a user changed the line:
/*1*/age = query['age']
to /*1*/age = 10 - query['age'] for some reason.
Now the database column age is changed to years.
The new line should be /*1*/years = 10 - query['years']. The problem is that I need to keep the 10 - entered by the user.
If I had this code is JSON (or any graph) I could find the part that needs to be changed and only affect the nodes I genereated before keeping the excess.
This exmaple is trivial, but it can get complicated very quickly. Especially with quotes and brackets. This is the only approach I can see to work right now. Just hoped that tools for it already exists.
Is there a way to convert C# code to JSON
Sure. You can either make your json contain a string with your c# code and use runtime code generation to execute it, or encode dlls as base64 data and put it into your json. If you want to dig deeper you could probably extract the CIL code and make some custom JSON encoding of it. There are also expression trees, but I only think they allow encoding of expressions, not arbitrary code.
But in any case it is probably not a good idea to let the user customize code at that level. If you want to allow customization you should probably go for an actual plugin architecture. Or if you just want some customization of some simple mathematical expression, just store it as a string and write a simple parser to validate & evaluate it.

Read/Write array to a file

I need guidance, someone to point me in the right direction. As the tittle says, I need to save information to a file: Date, string, integer and an array of integers. And I also need to be able to access that information later, when an user wants to review it.
Optional: File is plain text and I can directly check it and it is understandable.
Bonus points if chosen method can be "easily" converted to working with a database in the future instead of individual files.
I'm pretty new to C# and what I've found so far is that I should turn the array into a string with separators.
So, what'd you guys suggest?
// JSON.Net
string json = JsonConvert.SerializeObject(objOrArray);
File.WriteAllText(path, json);
// (note: can also use File.Create etc if don't need the string in memory)
or...
using(var file = File.Create(path)) { // protobuf-net
Serializer.Serialize(file, objOrArray);
}
The first is readable; the second will be smaller. Both will cope fine with "Date, string, integer and an array of integers", or an array of such objects. Protobuf-net would require adding some attributes to help it, but really simple.
As for working with a database as columns... the array of integers is the glitch there, because most databases don't support "array of integers" as a column type. I'd say "separation of concerns" - have a separate model for DB persistence. If you are using the database purely to store documents, then: pretty much every DB will support CLOB and BLOB data, so either is usable. Many databases now have inbuilt JSON support (helper methods, etc), which might make JSON as a CLOB more tempting.
I would probably serialize this to json and save it somewhere. Json.Net is a very popular way.
The advantage of this is also creating a class that can be later used to work with an Object-Relational Mapper.
var userInfo = new UserInfoModel();
// write the data (overwrites)
using (var stream = new StreamWriter(#"path/to/your/file.json", append: false))
{
stream.Write(JsonConvert.SerializeObject(userInfo));
}
//read the data
using (var stream = new StreamReader(#"path/to/your/file.json"))
{
userInfo = JsonConvert.DeserializeObject<UserInfoModel>(stream.ReadToEnd());
}
public class UserInfoModel
{
public DateTime Date { get; set; }
// etc.
}
for the Plaintext File you're right.
Use 1 Line for each Entry:
Date
string
Integer
Array of Integer
If you read the File in your code you can easily seperate them by reading line to line.
Make a string with a specific Seperator out of the Array:
[1,2,3] -> "1,2,3"
When you read the line you can Split the String by "," and gets a Array of Strings. Parse each Entry to int into an Array of Int with the same length.
How to read and write the File get a look at Easiest way to read from and write to files
If you really wants the switch to a database at a point, try a JSON Format for your File. It is easy to handle and there are some good Plugins to work with.
Mfg
Henne
The way I got started with C# is via the game Space Engineers from the Steam Platform, the Mods need to save a file Locally (%AppData%\Local\Temp\SpaceEngineers\ or %AppData%\Roaming\SpaceEngineers\Storage\) for various settings, and their logging is similar to what #H. Sandberg mentioned (line by line, perhaps a separator to parse with later), the upside to this is that it's easy to retrieve, easy to append, easy to overwrite, and I'm pretty sure it's even possible to retrieve File Size, which when combined with File Deletion and File Creation can prevent runaway File Sizes as this allows you to set an Upper Limit to check against, allowing you to run it on a Server with minimal impact (probably best to include a minimum Date filter {make sure X is at least Y days old before deleting it for being over Z Bytes} to prevent Debugging Data Loss {"Why was it over that limit?"})
As far as the actual Code behind the idea, I'm approximately at the same Skill Level as the OP, which is to say; Rookie, but I would advise looking at the Coding in the Space Engineers Mods for some Samples (plus it's not half bad for a Beta Game), as they are almost all written in C#. Also, the Programmable Blocks compile in C# as well, so you'll be able to use that to both assist in learning C# and reinforce and utilize what you already know (although certain C# commands aren't allowed for security reasons, utilizing the Mod API you'll have more flexibility to do things such as Creating/Maintaining Log Files, Retrieving/Modifying Object Properties, etc.), You are even capable of printing Text to various in Game Text Monitors.
I apologise if my Syntax needs some work, and I'm sorry I am not currently capable of just whipping up some Code to solve your issue, but I do know
using System;
Console.WriteLine("Hello World");
so at least it's not a total loss, but my example Code likely won't compile, since it's likely missing things like: an Output Location, perhaps an API reference or two, and probably a few other settings. Like I said, I'm New, but that is a valid C# Command, I know I got that part correct.
Edit: here's a better attempt:
using System;
class Test
{
static void Main()
{
string a = "Hello Hal, ";
string b = "Please open the Airlock Doors.";
string c = "I'm sorry Dave, "
string d = "I'm afraid I can't do that."
Console.WriteLine(a + b);
Console.WriteLine(c + d);
Console.Read();
}
}
This:
"Hello Hal, Please open the Airlock Doors."
"I'm sorry Dave, I'm afraid I can't do that."
Should be the result. (the "Quotation Marks" shouldn't appear in the readout {the last Code Block}, that's simply to improve readability)

How to centrally maintain a mathematical formula in C# (web) so it can be changed if needed?

We have an application that has a LOT of mathematical checks on the page and according to it, the user is given a traffic light (Red, green, yellow).
Green = He may continue
Red = Dont let him continue
Yellow = Allow to continue but warn
These formulas operate on the various text-fields on the page. So, for example, if textbox1 has "10" and texbox2 has "30"... The formula might be:
T1 * T2 > 600 ? "GREEN" : "RED"
My question is:
Is it possible to somehow centralize these formulas?
Why do I need it?
Right now, if there is any change in a formula, we have to replicate the change at server-side as well (violation of DRY, difficult to maintain code)
One option could be to
- store the (simple) formula as text with placeholders in a config(?)
- replace the placeholders with values in javascript as well as server-side code
- use eval() for computation in JS
- use tricks outlined here for C#
In this approach issue could be different interpretations of same mathematical string in JS and C#.
Am i making sense or should this question be reported?!! :P
Depending on your application's requirements, it may be acceptable to just do all the validation on the server. Particularly if you have few users or most of them are on a reasonably fast intranet, you can "waste" some network calls to save yourself a maintenance headache.
If the user wants feedback between every field entry (or every few entries, or every few seconds), you could use an AJAX call to ask the server for validation without a full page refresh.
This will, of course result in more requests than doing the validation entirely on the client, and if many of your users have bad network connections there could be latency in giving them the feedback. My guess is the total bandwidth usage is about the same. You use some for every validation round-trip, but those are small. It may be outweighed by all that validation JS that you're not going to send to clients.
The main benefit is the maintenance and FUD that you'd otherwise have keeping the client and server validation in sync. There's also the time savings in never having to write the validation javascript.
In any case, it may be worth taking a step back and asking what your requirements are.
The Microsoft.CSharp.CSharpCodeProvider provider can compile code on-the-fly. In particular, see CompileAssemblyFromFile.
This would allow you to execute code at runtime from a web.config for instance; however use with caution.
You could write C# classes to model your expressions with classes such as Expression, Value, BooleanExpr, etc. (an Abstract Syntax Tree)
e.g.
Expression resultExpression = new ValueOf("T1").Times(new ValueOf("T2")).GreaterThan(600).IfElse("RED","GREEN")
^Variable ^Variable ^Value=>BoolExpr ^(Value, Value) => Value
These expressions could then be used to evaluation in C# AND to emit Java script for the checks:
String result = resultExpression.bind("T1", 10).bind("T2",20).evaluate() //returns "RED"
String jsExpression resultExpression.toJavaScript // emits T1 * T2 > 600 ? "RED" : "GREEN"
You can make a low level calculator class that uses strings as input and pushes and pops things onto a stack. Look up a "Reverse Polish Calculator". If the number of inputs you are using doesn't change this would be a pretty slick way to store your equations. You would be able to store them in a text file or in a config file very easily.
for instance:
string Equation = "V1,V2,+";
string ParseThis = Equation.Replace("V1", "34").Replace("V2", "45");
foreach(string s in ParseThis.split(',')) {
if (s == "+") {
val1 = stack.Pop();
val2 = stack.Pop();
return int.parse(val1) + int.Parse(val2);
}
else {
stack.Push(s);
}
}
obviously this gets more complicated with different equations but it could allow you to store your equations as strings anywhere you want.
apologies if any of the syntax is incorrect but this should get you going in the right direction.
The simplest solution would be to implement the formulae once in C# server-side, and use AJAX to evaluate the expressions from the client when changes are made. This might slow down the page.
If you want the formulae evaluated client-side and server-side but written only once, then I think you will need to do something like:
Pull the formulae out into a separate class
For the client-side:
Compile the class to Javascript
Call into the javascript version, passing in the values from the DOM
Update the DOM using the results of the formulae
For the server-side:
Call into the formulae class, passing in the values from the form data (or controls if this is web-forms)
Take the necessary actions using the results of the formulae
.. or you could do the converse, and write the formulae in Javascript, and use a C# Javascript engine to evaluate that code server-side.
I wouldn't spend time writing a custom expression language, or writing code to translate C# to Javascript, as suggested by some of the other answers. As shown in the questions I linked to, these already exist. This is a distraction from your business problem. I would find an existing solution which fits and benefit from someone else's work.

Better method of handling/reading these files (HCFA medical claim form)

I'm looking for some suggestions on better approaches to handling a scenario with reading a file in C#; the specific scenario is something that most people wouldn't be familiar with unless you are involved in health care, so I'm going to give a quick explanation first.
I work for a health plan, and we receive claims from doctors in several ways (EDI, paper, etc.). The paper form for standard medical claims is the "HCFA" or "CMS 1500" form. Some of our contracted doctors use software that allows their claims to be generated and saved in a HCFA "layout", but in a text file (so, you could think of it like being the paper form, but without the background/boxes/etc). I've attached an image of a dummy claim file that shows what this would look like.
The claim information is currently extracted from the text files and converted to XML. The whole process works ok, but I'd like to make it better and easier to maintain. There is one major challenge that applies to the scenario: each doctor's office may submit these text files to us in slightly different layouts. Meaning, Doctor A might have the patient's name on line 10, starting at character 3, while Doctor B might send a file where the name starts on line 11 at character 4, and so on. Yes, what we should be doing is enforcing a standard layout that must be adhered to by any doctors that wish to submit in this manner. However, management said that we (the developers) had to handle the different possibilities ourselves and that we may not ask them to do anything special, as they want to maintain good relationships.
Currently, there is a "mapping table" set up with one row for each different doctor's office. The table has columns for each field (e.g. patient name, Member ID number, date of birth etc). Each of these gets a value based on the first file that we received from the doctor (we manually set up the map). So, the column PATIENT_NAME might be defined in the mapping table as "10,3,25" meaning that the name starts on line 10, at character 3, and can be up to 25 characters long. This has been a painful process, both in terms of (a) creating the map for each doctor - it is tedious, and (b) maintainability, as they sometimes suddenly change their layout and then we have to remap the whole thing for that doctor.
The file is read in, line by line, and each line added to a
List<string>
Once this is done, we do the following, where we get the map data and read through the list of file lines and get the field values (recall that each mapped field is a value like "10,3,25" (without the quotes)):
ClaimMap M = ClaimMap.GetMapForDoctor(17);
List<HCFA_Claim> ClaimSet = new List<HCFA_Claim>();
foreach (List<string> cl in Claims) //Claims is List<List<string>>, where we have a List<string> for each claim in the text file (it can have more than one, and the file is split up into separate claims earlier in the process)
{
HCFA_Claim c = new HCFA_Claim();
c.Patient = new Patient();
c.Patient.FullName = cl[Int32.Parse(M.Name.Split(',')[0]) - 1].Substring(Int32.Parse(M.Name.Split(',')[1]) - 1, Int32.Parse(M.Name.Split(',')[2])).Trim();
//...and so on...
ClaimSet.Add(c);
}
Sorry this is so long...but I felt that some background/explanation was necessary. Are there any better/more creative ways of doing something like this?
Given the lack of standardization, I think your current solution although not ideal may be the best you can do. Given this situation, I would at least isolate concerns e.g. file read, file parsing, file conversion to standard xml, mapping table access etc. to simple components employing obvious patterns e.g. DI, strategies, factories, repositories etc. where needed to decouple the system from the underlying dependency on the mapping table and current parsing algorithms.
You need to work on the DRY (Don't Repeat Yourself) principle by separating concerns.
For example, the code you posted appears to have an explicit knowledge of:
how to parse the claim map, and
how to use the claim map to parse a list of claims.
So there are at least two responsibilities directly relegated to this one method. I'd recommend changing your ClaimMap class to be more representative of what it's actually supposed to represent:
public class ClaimMap
{
public ClaimMapField Name{get;set;}
...
}
public class ClaimMapField
{
public int StartingLine{get;set;}
// I would have the parser subtract one when creating this, to make it 0-based.
public int StartingCharacter{get;set;}
public int MaxLength{get;set;}
}
Note that the ClaimMapField represents in code what you spent considerable time explaining in English. This reduces the need for lengthy documentation. Now all the M.Name.Split calls can actually be consolidated into a single method that knows how to create ClaimMapFields out of the original text file. If you ever need to change the way your ClaimMaps are represented in the text file, you only have to change one point in code.
Now your code could look more like this:
c.Patient.FullName = cl[map.Name.StartingLine].Substring(map.Name.StartingCharacter, map.Name.MaxLength).Trim();
c.Patient.Address = cl[map.Address.StartingLine].Substring(map.Address.StartingCharacter, map.Address.MaxLength).Trim();
...
But wait, there's more! Any time you see repetition in your code, that's a code smell. Why not extract out a method here:
public string ParseMapField(ClaimMapField field, List<string> claim)
{
return claim[field.StartingLine].Substring(field.StartingCharacter, field.MaxLength).Trim();
}
Now your code can look more like this:
HCFA_Claim c = new HCFA_Claim
{
Patient = new Patient
{
FullName = ParseMapField(map.Name, cl),
Address = ParseMapField(map.Address, cl),
}
};
By breaking the code up into smaller logical pieces, you can see how each piece becomes very easy to understand and validate visually. You greatly reduce the risk of copy/paste errors, and when there is a bug or a new requirement, you typically only have to change one place in code instead of every line.
If you are only getting unstructured text, you have to parse it. If the text content changes you have to fix your parser. There's no way around this. You could probably find a 3rd party application to do some kind of visual parsing where you highlight the string of text you want and it does all the substring'ing for you but still unstructured text == parsing == fragile. A visual parser would at least make it easier to see mistakes/changed layouts and fix them.
As for parsing it yourself, I'm not sure about the line-by-line approach. What if something you're looking for spans multiple lines? You could bring the whole thing in a single string and use IndexOf to substring that with different indices for each piece of data you're looking for.
You could always use RegEx instead of Substring if you know how to do that.
While the basic approach your taking seems appropriate for your situation, there are definitely ways you could clean up the code to make it easier to read and maintain. By separating out the functionality that you're doing all within your main loop, you could change this:
c.Patient.FullName = cl[Int32.Parse(M.Name.Split(',')[0]) - 1].Substring(Int32.Parse(M.Name.Split(',')[1]) - 1, Int32.Parse(M.Name.Split(',')[2])).Trim();
to something like this:
var parser = new FormParser(cl, M);
c.PatientFullName = FormParser.GetName();
c.PatientAddress = FormParser.GetAddress();
// etc
So, in your new class, FormParser, you pass the List that represents your form and the claim map for the provider into the constructor. You then have a getter for each property on the form. Inside that getter, you perform your parsing/substring logic like you're doing now. Like I said, you're not really changing the method by which your doing it, but it certainly would be easier to read and maintain and might reduce your overall stress level.

Custom .Net library or existing library to handle sequence formatting?

I am thinking a library already exists for this, but I need allow my users to create a numbering format for their documents.
For example, let's say we have an RFI from and the user has a specific format the numbering sequence needs to be in. A typical RFI number looks like this for their system: R0000100. The next RFI in line would be R0000101.
Before I set out to creating a formatting engine for numbers such as these, does something already exist that can accommodate this?
Update:
I failed to save the edit to this question. Anyway, I also want to give the users the ability to create their own formats. So, I may have a form where they can input the format: R####### And also allow them to specify the starting integer: in the case 100. Also, I may want to allow them to specify how they want to increment. maybe only by 100s. So the next number may be R0000200. I know this may sound ridiculous, but you never know. That is why I asked if something like this already exists.
If you keep value and format separated, you won't need a library or such a thing.
The numbers would be simple, say, integers i, i.e. 100, 101, 102, that you manage/store however you see fit. The formatting part would simply be a matter of R + i.ToString("0000000"), or if you want to have the format as a string literal string.Format("R{0:0000000}", i).
I know, this might only be an example, but as your question stands, the formatting options, that .NET provides out of the box seem to suffice.
The incrementing of identity field values is most often handled in an RDBMS-style database. This comes with a few benefits, such as built-in concurrency handling. If you want to generate the values yourself, a simple class to get the last-issued value and increment by one would be very easy to create. Make it thread-safe so you don't get any duplicates or gaps and you'll be good to go.

Categories