Introduction
Some time ago, I worked on an application which had a unique framework design. It was, at the core, an order management system where users could create orders, add order details, change order details, and generally do anything you would want a good shopping cart to do. The framework itself handled the usual business logic of adding to an order, totaling the order, checking to see if the item exists, or any other crucial order function. The unique part came from the need to allow different implementations to perform their own business logic before or after performing these tasks. Sometimes you'd want to override the descriptions created in the database or modify the quantities if certain conditions were met. In order to do these kinds of things, a developer would have to write a windows .dll that implemented these calls. It was cumbersome and often error-prone to write these .dlls. Furthermore, outside developers had to have very intimate knowledge of the framework before diving in. We needed a way for a developer to pass her or his business logic code to the framework (now a web service) that would get executed at a certain time.
As you know, you can't really pass business logic to a web service. Once you send it off, you have to wait for it to come back in order to change and resend data. After reading this article, I got the idea to use Jscript.NET's eval
function to accomplish the task that external libraries would. With the eval
function, it is possible to send text to a web service and then execute that text as though it were code. So I set out to write a Jscript.NET web service that would leverage the power of dynamic code execution.
Using the code
Consider the following example:
WebMethodAttribute public function InsertOrderDetail(
productId : int, quantity : int,
onAfterOrderDetailInsert : String) : OrderDetail
{
var orderDetail : OrderDetail = new OrderDetail(productId, quantity);
eval(onAfterOrderDetailInsert);
return orderDetail;
}
In this web method, an order is created and then some code is executed which can change the quantity, description, or pretty much anything you would want to do to an order. I then took it one step further and actually created a method to encapsulate this process:
private function OnAfterOrderDetailInsert(
code : String, Inserted : OrderDetail)
{
eval(code);
}
Because of security concerns, you would want to limit what a user can do in their eval
. Encapsulating it abstracts it a bit and imposes limits to only update an order detail object. Also, since I did not specify a value for the security level parameter, eval
doesn't have access to the network or file system. By no means does this relieve us of all security concerns, code can still mess things up. So now the previous code becomes:
WebMethodAttribute public function InsertOrderDetail(productId : int,
quantity : int, onAfterOrderDetailInsert : String) : OrderDetail
{
var orderDetail : OrderDetail = new OrderDetail(productId, quantity);
OnAfterOrderDetailInsert(onAfterOrderDetailInsert, orderDetail);
return orderDetail;
}
To conclude this method and use the eval
, its as simple as this:
protected void InsertOrderDetail_Click(object sender, EventArgs e)
{
string onOrderDetailInsert = @"" +
"if(Inserted.QuantityAvailable < 20)\n" +
"{\n" +
" Inserted.Description += ' ON SALE!!!';\n" +
"}";
OrderManagement.OrderService orderService =
new miscellaneous.JScriptEvalExample.WebSite.OrderManagement.OrderService();
OrderManagement.OrderDetail orderDetail =
orderService.InsertOrderDetail(
ProductID, Quantity, onOrderDetailInsert);
}
This modifies the order detail's description based upon the quantity available.
Conclusion
Eval code truly comes in handy when we have access to variables, properties, and methods that the web service does not expose. Let's say that, before you insert an order detail, you need to check an item's availabilty. Before, you would have to call the web service 2 times: once to get the availabilty and the again to add the item. Using the eval, you save that last step.
Therefore it is aparent that when used correctly and safely, eval functionality can really give web service consumers freedom. It can allow them to infiltrate the process at specified points and transmit their own business logic using SOAP calls. Furthermore, it can help combine steps to remove the need for multiple calls to the web service. I have attached all of the example code with the Jscript.NET web service and referenced the example website.
History
- 18 May, 2007 - Original version posted