Shrink-wrapped Mkay

If you’ve been following this blog, you’ll know that there is no point in writing your own custom validation attributes for ASP.NET MVC data validation any more. Instead, you should be using Mkay, which allows you to specify arbitrary validation rules for your models in a LISP-like syntax. And now you can actually do it too, since I’ve packaged everything nicely in a nuget package.

When you install the nuget package in your ASP.NET MVC Application, you’ll find that a few things are added. First, there’s a reference to Mkay.dll, which contains the Mkay attribute as well as the code that is executed on the server. Second, in your Scripts folder, you’ll find three JavaScript files: mkay-validation.js (which contains the runtime for the client-side validation in mkay), mkay-parser.js (which is there to support the implementation of eval) and mkay-jquery.js (which hooks up the mkay runtime with unobtrusive jQuery validation). Third, there’s a code file in the App_Start folder called MkayBoot.cs. You may recall that the Mkay attribute must be associated with its own data validator class, in order to obtain the name of the property being validated. This happens inside the Kick method in the MkayBoot class. That method is invoked by means of WebActivator voodoo some time right after Application_Start in global.asax has been invoked. That way, you don’t have to bother with that yourself. For convenience, the Kick method also creates a so-called bundle of the Mkay JavaScript files.

Of course, you must remember to reference the Mkay JavaScript bundle in your view somehow, as well as the jQuery validation bundle. You might want to add them to the layout used by your view, for instance. Here’s an example:


<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width" />
<title>@ViewBag.Title</title>
@Styles.Render("~/Content/css")
@Scripts.Render("~/bundles/modernizr")
@Scripts.Render("~/bundles/jquery")
@Scripts.Render("~/bundles/jqueryval")
@Scripts.Render("~/bundles/mkay")
</head>
<body>
@RenderBody()
@RenderSection("scripts", required: false)
</body>
</html>

view raw

_Layout.cshtml

hosted with ❤ by GitHub

And then you can start using Mkay for your own validation needs. Wee! World domination!


Self-referential validation in Mkay

…so I implemented eval for Mkay. That sentence doesn’t have a first half, because I couldn’t think of any good reasons for doing so. I happen to think that’s a perfectly valid reason in and by itself, but I fear that’s a minority stance. But it doesn’t really matter. The second half of the sentence is true in any case. I implemented eval for Mkay.

It might be unclear to you exactly what I mean by that, though. What I mean is that Mkay now has a function (called eval) that you can call inside an Mkay expression. That function will take another Mkay expression as a string parameter and produce a boolean result when called. That result will then be used within the original Mkay expression. Still opaque? A concrete example should make it entirely transparent.

public class Guardian
{
public string Rule { get; set; }
[Mkay("eval Rule")]
public string Value { get; set; }
}
view raw Guardian.cs hosted with ❤ by GitHub

So here we have a model that uses eval inside an Mkay expression. How does it work in practice? Have a look:

So what happens in the video is that the rule “(eval Rule)” that annotates the Value property says that you should take the content of the Rule property and interpret that as the rule that the Value property must adher to. It’s sort of like SQL injection, only for Mkay. Isn’t that nice?

The string passed to eval could of course be gleaned from several sources, not just a single property. For instance, the rule “(eval (+ “and ” A ” ” B))” creates and evaluates a validation rule by combining the string “and ” with the value of property A, a space, and the value of property B.

public class Composed
{
public string A { get; set; }
public string B { get; set; }
[Mkay("eval (+ \"and \" A \" \" B)")]
public string Value { get; set; }
}
view raw Composed.cs hosted with ❤ by GitHub

It’s even more amusing if you go all self-referential and Douglas Hofstadter-like, and have the value and the rule be one and the same thing. To accomplish that, all you have to do is annotate your property with “(eval .)”.

public class Self
{
[Mkay("eval .")]
public string Me { get; set; }
[Mkay("eval .")]
public string Too { get; set; }
}
view raw Self.cs hosted with ❤ by GitHub

And then we can do stuff like this:

Can you do anything useful with this? Probably not. But you’ve got to admit it’s pretty cute.