Here's my solution for that:
- Create validation messages in resource file
In your resource file (e.g Validation.resx) add entries for validation messages, e.g.
Of course, you'll need to define those entries in resource files for all languages your application should support (e.g. in Validation.de.resx for German, Validation.es.resx for Spanish, etc.). - Add business objects validation attributes
Let's use a sample business object representing User, which only includes name property. We have to add ActiveRecord attributes for validation e.g. ValidateNonEmpty and ValidateLength using appropriate parameters. These both attributes take the validation message as one of the arguments. Instead of giving here the actual message we can use its ID (name) from the resource file e.g. "vldNameRequired". Here is sample code of such Business Object:[ActiveRecord("User")]
For more validation attributes please refer to ActiveRecord documentation.
public class User : ActiveRecord
{
[Property(NotNull = true, Length = 50)]
[ValidateNonEmpty("vldNameRequired")]
[ValidateLength(1, 50, "vldNameLength")]
public string Name { get; set; }
} - Catch validation errors
Now, we have to enable validation for appropriate action. Let's say we want to validate data provided by the user while creating new account. For registering new user I've created the Register method together with appropriate data binds. Firstly we need to allow validation for that action (Validate = true).
Catching validation errors is described in comments in code below:(...)
using System.Resources;
public class UserController : SmartDispatcherController
{
(...)
public void Register([DataBind("User", Validate=true)]User user)
{
// Check whether the binded object is valid by calling the
// HasValidationError inherited from SmartDispatcherController
if (HasValidationError(user))
{
// If there are validation errors we can access the error
// summary using GetErrorSummary method
ErrorSummary summary = GetErrorSummary(user);
// Now we have to populate Flash item with localized
// validation messages by calling local private
// method GetLocalizedMessages
Flash["validationErrors"] = GetLocalizedMessages(summary);
PropertyBag["user"] = user;
}
else
{
//If there are no errors save the new user and redirect
//to other action
User.Save(user);
RedirectToAction('DoSomethingElse');
}
}
/// <summary>
/// Translates the message IDs to actual messages
/// </summary>
/// <param name="messageIDs">Message IDs to translate</param>
/// <returns>Array of translated messages</returns>
private string[] GetLocalizedMessages(string[] messageIDs)
{
string[] messages = new string[messageIDs.Length];
for (int i=0;i<messageIDs.Length;i++)
{
// YourNamespace.Validation is the full name of your
// resource file with validation messages
messages[i] = YourNamespace.Validation.
ResourceManager.GetString(messageIDs[i]);
if (messages[i] == null)
{
// ERR_NO_RESOURCE is constant storing ID of default
// error msg
messages[i] = Validation.ResourceManager.
GetString(ERR_NO_RESOURCE);
}
}
return messages;
}
} - Display localized validation messages
Now you have to display validation error messages on the page. This is the sample code that displays all validation errors coming from ActiveRecord validation (I'm using NVelocity as my view engine):
#if($validationErrors != null && $validationErrors.Length > 0)
<ul class="validationErrors">
#foreach($ve in $validationErrors)
<li>$ve</li>
#end
</ul>
#end