Results for tag "attributerequiredlevel"

CRM 2011 – Required Fields serverseitig Validieren

Hi Leute,

man kennt doch das Problem, ab und zu schlägt irgendein Javascript fehlt (Syntax-Error, neue Browser-Version, etc.) und schon hat man den Salat, dass z.B. ein User eine Funktion auslöst, zu der er eigentlich nicht berechtigt wäre. Oder dass Felder, welche als Muss bzw. Required definiert sind, nicht ausgefüllt werden. Auf letzteren Punkt möchte ich den Fokus in diesem Blog-Entry legen. Nämlich wie man diese Required-Fields z.B. in einem eigenen WS oder in einem Plugin checkt.

CRM agiert hier, wie so oft, etwas eigenartig. Denn, wenn man sich die SDK so durchsieht, findet man ausschließlich einen ValidateRequest, welcher dann aber leider nur für div. Aktivitäten funktioniert, nicht für „normale“ Entitäten.

Contains the data that is needed to verify that an appointment or service appointment (service activity) has valid available resources for the activity, duration, and site as appropriate.

Warum das so ist, immerhin ist eine Aktivität nichts anderes als eine Entität, ist leider unklar. Also blieb nichts anderes übrig, selbst einen Weg zu finden, was auch relativ einfach gelang.

Zunächst mussten wir alle Required-Fields für eine Entität an Hand der Metainformationen herausfiltern:

[sourcecode language=“csharp“]
public static List<KeyValuePair<string, string>> GetRequiredFields(contracts.IOrganization organization, Entity entity)
{
try
{
List<KeyValuePair<string, string>> reqFields = new List<KeyValuePair<string, string>>();

var metadata = GetAllEntityAttributes(organization, entity.LogicalName);
foreach (var attribute in metadata)
{
if (attribute.RequiredLevel.Value == AttributeRequiredLevel.ApplicationRequired)
{
string label = attribute.AttributeOf;
if (attribute.DisplayName.UserLocalizedLabel != null)
label = attribute.DisplayName.UserLocalizedLabel.Label;

reqFields.Add(new KeyValuePair<string, string>(attribute.LogicalName, label));
}
}
return reqFields;
}
catch(Exception ex)
{
throw ex;
}
}
[/sourcecode]

Wir prüfen dabei nur auf „ApplicationRequired„-Fields, was den selbst definierten Pflichtfeldern entspricht. Man könnte noch „SystemRequired“ verwenden, was dann auch Felder wie „ownerid“, etc. zurückliefert. Es gibt noch weitere Optionen, hier lohnt sich der Blick ins CRM-SDK.

ApplicationRequired – The attribute is required to have a value.
None – No requirements are specified.
Recommended – It is recommended that the attribute has a value.
SystemRequired – The attribute is required to have a value.

Letztlich fehlt nur noch jene Methode, die überprüft, ob die gewünschte Entität auch die als required definierten Felder hält. Das funktioniert in CRM sehr einfach, denn die Attribute-Collection eines Microsoft.Xrm.Sdk.Entity-Objekts hält prinzipiell nur jene Attribute, die gesetzt wurden. Fehlt in dieser Collection also ein required Field, wurde es nicht gesetzt:

[sourcecode language=“csharp“]
public static List<KeyValuePair<string, string>> ValidateEntity(IOrganization organization, Entity entity)
{
try
{
// List<KeyValuePair<string, string>> listOfAlerts = new List<KeyValuePair<string, string>>();
List<ValidationResult> listOfErrors = new List<ValidationResult>();
// get required fields
var reqFields = GetRequiredFields(organization, entity);

// get displayname from entitymeta
var meta = GetEntityMeta(organization, entity.LogicalName);
var displayName = meta.DisplayName.UserLocalizedLabel.Label;

foreach(var field in reqFields)
{
if(!entity.Attributes.ContainsKey(field.Key))
listOfErrors.Add(new ValidationResult(field.Value, displayName, field.Key)); // Entitäts-Label | attribute-label | prefix_attributename
}

return listOfErrors;
}
catch (Exception ex)
{
throw ex;
}
}
[/sourcecode]

Die Methode liefert eine Generic-List retour, welche jene Felder beinhält, welche zwar required sind aber nicht gesetzt wurden.

Happy Programming 😉

Cheers,
Chris