Archive for February 2016

Custom Validation Attributes and Client-Side Validation For Idiots Like Me

Just join the what to what?

This is one of those posts that I’ve written more the benefit of Future Me than anyone else. Future Me is a forgetful fellow, it seems, so this will hopefully save him some wretched googling while trying to recall that one crucial detail that makes this just work. If it helps you in a similar way then that’s nice.

First of all, this assumes that you already have Unobtrusive Javascript set up and working in your project. There are plenty of guides on that and I’m confident even Future Me can handle it. It also assumes you’re already familiar with creating custom validation attributes. What it does concern is writing a jQuery adapter to do the validation client-side. There are plenty of guides on this, but what I’m presenting here is the bare minimum required for simple validators.

Let’s write a tiny amount of code

The first thing to do is modify your existing validation attribute class. This is done on in two places:

The class itself needs to inherit IClientValidatable:

public class MyLovelyCustomValidator : ValidationAttribute, IClientValidatable

And the GetClientValidationRules class from that interface needs implementing:

public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
        {
            var rule = new ModelClientValidationRule();
            rule.ErrorMessage = FormatErrorMessage(metadata.GetDisplayName());
            rule.ValidationType = "myadaptername";
            yield return rule;
        }

The FormatErrorMessage return being added to the rule above comes from the ValidationAttribute your custom validator inherits. You may have overridden it, you may not. That’s unimportant here.

More important is the ValidationType being added. I’ve set it to myadaptername in this example because it will be used as the name of your jQuery adapter too.

Now we’ll write the adapter. Create a new .js file somewhere sensible in your project and add this:

$.validator.unobtrusive.adapters.addBool("myadaptername");

There are a number of methods available for adding adapters. There’s a really good summary of them (and a more in-depth examination of custom validation) at Brad Wilson’s excellent if now slightly ancient blog post.

I’ve chosen addBool(adapterName, [ruleName]) because this is very simple validation based solely on the input value, which is what this validator does. Note that it has an optional ruleName parameter which we’re not using. The rule name could be one of the built-in jQuery validation rules (eg mandatory) or it could be one of your own. If it’s omitted the adapterName is used instead. Since I’m writing my own specifically for this adapter, I’ve omitted it for simplicity’s sake.

Next we add the validator to the same file:

$.validator.addMethod("myadaptername", function(value) {
    return value > 0; //your implementation here
});

Again this is very simple. We pass in the adapter name, and a function to perform the validation. The full signature for the function is function (value, element, params), but as we don’t need element (our validator is only testing the value itself) and we have no additional parameters, we can omit them.

Finally, do your validation within the function. Include the .js file in the page containing your form, and assuming validation was working fine before, it should now validate the field using your custom validator client-side too.

As an afterword, the reason this example is so simple is because I have a validator that tests whether a nullable decimal has a value greater than zero. However hopefully you, or Future Me, will find it a useful basis to build more complex validators from.

Microsoft Dynamics CRM Integration

Fun for all the family

Gripping headline, I know. My current contract has involved communicating with a third-party Dynamics CRM, and while there is plenty of advice out there on the internet, I didn’t find anything that completely worked. So this, for now at least, will fill that gap.

We’re going to need a couple of things before we start:

  • The service URL and credentials for the Dynamics instance.
  • The MS Dynamics SDK. I’m using the 2011 version; you may need a different one.

The SDK contains the CrmSvcUtil.exe command line tool, which will generate code for early-binding to the CRM objects. Getting the correct parameters for this was the hardest part of the integration, and essentially this is the meat of this blog post.

You’ll find CrmSvcUtil.exe in the bin folder in the SDK. Open a command prompt there with admin privileges, then construct your command using this form:

CrmSvcUtil.exe /codeCustomization:"Microsoft.Xrm.Client.CodeGeneration.CodeCustomization, Microsoft.Xrm.Client.CodeGeneration" /out:Xrm.cs /url:[DYNAMICS SERVICE URL] /username:[DYNAMICS USER NAME] /password:[DYNAMICS PASSWORD] /namespace:Xrm /serviceContextName:XrmServiceContext

The parameters you’ll need to set for your particular instance are:

  • [DYNAMICS SERVICE URL] – You can find this in your dynamics management site, under Settings > Customization > Developer Resources. You want the SOAP Organization Service. This will be of the form https://[YOUR-CRM-NAME].[LOCATION].dynamics.com/XRMServices/2011/Organization.svc. This example contains 2011 in the URL because I’m using the 2011 version. [YOUR-CRM-NAME] will have been set when your instance was created. [LOCATION] depends on the physical location of your instance and the identity provider being used. For example, mine is crm4.
  • [DYNAMICS USER NAME] – This will be the email address of the account you are using to access Dynamics.
  • [DYNAMICS PASSWORD] – The password for the same account, duh.

Note that I’ve set the out parameter to be Xrm.cs. This will dump all the generated code into that file in the SDK/Bin folder. If you’re going to regenerate the code often you may want to set the output path to somewhere in your project, but I’m trying to keep things simple in this example.

With everything in place, hit return and wait while the utility does its stuff. It will probably sit there looking like it’s doing nothing for a little while. Be patient, and eventually it will start spewing out logs like something from The Matrix. If you’ve got a large organization this could take some time.

At the end of the process you should have a massive pile of autogenerated code. In my case it ran to over 100,000 LOC which Visual Studio choked on when I tried to open it. So if you need to look at it, use something like Notepad++ instead.

If it isn’t already there, copy the generated file to somewhere suitable in the project. We will reference it in the next step.

If you’re still awake

The XRM SDK contains the very useful CrmConnection. This provides a way of getting authentication details from a connection string and reusing this connection throughout the application. This may sound counter-intuitive. Surely it would be better to have multiple connections? The problem the single shared connection solves is that authenticating the connection takes a while. Rather than go through the process for every transaction, the shared connection means subsequent transactions are pre-authenticated. The CrmConnection is thread-safe, and performance issues with multiple transactions are avoided by creating a new XrmServiceContext with the connection for each transaction.

Let’s get started by adding the Microsoft Dynamics CRM 2015 SDK client and portal assemblies via nuget. You may have noticed that’s the 2015 version. I couldn’t find an exact equivalent for 2011, and my best guess didn’t work. So this may be the part where this blog post falls apart and causes great anguish, but so far I’ve had no issues using the 2015 one.

Now we have the XRM objects we need, let’s add a connection string. Add it to web.config, in the usual place where connection strings live:

<add name="CrmConnection" connectionString="Url=https://[YOUR-CRM-NAME].[LOCATION].dynamics.com; Username=[DYNAMICS USER NAME]; Password=[DYNAMICS PASSWORD];" />

The tokenised parts are exactly the same as described in the CrmSvcUtil parameters above.

To use the connection across your application you’ll most likely want to set it up using your dependency injection weapon of choice. I’m using StructureMap:

container.For<CrmConnection>().Singleton().Use(ctx => new CrmConnection("CrmConnection"));

Note that I’m creating it as a singleton because we want to share it across the application. It’s thread-safe, remember.

Now we’re ready to use it. Here’s an extremely basic example, which retrieves a contact from the ContactSet:

public class XrmExample
{
	private readonly CrmConnection _crmConnection;

	public XrmExample(CrmConnection crmConnection)
	{
		_crmConnection = crmConnection;
	}

	public Contact GetContact(string username)
	{
		using (var xrm = new XrmServiceContext(_crmConnection))
		{
			var contact = xrm.ContactSet.FirstOrDefault(x => x.EMailAddress1 == username.ToLower());
			if (contact != null)
			{
				return contact;
			}
		}
		return null;
	}
}

EMailAddress1 probably doesn’t exist in your instance, but you get the idea. The main points are that we’re getting the CrmConnection singleton and using it to create a new XrmServiceContext for our transaction. Repeat this pattern throughout your application and all will be well.