Blog Page

CRM 2011 – Custom Ribbon Button – Mehr als 3 Elemente – Buttons deaktiviert

Mal wieder etwas spannendes…

Vergisst man beim Definieren der Ribbon-Buttons im customization.xml die Sequence hochzuzählen, so zeigt dies zunächst keine Auswirkungen.
Die Buttons 1-3 werden wie erwartet dargestellt und entsprechend der Rules aktiviert/deaktiviert.

Fügt man jedoch einen 4. oder 5. Button hinzu, werden diese sofort deaktiviert, die Enable/Display-Rule gar nicht mehr aufgerufen.

Funktioniert:
[sourcecode language=“xml“]
<Button Id="Mscrm.Isv.prefix_angebot.Form.Group0.Control0" Sequence="10" Command="Mscrm.Isv.prefix_angebot.Form.Group0.Control0" LabelText="$LocLabels:BestellungGenerieren.Label" ToolTipTitle="$LocLabels:BestellungGenerieren.Tooltip" ToolTipDescription="$LocLabels:BestellungGenerieren.Description" Image16by16="$webresource:hcs_bestellung_32" Image32by32="$webresource:hcs_bestellung_32" TemplateAlias="o1"></Button>
<Button Id="Mscrm.Isv.prefix_angebot.Form.Group0.Control1" Sequence="10" Command="Mscrm.Isv.prefix_angebot.Form.Group0.Control1" LabelText="$LocLabels:AngebotSenden.Label" ToolTipTitle="$LocLabels:AngebotSenden.Tooltip" ToolTipDescription="$LocLabels:AngebotSenden.Description" Image16by16="$webresource:prefix_icon_kalkulation_angebot_mail" Image32by32="$webresource:prefix_icon_kalkulation_angebot_mail" TemplateAlias="o1"></Button>
<Button Id="Mscrm.Isv.prefix_angebot.Form.Group0.Control2" Sequence="10" Command="Mscrm.Isv.prefix_angebot.Form.Group0.Control2" LabelText="$LocLabels:AngebotWord.Label" ToolTipTitle="$LocLabels:AngebotWord.Tooltip" ToolTipDescription="$LocLabels:AngebotWord.Description" Image16by16="$webresource:prefix_icon_kalkulation_angebot_word" Image32by32="$webresource:prefix_icon_kalkulation_angebot_word" TemplateAlias="o1"></Button>
[/sourcecode]

Funktioniert nur für die ersten 3 Buttons:
[sourcecode language=“xml“]
<Button Id="Mscrm.Isv.prefix_angebot.Form.Group0.Control0" Sequence="10" Command="Mscrm.Isv.prefix_angebot.Form.Group0.Control0" LabelText="$LocLabels:BestellungGenerieren.Label" ToolTipTitle="$LocLabels:BestellungGenerieren.Tooltip" ToolTipDescription="$LocLabels:BestellungGenerieren.Description" Image16by16="$webresource:hcs_bestellung_32" Image32by32="$webresource:hcs_bestellung_32" TemplateAlias="o1"></Button>
<Button Id="Mscrm.Isv.prefix_angebot.Form.Group0.Control1" Sequence="10" Command="Mscrm.Isv.prefix_angebot.Form.Group0.Control1" LabelText="$LocLabels:AngebotSenden.Label" ToolTipTitle="$LocLabels:AngebotSenden.Tooltip" ToolTipDescription="$LocLabels:AngebotSenden.Description" Image16by16="$webresource:prefix_icon_kalkulation_angebot_mail" Image32by32="$webresource:prefix_icon_kalkulation_angebot_mail" TemplateAlias="o1"></Button>
<Button Id="Mscrm.Isv.prefix_angebot.Form.Group0.Control2" Sequence="10" Command="Mscrm.Isv.prefix_angebot.Form.Group0.Control2" LabelText="$LocLabels:AngebotWord.Label" ToolTipTitle="$LocLabels:AngebotWord.Tooltip" ToolTipDescription="$LocLabels:AngebotWord.Description" Image16by16="$webresource:prefix_icon_kalkulation_angebot_word" Image32by32="$webresource:prefix_icon_kalkulation_angebot_word" TemplateAlias="o1"></Button>
<Button Id="Mscrm.Isv.prefix_angebot.Form.Group0.Control3" Sequence="10" Command="Mscrm.Isv.prefix_angebot.Form.Group0.Control3" LabelText="$LocLabels:AngebotUebergeben.Label" ToolTipTitle="$LocLabels:AngebotUebergeben.Tooltip" ToolTipDescription="$LocLabels:AngebotUebergeben.Description" Image16by16="$webresource:prefix_icon_kalkulation_angebot_uebergeben" Image32by32="$webresource:prefix_icon_kalkulation_angebot_uebergeben" TemplateAlias="o1"></Button>
<Button Id="Mscrm.Isv.prefix_angebot.Form.Group0.Control4" Sequence="10" Command="Mscrm.Isv.prefix_angebot.Form.Group0.Control4" LabelText="$LocLabels:AngebotObsolet.Label" ToolTipTitle="$LocLabels:AngebotObsolet.Tooltip" ToolTipDescription="$LocLabels:AngebotObsolet.Description" Image16by16="$webresource:prefix_icon_kalkulation_angebot_obsolet" Image32by32="$webresource:prefix_icon_kalkulation_angebot_obsolet" TemplateAlias="o1"></Button>
[/sourcecode]

UPDATE!!!! Die Sequence sollte man in mind. 10er Schritten hochzählen. Verwendet man Einerschritte, ist beim 5. Button Sense und das Problem, dass der Button automatisch deaktiviert und die EnableRule ignoriert wird, tritt wieder auf!!

Richtig:
[sourcecode language=“xml“]
<Button Id="Mscrm.Isv.prefix_angebot.Form.Group0.Control0" Sequence="10" Command="Mscrm.Isv.prefix_angebot.Form.Group0.Control0" LabelText="$LocLabels:BestellungGenerieren.Label" ToolTipTitle="$LocLabels:BestellungGenerieren.Tooltip" ToolTipDescription="$LocLabels:BestellungGenerieren.Description" Image16by16="$webresource:hcs_bestellung_32" Image32by32="$webresource:hcs_bestellung_32" TemplateAlias="o1"></Button>
<Button Id="Mscrm.Isv.prefix_angebot.Form.Group0.Control1" Sequence="20" Command="Mscrm.Isv.prefix_angebot.Form.Group0.Control1" LabelText="$LocLabels:AngebotSenden.Label" ToolTipTitle="$LocLabels:AngebotSenden.Tooltip" ToolTipDescription="$LocLabels:AngebotSenden.Description" Image16by16="$webresource:prefix_icon_kalkulation_angebot_mail" Image32by32="$webresource:prefix_icon_kalkulation_angebot_mail" TemplateAlias="o1"></Button>
<Button Id="Mscrm.Isv.prefix_angebot.Form.Group0.Control2" Sequence="30" Command="Mscrm.Isv.prefix_angebot.Form.Group0.Control2" LabelText="$LocLabels:AngebotWord.Label" ToolTipTitle="$LocLabels:AngebotWord.Tooltip" ToolTipDescription="$LocLabels:AngebotWord.Description" Image16by16="$webresource:prefix_icon_kalkulation_angebot_word" Image32by32="$webresource:prefix_icon_kalkulation_angebot_word" TemplateAlias="o1"></Button>
<Button Id="Mscrm.Isv.prefix_angebot.Form.Group0.Control3" Sequence="40" Command="Mscrm.Isv.prefix_angebot.Form.Group0.Control3" LabelText="$LocLabels:AngebotUebergeben.Label" ToolTipTitle="$LocLabels:AngebotUebergeben.Tooltip" ToolTipDescription="$LocLabels:AngebotUebergeben.Description" Image16by16="$webresource:prefix_icon_kalkulation_angebot_uebergeben" Image32by32="$webresource:prefix_icon_kalkulation_angebot_uebergeben" TemplateAlias="o1"></Button>
<Button Id="Mscrm.Isv.prefix_angebot.Form.Group0.Control4" Sequence="50" Command="Mscrm.Isv.prefix_angebot.Form.Group0.Control4" LabelText="$LocLabels:AngebotObsolet.Label" ToolTipTitle="$LocLabels:AngebotObsolet.Tooltip" ToolTipDescription="$LocLabels:AngebotObsolet.Description" Image16by16="$webresource:prefix_icon_kalkulation_angebot_obsolet" Image32by32="$webresource:prefix_icon_kalkulation_angebot_obsolet" TemplateAlias="o1"></Button>
[/sourcecode]

Cheers,
Christian

CRM 2011 – Custom Lookup (addCustomView) – OK Button disabled – Eintrag kann nicht ausgewählt werden

Wie der Titel des Artikels schon sagt, gilt es bei der Erstellung eines Custom Lookups ein paar Kleinigkeiten zu beachten. Tut man dies nicht, kann es dazu führen, dass man im Lookup zwar die richtigen Werte angezeigt bekommt, diese aber nicht übernehmen (per Klick auf den Record oder per Klick auf den OK-Button) kann.

Unter anderem geschieht dies, wenn das Layout-XML und Fetch-XML nicht genau aufeinander abstimmt. In meinem Fall hat es geholfen, darauf zu achten, dass überall der PrimaryKey der Entität verwendet wird.

Beispiel:

[sourcecode language=“xml“]
<grid name="resultset" object="1" jump="new_id" select="1" icon="1" preview="1"><row name="result" id="new_id"><cell name="new_name" width="300"/></row></grid>

<fetch version=’1.0′ output-format=’xml-platform‘ mapping=’logical‘ distinct=’true‘>
<entity name=’new_id‘>
….
</fetch>
[/sourcecode]

Bei mir hat das geholfen. Was sind eure Erfahrungen damit?

Cheers,
Chris

CRM 2011 – N:M Relation mit selber Entity – entityA n : m entityA – Retrieve Items

Mal wieder etwas spannendes aus der CRM Welt. Ich habe hier schon mal über Relationen gebloggt (siehe: Relationen). Nun kam mir etwas spannendes unter.

Und zwar musste eine N:M Relation abgebildet werden, wobei es sich auf beiden Seiten um die selbe Entität handelt. Also eine Adresse kann N andere Adressen referenziert haben und umgekehrt.

Betrachtet man das in nem Classdiagram, sieht’s wie folgt aus:

Man sollte denken, dass die Relation nun zwei ID’s hat, welche beide „entityiaid“ heissen. Das ist aber nicht der Fall. CRM hängt dem zweiten Schlüssel ein „one“ an. Das ist irrsinnig wichtig zu beachten, da es sonst zu kryptischen Fehlern bei FetchXml oder QueryExpressions kommt.

Cheers,
Christian

CRM 2011 – Verkaufschance abschließen – „gewonnen“/“verloren“

Nachfolgend findet Ihr zwei nützliche Funktionen, mit welchen Ihr programmatisch eine Verkaufschance abschließen (als ‚gewonnen‘ schließen bzw. als ‚verloren‘ schließen) könnt:

[sourcecode language=“csharp“]

/// <summary>
/// Marks as lost.
/// </summary>
/// <param name="organization">The organization.</param>
/// <param name="entityId">The entity id.</param>
/// <returns></returns>
public Result MarkAsLost(IOrganization organization, string entityId)
{
try
{
LoseOpportunityRequest req = new LoseOpportunityRequest();
Entity opportunityClose = new Entity("opportunityclose");
opportunityClose.Attributes.Add("opportunityid", new EntityReference("opportunity", new Guid(entityId)));
opportunityClose.Attributes.Add("subject", "opportunity lost");
req.OpportunityClose = opportunityClose;

OptionSetValue o = new OptionSetValue();
o.Value = 4;
req.Status = o;
LoseOpportunityResponse resp = (LoseOpportunityResponse) Helper.OrgService(organization).Execute(req);

return Helper.CreateResult("ok", Result.StatusCodes.Ok, null);
}
catch (Exception ex)
{
return Helper.CreateResult(ex.Message, Result.StatusCodes.Error, null);
}
}

/// <summary>
/// Marks as won.
/// </summary>
/// <param name="organization">The organization.</param>
/// <param name="entityId">The entity id.</param>
/// <returns></returns>
public Result MarkAsWon(IOrganization organization, string entityId)
{
try
{
WinOpportunityRequest req = new WinOpportunityRequest();
Entity opportunityClose = new Entity("opportunityclose");
opportunityClose.Attributes.Add("opportunityid", new EntityReference("opportunity", new Guid(entityId)));
opportunityClose.Attributes.Add("subject", "opportunity won");
req.OpportunityClose = opportunityClose;

//The Status parameter corresponds to Status Reason in the Microsoft CRM application. If you pass -1 for this parameter, the platform sets the status to the appropriate value for the Microsoft CRM application.
req.Status = new OptionSetValue(-1);

WinOpportunityResponse res = (WinOpportunityResponse)Helper.OrgService(organization).Execute(req);
return Helper.CreateResult("ok", Result.StatusCodes.Ok, null);
}
catch (Exception ex)
{
return Helper.CreateResult(ex.Message, Result.StatusCodes.Error, null);
}
}

[/sourcecode]

Happy coding!

CRM 2011 – „assembly must be registered in isolation“-Error

Nach längerer Zeit mal wieder was neues von der „Front“.

Wir haben letztens von unserem Implementierungspartner eine neue Solution zugesendet bekommen. Es gab jedoch Probleme beim Einspielen der neuen Solution, der „bekannte“ Fehler „Assembly must be registered in isolation“.

Was tun? Zunächst haben wir festgestellt, dass eine „alte“ Version der Assembly am Server direkt in CRM registriert war. Beim Versuch diese zu aktualisieren, kam der gleiche Fehler. Die Recherche unseres Partners hat ergeben, dass man für Änderungen – welche mit Assemblies zu tun haben – „Deployment Manager“ sein muss. Anstatt einer sprechenden Fehlermeldung kam jedoch der oben beschriebene Fehler.

Nachfolgend eine Sammlung von Links, welche bei der Lösung geholfen haben:

http://juicysnippets.blogspot.com/2011/03/assembly-must-be-registered-in.html
http://blogs.msdn.com/b/crminthefield/archive/2011/08/17/error-message-assembly-must-be-registered-in-isolation-when-registering-plugins-in-microsoft-dynamics-crm-2011.aspx
http://martinbodocky.wordpress.com/2011/05/12/assembly-must-be-registered-in-isolation/
http://social.microsoft.com/Forums/en/crm/thread/8fabc9a7-595f-4ebe-8ea2-b89848acf59d

Ich hoffe, ich konnte euch ein wenig weiterhelfen. Und natürlich DANKE an die Blogger, die dieses Problem bereits gelöst hatten 🙂

Cheers,
Christian

CRM 2011 – Custom View – Filter auf N:M Relation

Folgendes Beispiel:

Ihr habt in eurem Projekt folgende Entitätshierarchie:

Adresse ( n:m ) Gebäude ( n: 1 ) Standort

Am Formular des Standorts soll der Benutzer nun zunächst in einem Lookup das entsprechende Gebäude auswählen können (kein Filter). Nach Auswahl des Gebäudes sollen nur noch jene Adressen ausgewählt werden können, welche eine Verknüpfung mit dem ausgewählten Gebäude haben. Vom Prinizp eine Funktionsweise wie bei einer dependend Dropdownlist.

Normalerweise greift man jetzt einfach zu einem „FetchXML“ und baut sich das Konstrukt entsprechend auf. Aber hier beginnts zu haken: Beim Einrichten des Filters merkt man schnell, dass sich eine N:M-Relation nicht, wie z.B. eine 1:1/1:n-Relation, an einem Fremdschlüssel „aufhängt“, es fehlt also das Filter-Attribut. Jetzt wird man im Internet relativ schnell fündig, dass man in solchen Fällen einfach eine „Linked-Entity“ in das Fetch-Xml einbauen kann/muss. Problem hierbei: die addCustomView-Methode erwartet eine Entität, keine Relation.

Die Lösung sieht nun wie folgt aus:

Zunächst baut man das Fetch-XML wie gewohnt auf und lässt es mittels „Linked Entity“ auf die Relation verweisen. Innerhalb der Linked Entity, welche ja eig. keine Entität sondern eine Relation ist, hat man Zugriff auf die beiden Primary-Key-Felder der Relation. In meinem Fall „Adressid“ und „Gebaeudeid“. Dort lässt sich dann der Filter entsprechend einrichten.

Das fertige Fetch-XML sieht nun in meinem Fall wie folgt aus:

[sourcecode language=“xml“]
<fetch version="1.0" output-format="xml-platform" mapping="logical" distinct="false">
<entity name="<strong>new_address</strong>">
<attribute name="new_name" />
<attribute name="new_line1" />
<attribute name="new_city" />
<attribute name="new_stateorprovince" />
<link-entity name="<strong>relationname</strong>" from="primarykey" to="primarykey" >
<all-attributes/>
<filter type="and">
<condition attribute="primarykey" operator="eq" value="{1BF2077D-B6F0-E011-8481-005056A20041}" />
</filter>
</link-entity>
<order attribute="createdon" decending="true" />
</entity>
</fetch>
[/sourcecode]

Happy programming!
Chris

CRM 2011 – Ribbons via Javascript deaktivieren (disable Ribbons with javascript)

Jeder CRM Developer wird wohl schon vor folgendem Problem gestanden sein: Einen Ribbon Button deaktivieren, weil dieser im aktuellen Kontext keinen Sinn macht. Andere Buttons verwirren den Kunden, wiederrum andere sollen überhaupt verschwinden.

In einem meiner Projekte hatten wir nun die Situation, dass wir in einem bestimmten Prozess-Stati alle Ribbon Buttons von ca. 15-20 Entitäten sperren sollten. Inklusive der Original-Ribbon-Buttons (Datei, Entität, Hinzufügen, Listentools, etc.). Microsoft stellt dafür keinen vernünftigen Weg zur Verfügung, schlägt nur die Customizations.xml vor, was für ca. 400 Buttons ein enormer Zeitaufwand wäre, abgesehen von der extremen fehleranfälligkeit.

Ich habe daher, trotz aller Warnungn von div. CRM-Spezialisten („dieser Weg wird von MS nicht supportet“, etc.), einen Weg mittels Javascript gefunden, mittels welchem sich die Ribbon Buttons deaktivieren oder ganz ausblenden lassen, seht selbst:

[sourcecode language=“javascript“]

function HideRibbonButtons () {

var dateiButton = parent.document.getElementById("jewelcontainer"); // versteckt den "Datei"-Ribbon. Diesen zu deaktivieren habe ich nicht getestet!
dateiButton.style.display = ’none‘;

var ribbon = parent.document.getElementById("Mscrm.Ribbon");
var container = ribbon.childNodes[2].childNodes[0]; // container = Ein Tab, oberhalb der dargestellten Ribbons.

for (var i = 0; i < container.childNodes.length; i++) {
var group = container.childNodes[i];

if (group.id.indexOf(‚Isv‘) > 0) { // selbst hinzugefügte tabs enthalten bei mir den Hinsweis "Isv" und werden explizit ausgenommen.
// do nothing…
}
else {
DisableAllChilds(group);
}
}
}

// iteriert über alle child elements, bis das element mit der Rolle "button" gefunden wurde.
// An dieser Stelle kann dann die Deactivate oder Hide Funktionalität aufgerufen werden
function DisableAllChilds(element) {

for (var i = 0; i < element.childNodes.length; i++) {
var subElement = element.childNodes[i];

if (subElement.childNodes.length > 0)
DisableAllChilds(subElement);
}

if (element.role == "button") {

DeactivateRibbonButton(element);

}

}

// nachdem sich ein button nicht so ohne weiteres deaktivieren lässt (der dahinterliegende Event lässt sich nicht ausschalten),
// habe ich das element einfach geklont und das original-Element durch das erzeugte Element ersetzt.
function DeactivateRibbonButton(element) {
var link = document.createElement("a");
link.role = "button";
link.className = "ms-cui-ctl-large ms-cui-disabled";

try {
link.appendChild(element.childNodes[0]); // image/buttion
link.appendChild(element.childNodes[0]); // label
}
catch (exception) {
// do nothing…
}

element.parentNode.replaceChild(link, element);
}

// einen Button ausblenden ist hingegen recht easy und sollte keine negativen Auswirkungen haben.
function HideRibbonButton(element) {
element.style.display = ’none‘;
}

[/sourcecode]

Wichtig ist es noch zu wissen, dass das CRM nur den ersten Tab voll lädt, bedeutet, die Ribbons für alle weiteren Tabs werden erst bei erstmaligem Aufruf nachgeladen. Daher ist es notwendig, die Funktion „HideRibbonButtons()“ mehrmals aufzurufen, ich mache dieses mittels einem „setInterval“. Einen eleganteren Weg habe ich leider nicht finden können.

Abschließend nochmals explizit der Hinweis: Dies ist ein von Microsoft nicht unterstützter Weg! Bitte überlegt euch daher gut, ob ihr diesen gehen wollt!

Viel Spaß beim Nachmachen!

CRM 2011 – Custom View für Subgrid

In einem anderen Blog beschreibe ich, wie man einen Custom View zu einem Lookup hinzufügen kann. Heute habe ich die gleiche Funktionalität für ein Subgrid benötigt. Nachdem ich nicht gleich eine Lösung dafür gefunden habe, möchte ich euch meine nicht vorenthalten bzw. die Unterschiede zeigen:

[sourcecode language=“javascript“]
//Add your new view to the Lookup’s set of availabe views and make it the default view
$("#" + lookupFieldId).attr("disableViewPicker", "0");
Xrm.Page.getControl(lookupFieldId).addCustomView(viewId, entityName, viewDisplayName, fetchXml, layoutXml, viewIsDefault);
$("#" + lookupFieldId).attr("disableViewPicker", "1");
[/sourcecode]
So funktionierts für ein Lookup…

[sourcecode language=“javascript“]
var grd = document.getElementById(lookupFieldId);
if (grd.readyState != "complete") {
setTimeout("SetLookupForm(…params…);", 500);
}

grd.control.setParameter("fetchXml", fetchXml);
grd.control.refresh();
[/sourcecode]
… und so für ein Subgrid.

Achtet besonders auf die Abfrage auf „readystate“. Wenn Ihr die Funktionalität im OnLoad-Event verwendet, muss das Grid noch nicht geladen sein!! In diesem Fall rufe ich die Funktion einfach erneut auf…

Viel Spaß beim Nachmachen!

CRM 2011 – N:M Beziehung via C# setzen

CRM 2011 beherrscht nun endlich eine vernünftige N:M Beziehung.
Folgendes Code-Snippet zeigt, wie man via C# und dem SDK-Webservice zwei Entitäten verbindet.

[sourcecode language=“csharp“]
/// <summary>
/// Clones the entity.
/// </summary>
/// <param name="organization">The organization.</param>
/// <param name="entity1">The entity1.</param>
/// <param name="entity2">The entity2.</param>
/// <param name="relationShipName">Name of the relation ship.</param>
public static void AssociateEntities(contracts.IOrganization organization, Entity entity1, Entity entity2, string relationShipName)
{
// Create an AssociateEntities request
AssociateEntitiesRequest request = new AssociateEntitiesRequest();

// Set the ID of Moniker1 to the ID of the lead.
request.Moniker1 = new EntityReference { Id = entity1.Id, LogicalName = entity1.LogicalName};

// Set the ID of Moniker2 to the ID of the contact.
request.Moniker2 = new EntityReference { Id = entity2.Id, LogicalName = entity2.LogicalName};

// Set the relationship name to associate on.
request.RelationshipName = relationShipName;

// Execute the request.
Helper.OrgService(organization).Execute(request);
}
[/sourcecode]

Viel Spaß beim Ausprobieren!

CRM 2011 – Verbundene Objekte finden/laden (Get related Entities)

Verbindungen zwischen Entitäten werden in CRM, wie in einer Datenbank, mittels Referenzen abgebildet. Das funktioniert im GUI bzw. im Customizing (welches direkt im CRM passiert) auch sehr gut. Wenn man mittels C#-SDK versucht Entitäten zu bearbeiten/erstellen wird es dann schnell etwas umständlich.

Jeder kennt z.B. folgendes Beispiel: Angebot –> Positionen (1:n). Über die Eigenschaften (Attributes) der Angebot-Entität lässt sich nun nicht mehr ermitteln, wieviele Positionen das Angebot nun besitzt. Um diese Aufgabe zu lösen, habe ich mir zwei Helper-Methoden geschrieben, welche mir eine Collection der (Positionen-)Entitäten oder nur deren PrimaryKeys zurückliefern:

[sourcecode language=“csharp“]
/// <summary>
/// Gets the related projekt standorte.
/// </summary>
/// <param name="organization">The organization.</param>
/// <param name="entityName">Name of the entity.</param>
/// <param name="foreignKeyFieldName">Name of the foreign key field.</param>
/// <param name="foreignKeyFieldValue">The foreign key field value.</param>
/// <param name="columnSet">The column set.</param>
/// <returns></returns>
public static EntityCollection GetRelatedEntities(IOrganization organization, string entityName, string foreignKeyFieldName, string foreignKeyFieldValue, ColumnSet columnSet)
{
ConditionExpression condition = new ConditionExpression();
condition.AttributeName = foreignKeyFieldName;
condition.Operator = ConditionOperator.Equal;
condition.Values.Add(foreignKeyFieldValue);

// Create query expression.
QueryExpression query1 = new QueryExpression();
query1.ColumnSet = columnSet;
query1.EntityName = entityName;
query1.Criteria.AddCondition(condition);

EntityCollection result1 = Helper.OrgService(organization).RetrieveMultiple(query1);

return result1;
}

/// <summary>
/// Gets the related object ids.
/// </summary>
/// <param name="organization">The organization.</param>
/// <param name="entityId">The entity id.</param>
/// <param name="relatedEntityName">Name of the related entity.</param>
/// <param name="relatedEntityPrimaryKeyName">Name of the related entity primary key.</param>
/// <param name="foreignKeyName">Name of the foreign key.</param>
/// <returns></returns>
public static List<string> GetRelatedObjectIds(IOrganization organization, string entityId, string relatedEntityName, string relatedEntityPrimaryKeyName, string foreignKeyName)
{
var relEntities = EntityHelper.GetRelatedEntities(organization, relatedEntityName, foreignKeyName,
entityId, new ColumnSet(relatedEntityPrimaryKeyName));

return relEntities.Entities.Select(entity => entity.Attributes[relatedEntityPrimaryKeyName].ToString()).ToList();
}
[/sourcecode]

Ich hoffe ich konnte euch damit die Arbeit ein wenig verkürzen 😉

Cheers,
Chris