Thursday, March 20, 2014

A Dynamic ASP.NET MVC Controller using CSScript

At my day job, we are working on a large enterprise system.  One of the feature areas of this product is an array of different charts of performance metrics.  All of these charts accept a common set of parameters, and generate some json that is used by our client side to render a chart for the requested metric.

At the moment, we are using a standard MVC controller to define the actions necessary to calculate and collate these stats.  The other day, we were kicking around the idea of how we would be able to add new charts in for a client, after they already have the product installed.  With the current design we are using, there isn’t really an easy way to do that without dropping in the updated build that has the updated controller.  That’s not really an ideal situation, since reinstalling and reconfiguring the application is kind of a heavy-handed approach when all we want to do is add a couple of new charts in, without impacting the rest of the application.  It also doesn’t give us many options if our customer, for whatever reason, wants to disable certain charts.

Probably, what we’ll end up doing, is using the database to define the chart calculation SQL, either using by storing the SQL statements to retrieve the metrics in a table, or via stored procedures.  I’ll admit, I’m not crazy about this approach, since I’ve worked on a couple of other products that used this method, and I have some slight PTSD from trying to troubleshoot convoluted SQL that was poorly written and not checked into source control other than in the master database creation script.  With a sane process, this will probably be an effective option; one of the reasons we are likely going to need to go this route is that we are developing parallel .NET and Java versions, due to API restrictions of the underlying technology stacks that we are targeting, while trying to use a common UI and database.

This did get me thinking about how it would be possible to dynamically populate the actions of an MVC controller.  I had come across some posts on CSScript, which is a library which allows you to run arbitrary C# code interpretively.  Depending on how you use it, you can load up entire classes, methods or even statements, and invoke them at run-time, without the script code being compiled and embedded in your .dll.  So, theoretically, it should be possible to define the controller action that calculates the metrics for a given chart in a CSScript file, load that up, execute it using the CSScript interpreter, passing any parameters needed in, and return the results.

The other piece of this is figuring out how to get an MVC controller to accept action routes that are not explicitly defined for it.  Fortunately, with the latest version of MVC, you are able to tweak the default behavior of the controller to a considerable degree, if you are willing to delve into overriding some of the virtual methods the the Controller class gives you access to.  So, after a little digging, I was able to figure out a slightly crazy way to wrestle MVC into doing what I wanted it to do – accepting dynamic controller actions, executing a scripted action, and then returning the result to the webpage.

This is a very quick and dirty example, really just a proof of concept prototype, so I make no promises as to its performance or robustness.  But, it was cool to figure out that such a thing was possible, and I figured that I would share it as a jumping-off point in case anyone else encounters a similar crazy requirement.  The code is available on my GitHub repository, at https://github.com/ericrrichards/MVCScriptedController.git.

As a simple example, let’s assume that we know that we are going to have to support controller actions with a signature like this:

ActionResult Action( string i )

An example implementation of an action like this would look like this (from Scripts/Reports/Foo.cs in the project):

public ActionResult Foo(string i) {
return new JsonResult() {
Data = "Foo - " + i,
JsonRequestBehavior = JsonRequestBehavior.AllowGet
};
}

We’ll start with an empty MVC5 project, and then add a new empty Controller to the project.  Deleting the auto-generated Index action, that leaves us with this:

using System.Web.Mvc;

namespace ScriptedController.Controllers {
public class ReportController : Controller {

}
}

The Controller class offers us a virtual method, void HandleUnknownAction(string actionName), which is fired when a request is routed to the controller and the requested action does not match any of the defined controller actions.  By default, this method just throws an HTTPException with a 404 error code.  Interestingly enough, there must be something else in the Controller class which catches this error, because if you were to actually hit a non-existent controller action without overriding HandleUnknownAction, you’ll get a 200 response with no content.  However, we can override this method to allow us to do something else, which in our case will be to look for a dynamically loaded action method delegate and execute that instead.


To support this, we are going to add a delegate to match the action signature that we are expecting, and a dictionary to map action names to these delegates to our controller. We’ll make this dictionary static, so that it can be shared between all instances of the controller that we are creating – this will save us some time on each request, since MVC creates a new Controller instance for each incoming request, so that we would otherwise need to load up our dynamic Actions for every request. 

private volatile static Dictionary<string, MvcAction> _actions;
private delegate ActionResult MvcAction(string i);

We can now overload the HandleUnknownAction method, so that it checks this dictionary for an action which matches the passed actionName.  If the action is found, we will execute it, and write the result to the http response, using the ActionResult.ExecuteResult() method.  Otherwise, we will attempt to invoke the base HandleUnknownAction method.  For whatever reason, when we do this, the resulting exception is not caught, so we need to handle that and set the response code to 404.

protected override void HandleUnknownAction(string actionName) {
if (_actions.ContainsKey(actionName)) {
_actions[actionName](HttpContext.Request.Params["i"]).ExecuteResult(ControllerContext);
} else {
try {
base.HandleUnknownAction(actionName);
} catch (Exception ex) {
HttpContext.Response.StatusCode = 404;
}
}
}

Getting the parameters to the action is somewhat hacky.  We can access any of the parameters passed along with the HTTP request by using the HTTPContext.Request.Params dictionary.  In this situation, where we know that all of the dynamic actions for this controller will share a common set of parameters, we can hard-code the parameters that we extract – at the moment, I’m not totally sure how I would handle a more general case, so that bears some thought.


At this point, we have a controller that can handle actions requested of it that are not defined explicitly in the class, assuming that they are contained in its dictionary of dynamic actions.  The next step is figuring out how to populate that dictionary with the dynamic actions.  For that, we need to use CSScript.  We are going to add another method to our controller, named EnsureActionsLoaded(), which will handle this for us. 


What this method will do, is check whether the actions dictionary has already been loaded, and if not, load the actions from a directory which contains a series of script files, where each file contains a single action method, with the filename matching the action name.  We’ll use CSScript to dynamically load each method as a delegate, which we can then push into our dictionary. 

private void EnsureActionsLoaded() {
if (_actions != null) {
return;
}
lock (SyncRoot) {
if (_actions == null) {
_actions = new Dictionary<string, MvcAction>();
var path = Server.MapPath(ScriptsDirectory);

foreach (var file in Directory.GetFiles(path)) {
try {
var action = CSScript.Evaluator.LoadDelegate<MvcAction>(System.IO.File.ReadAllText(file));
var actionName = Path.GetFileNameWithoutExtension(file);
if (!string.IsNullOrEmpty(actionName)) {
_actions[actionName] = action;
}
} catch (Exception ex) {
Console.WriteLine(ex.Message);
}
}
}
}
}

If you have dealt with the singleton pattern in C#, you may have noticed that we are using a similar double-check locking method to determine if the action dictionary has already been loaded.  Since the dictionary is static, and because of the multi-threaded nature of web applications, it is possible that two or more simultaneous requests will arrive at once, and if both attempt to load the actions dictionary at the same time, they have the potential to stomp on each other.


Since we are using the Server.MapPath() function to determine the location of our script directory, we need to also override the Initialize() method of the controller to call our EnsureActionsLoaded method.  Ideally, we could do this in the constructor, but at that point, the Server variable is not yet initialized.

protected override void Initialize(RequestContext requestContext) {
base.Initialize(requestContext);
EnsureActionsLoaded();
}

At this point, we have a working controller which can load CSScript files as controller actions, and execute them.  There are a couple of simple examples of these scripts in the Scripts/Report folder of the project, like the following Fizz.cs:

using System.Web.Mvc;
public ActionResult Fizz(string i) {
return new JsonResult() {
Data = "Fizz - " + i,
JsonRequestBehavior = JsonRequestBehavior.AllowGet
};
}

One thing to note is that you will either need to use fully-qualified type names in your scripts, or else include the necessary using statements for CSScript to properly parse and compile your scripts.  I haven’t tried anything more complicated yet using assemblies that are not referenced in the project itself, so be aware that there may be some gotchas there.


Altogether, our dynamic controller looks like this:

using System;
using System.Collections.Generic;
using System.Web.Mvc;
using System.IO;

namespace ScriptedController.Controllers {
using System.Web.Routing;

using CSScriptLibrary;

public class ReportController : Controller {
private const string ScriptsDirectory = "~/Scripts/Reports";

private static readonly object SyncRoot = new object();
private volatile static Dictionary<string, MvcAction> _actions;
private delegate ActionResult MvcAction(string i);

protected override void Initialize(RequestContext requestContext) {
base.Initialize(requestContext);
EnsureActionsLoaded();
}

private void EnsureActionsLoaded() {
if (_actions != null) {
return;
}
lock (SyncRoot) {
if (_actions == null) {
_actions = new Dictionary<string, MvcAction>();
var path = Server.MapPath(ScriptsDirectory);

foreach (var file in Directory.GetFiles(path)) {
try {
var action = CSScript.Evaluator.LoadDelegate<MvcAction>(System.IO.File.ReadAllText(file));
var actionName = Path.GetFileNameWithoutExtension(file);
if (!string.IsNullOrEmpty(actionName)) {
_actions[actionName] = action;
}
} catch (Exception ex) {
Console.WriteLine(ex.Message);
}
}
}
}
}

protected override void HandleUnknownAction(string actionName) {
if (_actions.ContainsKey(actionName)) {
_actions[actionName](HttpContext.Request.Params["i"]).ExecuteResult(ControllerContext);
} else {
try {
base.HandleUnknownAction(actionName);
} catch (Exception ex) {
HttpContext.Response.StatusCode = 404;
}
}
}
}
}

If you run the project, you should be able to hit both /Report/Foo and /Report/Fizz, and see results like the below:


image


image


Attempting to hit an unregistered controller action will give you the lovely ASP.NET 404 error page:


image




I’m not sure if I will ever get a chance to actually use this, but it was a fun little experiment.  Hopefully if any of you find yourself with a similar problem, this will give you a starting point to work from.

Wednesday, February 5, 2014

Rendering Text using SlimDX SpriteTextRenderer

Howdy.  Today, I’m going to discuss rendering UI text using the SlimDX SpriteTextRenderer library.  This is a very nifty and light-weight extension library for SlimDX, hosted on CodePlex.  In older versions of DirectX, it used to be possible to easily render sprites and text using the ID3DXSprite and ID3DXFont interfaces, but those have been removed in newer versions of DirectX.  I’ve experimented with some other approaches, such as using Direct2D and DirectWrite or the DirectX Toolkit, but wasn’t happy with the results.  For whatever reason, Direct2D doesn’t interop well with DirectX 11, unless you create a shared DirectX 10 device and jump through a bunch of hoops, and even then it is kind of a PITA.  Likewise, I have yet to find C# bindings for the DirectX Toolkit, so that’s kind of a non-starter for me; I’d either have to rewrite the pieces that I want to use with SlimDX, or figure out the marshaling to use the C++ dlls.  So for that reason, the SpriteTextRenderer library seems to be my best option at the moment, and it turned out to be relatively simple to integrate into my application framework.

If you’ve used either the old DirectX 9 interfaces or XNA, then it’ll be pretty intuitive how to use SpriteTextRenderer.  The SpriteRenderer class has some useful methods to draw 2D sprites, which I haven’t explored much yet, since I have already added code to draw scree-space quads.  The TextBlockRenderer class provides some simple and handy methods to draw text up on the screen.  Internally, it uses DirectWrite to generate sprite font textures at runtime, so you can use any installed system fonts, and specify the weight, style, and point size easily, without worrying about the nitty gritty details of creating the font.

One limitation of the TextBlockRenderer class is that you can only use an instance of it to render text with a single font.  Thus, if you want to use different font sizes or styles, you need to create different instances for each font that you want to use.  Because of this, I’ve written a simple manager class, which I’m calling FontCache, which will provide a central point to store all the fonts that are used, as well as a default font if you just want to throw some text up onto the screen.

The new code for rendering text has been added to my pathfinding demo, available at my GitHub repository, https://github.com/ericrrichards/dx11.git.

font

Sunday, February 2, 2014

IBM Connect 2014

Yikes!  It’s been more than two weeks since my last post…  It’s been a busy two weeks, as my employer has been gearing up for and attending IBM’s Connect 2014 conference in Orlando.  So I’ve had less time than usual to work on my side projects here.  Because of that, I’m going to go outside of my usual format, and recap the conference and some thoughts on it.  These are my personal opinions, so bear in mind the old adage about the ubiquity and quality of opinions…

1545900_10153775947190296_46999126_n

Saturday, January 18, 2014

Simple Particle Physics

As I mentioned last time, I’m going to move on from fiddling with my Terrain class for a little while, and start working on some physics code instead.  I bought a copy of Ian Millington’s Game Physics Engine Development some months ago and skimmed through it, but was too busy with other things to really get into the accompanying source code.  Now, I do have some free cycles, so I’m planning on working through the examples from the book as my next set of posts.

Once again, the original source code is in C++, rather than C# as I’ll be using.  Millington’s code also uses OpenGL and GLUT, rather than DirectX.  Consequently, these aren’t going to be such straight ports like I did with most of Frank Luna’s examples; I’ll be porting the core physics code, and then for the examples, I’m just going to have to make something up that showcases the same features.

In any case, we’ll start off with the simple particle physics of Chapters 3 & 4, and build a demo that simulates the ballistics of firing some different types of projectiles.  You can find my source for this example on my GitHub page, at https://github.com/ericrrichards/dx11.git.

Here you can see the four projectile types: 1.) a pistol-type round, 2.) a large artillery shell, 3) a fireball, 4.) a bolt from a railgun or energy weapon

Saturday, January 11, 2014

Pathfinding III: Putting it All Together

Watch the intrepid red blob wind its way through the mountain slopes!

Last time, we discussed the implementation of our A* pathfinding algorithm, as well as some commonly used heuristics for A*.  Now we’re going to put all of the pieces together and get a working example to showcase this pathfinding work.

We’ll need to slightly rework our mouse picking code to return the tile in our map that was hit, rather than just the bounding box center.  To do this, we’re going to need to modify our QuadTree, so that the leaf nodes are tagged with the MapTile that their bounding boxes enclose.

We’ll also revisit the function that calculates which portions of the map are connected, as the original method in Part 1 was horribly inefficient on some maps.  Instead, we’ll use a different method, which uses a series of depth-first searches to calculate the connected sets of MapTiles in the map.  This method is much faster, particularly on maps that have more disconnected sets of tiles.

We’ll also need to develop a simple class to represent our unit, which will allow it to update and render itself, as well as maintain pathfinding information.  The unit class implementation used here is based in part on material presented in Chapter 9 of Carl Granberg’s Programming an RTS Game with Direct3D.

Finally, we’ll add an additional texture map to our rendering shader, which will draw impassible terrain using a special texture, so that we can easily see the obstacles that our unit will be navigating around.  You can see this in the video above; the impassible areas are shown with a slightly darker texture, with dark rifts.

The full code for this example can be found on my GitHub repository, https://github.com/ericrrichards/dx11.git, under the 33-Pathfinding project.