The following explains how to take advantage of the Action Feature in 2013 , to validate an entity.
Once the action is in place it can be called from anywhere (Portal , Plugin , Client side JavaScript , Batch job, etc ) via the CRM service. The example below will explain how to validate the contact Record using a custom action.
1. In your project solution in CRM add a new process of type action . The name can be ValidateContact and The entity value can be Contact.. In the process arguments , It needs an Entity type (with contact as the rntity value) as input called "Entity" and EntityCollection as an Output called "ValidationResults". No steps are required as the executing code will be in the Plugin .
2. Create a new entity called new_validationResult with attributes Type(option set Error,warning), Feild (string), ValidationMessage(ntext). Refresh the early bound library
3.Publish All Customization's
4. Create a new Plugin with the following Code
public void Execute(IServiceProvider serviceProvider)
{
base.Intialise(serviceProvider);
EntityCollection collection = new EntityCollection();
collection.EntityName = new_validationresult.EntityLogicalName;
collection.MinActiveRowVersion = "-1";
//To get access to the image of the Quote record
Contact contact = new Contact();
if (base.Context.InputParameters.Keys.Contains("Entity") && base.Context.InputParameters["Entity"] != null)
{
Entity entityRef = base.Context.InputParameters["Entity"] as Entity;
contact.Intialise(entityRef);
}
if (contact.FirstName == null || contact.FirstName == string.Empty)
{
new_validationresult result = new new_validationresult();
result.new_ValidationMessage = "Please Fill in First Name";
result.new_Field = "FirstName";
result.new_Type = (int)new_validationresultnew_Type.Error;
collection.Entities.Add(result.ToEntity());
}
base.Context.OutputParameters["ValidationResults"] = collection;
}
5. In the Plugin registration tool Register the Plugin . Create a new Step with the now available "new_ValidateContact" Message. It can Be registered against the Post Execution.
Note for Online you need to restart Plugin Registration Tool in order for the message to be picked up.
6. The new_validateContact action can now be called from anywhere A c# early bound example below. You need to include the
/generateActions parameter in the CRMsvcUtil command
Early Bound Example
Contact contact = new Contact();
contact.LastName = "Cunningham";
contact.Create();
new_ValidateContactRequest request = new new_ValidateContactRequest();
request.Entity = contact.ToEntity();
EntityReference reference = new EntityReference();
reference.LogicalName = "contact";
reference.Id = contact.Id; /// this can be set to a "dummy" contact if you want to validate the contact before create
request.Target = reference;
new_ValidateContactResponse response = CRMConnection.Service.Execute(request) as new_ValidateContactResponse;
string messages = string.Empty;
foreach (Entity result in response.ValidationResults.Entities)
{
new_validationresult o = new new_validationresult();
o.Intialise(result);
messages += o.new_ValidationMessage;
}
Console.WriteLine("Errors found:" + messages);
late bound example
Entity contact = new Entity("contact");
contact.Attributes.Add("lastname", "Cunningham Late");
contact.Id= CRMConnection.Service.Create(contact);
OrganizationRequest request = new OrganizationRequest();
request.Parameters.Add("Entity",contact);
request.RequestName = "new_ValidateContact";
EntityReference reference = new EntityReference();
reference.LogicalName = "contact";
reference.Id = contact.Id; /// this can be set to a "dummy" contact if you want to validate the contact before create
request.Parameters.Add("Target", reference);
OrganizationResponse response = CRMConnection.Service.Execute(request) as OrganizationResponse;
string messages = string.Empty;
EntityCollection collection = (EntityCollection)response.Results["ValidationResults"];
foreach (Entity result in collection.Entities)
{
messages += result["new_validationmessage"].ToString();
}
Console.WriteLine("Errors found:" + messages);
A JavaScript example
function ExecuteValidationActionCreateProject()
{
var target1 = Sdk.EntityReference("contact",Xrm.Page.data.entity.getId().replace('{', '').replace('}', '') ,null);
var entity1 = null;
var request = Sdk.new_ValidateContactRequest(entity1,target1);
Sdk.Async.execute(request, successCallBack, errorCallBack, passThruObj );
}
function successCallBack(data)
{
var entityCollection = data.getValidationResults();
var validationResults = entityCollection.getEntities();
var message = "" ;
for ( i = 0 ; i < validationResults.getCount(); i++)
{
var entity = validationResults.getByIndex(i);
var attributes = entity.getAttributes().getAttributes();
for ( r = 0 ; r < attributes.getCount(); r++)
{
var attribute = attributes.getByIndex(r);
if (attribute.getName() == "new_validationmessage")
{
message= message.concat(attribute.getValue());
}
}
}
if(message != "")
{
alert("Errors:"+message);
}
}
function errorCallBack(data)
{
alert("Error");
}
function passThruObj(data)
{
}
Note: In this example "Contact " was used as the target entity(see step one). If you choose contact you have to pass an existing contact guid as the target when using this custom action. If you don't the action request will fail. Using "none" will allow you to bypass this check. This would get over the problem where for example you wanted to validate a contact before creating that contact.(contact would have no guid so you have no guid to pass to the target)