%3CLINGO-SUB%20id%3D%22lingo-sub-974352%22%20slang%3D%22en-US%22%3ERules%20Extensions%20-%20MapAttributesForJoin%3C%2FLINGO-SUB%3E%3CLINGO-BODY%20id%3D%22lingo-body-974352%22%20slang%3D%22en-US%22%3E%0A%20%26lt%3Bmeta%20http-equiv%3D%22Content-Type%22%20content%3D%22text%2Fhtml%3B%20charset%3DUTF-8%22%20%2F%26gt%3B%3CSTRONG%3EFirst%20published%20on%20MSDN%20on%20Feb%2008%2C%202016%20%3C%2FSTRONG%3E%20%3CBR%20%2F%3E%20Update%201%2F19%2F2017%20%3CBR%20%2F%3E%20When%20configuring%20your%20%22Join%20Logic%22%20via%20a%20Custom%20MA%20Extension%20we%20need%20to%20remember%20to%20try%20and%20keep%20it%20simple%20i%20know%20that's%20not%20always%20possible%20but%20the%20more%20complex%20the%20Join%20Logic%20the%20greater%20the%20risk%20of%20joining%20two%20objects%20up%20incorrectly%2C%20Also%20try%20not%20to%20get%20into%20the%20trap%20of%20trying%20to%20make%20a%20super%20complex%20join%20logic%20to%20cover%20every%20possible%20scenario%2C%20Join%20logic%20should%20not%20be%20a%20replacement%20for%20good%20old%20fashion%20Data%20Clean%20Up.%20Yes%20using%20code%20can%20and%20will%20make%20Data%20Clean%20up%20easier%20but%20if%20you%20have%202%20million%20objects%20and%20there%20is%20one%20object%20that%20has%20no%20real%20data%20to%20be%20used%20for%20joining%20do%20you%20waste%20countless%20hours%20to%20come%20up%20with%20logic%20to%20allow%20that%201%20object%20to%20join%20up%20with%20something%20or%20do%20you%20find%20that%20object%20after%20and%20just%20clean%20it%20up%20at%20the%20source.%20%3CBR%20%2F%3Eby%20modifying%20the%20following%20section%20you%20can%20build%20a%20more%20advance%20Join%20Logic%2C%20the%20below%20code%20is%20referenced%20from%20the%20following%20post%20%3CA%20href%3D%22https%3A%2F%2Fblogs.msdn.microsoft.com%2Fconnector_space%2F2016%2F03%2F25%2Frules-extension-maextension%2F%22%20target%3D%22_blank%22%20rel%3D%22noopener%20noreferrer%20noopener%20noreferrer%22%3E%20Rules%20Extension%20-MAExtension%20%3C%2FA%3E%20%3CBR%20%2F%3E%20%3CBR%20%2F%3E%20%3CSPAN%20style%3D%22background-color%3A%20%23ffff00%22%3E%20void%20IMASynchronization.MapAttributesForJoin%20(string%20FlowRuleName%2C%20CSEntry%20csentry%2C%20ref%20ValueCollection%20values)%20%3C%2FSPAN%3E%20%3CBR%20%2F%3E%20%3CSPAN%20style%3D%22background-color%3A%20%23ffff00%22%3E%20%7B%20%3C%2FSPAN%3E%20%3CBR%20%2F%3E%20%3CSPAN%20style%3D%22background-color%3A%20%23ffff00%22%3E%20%2F%2F%20%3C%2FSPAN%3E%20%3CBR%20%2F%3E%20%3CSPAN%20style%3D%22background-color%3A%20%23ffff00%22%3E%20%2F%2F%20TODO%3A%20write%20join%20mapping%20code%20%3C%2FSPAN%3E%20%3CBR%20%2F%3E%20%3CSPAN%20style%3D%22background-color%3A%20%23ffff00%22%3E%20%2F%2F%20%3C%2FSPAN%3E%20%3CBR%20%2F%3E%20%3CSPAN%20style%3D%22background-color%3A%20%23ffff00%22%3E%20throw%20new%20EntryPointNotImplementedException()%3B%20%3C%2FSPAN%3E%20%3CBR%20%2F%3E%20%3CSPAN%20style%3D%22background-color%3A%20%23ffff00%22%3E%20%7D%20%3C%2FSPAN%3E%20%3CBR%20%2F%3E%20%3CBR%20%2F%3E%20If%20you%20would%20like%20to%20join%20objects%20from%20a%20Source%20Directory%20that%20has%20samAccountNames%20with%20the%20format%20that%20includes%20%22SP_%22%20added%20to%20the%20accountName%20from%20other%20directories.%20%3CBR%20%2F%3E%20in%20a%20Disaster%20Recovery%20Scenario%20where%20you%20have%20to%20rebuild%20the%20Metaverse%20and%20join%20objects%20back%20up.%20%3CBR%20%2F%3E%20the%20following%20piece%20of%20code%20would%20remove%20%22SP_%22%20from%20the%20samAccountName%20of%20the%20source%20object%20and%20than%20attempt%20to%20join%20to%20an%20object%20in%20the%20metaverse%20with%20the%20accountName%20that%20matches%20the%20sAMAccountName%20of%20the%20source%20object%20minus%20the%20%22SP_%22%20%3CBR%20%2F%3E%20Example%20A%20%3CBR%20%2F%3E%20%3CSPAN%20style%3D%22background-color%3A%20%23ffcc00%22%3E%20void%20IMASynchronization.MapAttributesForJoin%20(string%20FlowRuleName%2C%20CSEntry%20csentry%2C%20ref%20ValueCollection%20values)%20%3C%2FSPAN%3E%20%3CBR%20%2F%3E%20%3CSPAN%20style%3D%22background-color%3A%20%23ffcc00%22%3E%20%7B%20%3C%2FSPAN%3E%20%3CBR%20%2F%3E%20%3CSPAN%20style%3D%22background-color%3A%20%23ffcc00%22%3E%20%2F%2F%20%3C%2FSPAN%3E%20%3CBR%20%2F%3E%20%3CSPAN%20style%3D%22background-color%3A%20%23ffcc00%22%3E%20%2F%2F%20TODO%3A%20write%20join%20mapping%20code%20%3C%2FSPAN%3E%20%3CBR%20%2F%3E%20%3CSPAN%20style%3D%22background-color%3A%20%23ffcc00%22%3E%20%2F%2F%20%3C%2FSPAN%3E%20%3CBR%20%2F%3E%20%3CSPAN%20style%3D%22background-color%3A%20%23ff99cc%22%3E%20values.Add(csentry%5B%22samAccountName%22%5D.StringValue.Replace(%22SP_%22%2C%20%22%22))%3B%20%3C%2FSPAN%3E%20%3CBR%20%2F%3E%20%3CSPAN%20style%3D%22background-color%3A%20%23ffcc00%22%3E%20%2F%2Fthrow%20new%20EntryPointNotImplementedException()%3B%20%3C%2FSPAN%3E%20%3CBR%20%2F%3E%20%3CSPAN%20style%3D%22background-color%3A%20%23ffcc00%22%3E%20%7D%20%3C%2FSPAN%3E%20%3CBR%20%2F%3E%20%3CBR%20%2F%3E%20The%20problem%20with%20the%20above%20code%20is%2C%20I%20left%20no%20room%20for%20addition%20Join%20logic.%20If%20I%20wanted%20to%20use%20the%20Same%20extension%20across%20several%20Management%20Agents%20each%20with%20their%20own%20unique%20Join%20Statement%20I%20would%20need%20to%20modify%20the%20code%20like%20the%20following%20example%20%3CBR%20%2F%3E%20Example%20B%20%3CBR%20%2F%3E%20void%20IMASynchronization.MapAttributesForJoin(string%20FlowRuleName%2C%20CSEntry%20csentry%2C%20ref%20ValueCollection%20values)%20%3CBR%20%2F%3E%3CP%20style%3D%22padding-left%3A%2030px%22%3E%7B%3C%2FP%3E%3CBR%20%2F%3E%3CP%20style%3D%22padding-left%3A%2030px%22%3Eswitch%20(FlowRuleName)%3C%2FP%3E%3CBR%20%2F%3E%3CP%20style%3D%22padding-left%3A%2060px%22%3E%7B%3C%2FP%3E%3CBR%20%2F%3E%3CP%20style%3D%22padding-left%3A%2060px%22%3Ecase%20%22SPAccountName%22%3A%3C%2FP%3E%3CBR%20%2F%3E%3CP%20style%3D%22padding-left%3A%2090px%22%3Evalues.Add(csentry%5B%22samAccountName%22%5D.StringValue.Replace(%22SP_%22%2C%20%22%22))%3B%3C%2FP%3E%3CBR%20%2F%3E%3CP%20style%3D%22padding-left%3A%2060px%22%3Ebreak%3B%3C%2FP%3E%3CBR%20%2F%3E%3CP%20style%3D%22padding-left%3A%2060px%22%3Ecase%20%22BuildAccountName%22%3A%3C%2FP%3E%3CBR%20%2F%3E%3CP%20style%3D%22padding-left%3A%2090px%22%3Eif%20(csentry%5B%22accountName%22%5D.IsPresent)%3C%2FP%3E%3CBR%20%2F%3E%3CP%20style%3D%22padding-left%3A%2090px%22%3E%7B%3C%2FP%3E%3CBR%20%2F%3E%3CP%20style%3D%22padding-left%3A%20120px%22%3Evalues.Add(csentry%5B%22accountName%22%5D.StringValue)%3B%3C%2FP%3E%3CBR%20%2F%3E%3CP%20style%3D%22padding-left%3A%2090px%22%3E%7D%3C%2FP%3E%3CBR%20%2F%3E%3CP%20style%3D%22padding-left%3A%2090px%22%3Eelse%20if%20(csentry%5B%22firstName%22%5D.IsPresent%20%26amp%3B%26amp%3B%20csentry%5B%22lastName%22%5D.IsPresent)%3C%2FP%3E%3CBR%20%2F%3E%3CP%20style%3D%22padding-left%3A%2090px%22%3E%7B%3C%2FP%3E%3CBR%20%2F%3E%3CP%20style%3D%22padding-left%3A%20120px%22%3Evalues.Add(csentry%5B%22firstName%22%5D.StringValue%20%2B%20%22.%22%20%2B%20csentry%5B%22lastName%22%5D.StringValue)%3B%3C%2FP%3E%3CBR%20%2F%3E%3CP%20style%3D%22padding-left%3A%2090px%22%3E%7D%3C%2FP%3E%3CBR%20%2F%3E%3CP%20style%3D%22padding-left%3A%2090px%22%3Ebreak%3B%3C%2FP%3E%3CBR%20%2F%3E%3CP%20style%3D%22padding-left%3A%2060px%22%3E%7D%3C%2FP%3E%3CBR%20%2F%3E%3CP%20style%3D%22padding-left%3A%2030px%22%3E%7D%3C%2FP%3E%3CBR%20%2F%3E%20Example%20A%20would%20require%20the%20MA%20Join%20Logic%20to%20be%20configured%20like%20%3CBR%20%2F%3E%20%3CBR%20%2F%3E%20%3CIMG%20alt%3D%22joinLogicEXA%22%20class%3D%22alignnone%20size-mediumlarge%20wp-image-2297%22%20height%3D%2257%22%20src%3D%22https%3A%2F%2Ftechcommunity.microsoft.com%2Ft5%2Fimage%2Fserverpage%2Fimage-id%2F153682iF361F353C988782D%22%20width%3D%22500%22%20%2F%3E%20%3CBR%20%2F%3E%20Example%20B%20would%20use%20the%20FlowRuleName%20making%20it%20easier%20to%20manage%20%3CBR%20%2F%3E%20%3CIMG%20alt%3D%22joinLogicEXB%22%20class%3D%22alignnone%20size-mediumlarge%20wp-image-2305%22%20height%3D%22119%22%20src%3D%22https%3A%2F%2Ftechcommunity.microsoft.com%2Ft5%2Fimage%2Fserverpage%2Fimage-id%2F153683iC7E99A0CEA4A5FB5%22%20width%3D%22500%22%20%2F%3E%20%3CBR%20%2F%3E%20%3CBR%20%2F%3E%20Once%20the%20code%20has%20been%20compiled%20%3CA%20href%3D%22http%3A%2F%2Fblogs.msdn.com%2Fb%2Fconnector_space%2Farchive%2F2016%2F02%2F12%2Frules-extensions-build-and-compile.aspx%22%20target%3D%22_blank%22%20rel%3D%22noopener%20noreferrer%20noopener%20noreferrer%22%3E%20See%20Rules%20Extensions%20-%20Build%20and%20Compile%20%3C%2FA%3E%20%3CBR%20%2F%3E%20Right%20Click%20on%20the%20Management%20Agent%20that%20the%20extension%20is%20for%20and%20click%20on%20Properties%20%3CBR%20%2F%3E%20in%20this%20example%20we%20wrote%20an%20extension%20for%20Join%20Logic%20so%20we%20will%20click%20on%20Configure%20Join%20and%20Projection%20Rules%20%3CBR%20%2F%3E%20Select%20the%20object%20type%20you%20wish%20to%20configure%20the%20Join%20Rule%20for%2C%20in%20this%20example%20we%20chose%20group.%20%3CBR%20%2F%3E%20now%20Select%20New%20Join%20Rule%2C%20%3CBR%20%2F%3E%20In%20the%20Data%20Source%20attribute%3A%20section%20we%20selected%20sAMAccountName%20%3CBR%20%2F%3E%20for%20Mapping%20Type%20we%20selected%20Rules%20Extension%20%3CBR%20%2F%3E%20For%20Metaverse%20object%20type%3A%20select%20the%20object%20type%20that%20you%20wish%20to%20join%20to%20in%20the%20metaverse%20do%20not%20leave%20as%20ANY%2C%20unless%20that%20is%20what%20you%20really%20need.%20%3CBR%20%2F%3E%20and%20for%20Metaverse%20Object%20type%3A%20we%20selected%20accountName%20%3CBR%20%2F%3E%20%3CBR%20%2F%3E%20Once%20you%20have%20that%20selected%20click%20on%20Add%20Condition%2C%20you%20may%20get%20the%20following%20message%20about%20joining%20non-indexed%20%3CBR%20%2F%3E%20Click%20on%20OK%20%3CBR%20%2F%3E%20Now%20in%20the%20next%20window%20you%20need%20to%20define%20context%20or%20function%20in%20which%20will%20be%20called%20in%20the%20rules%20extension%20that%20will%20perform%20the%20action%20you%20desire.%20%3CBR%20%2F%3E%3CP%20style%3D%22padding-left%3A%2030px%22%3EIf%20you%20dont%20know%20what%20it%20is%20open%20up%20the%20extension%20again%20in%20Visual%20Studios%3C%2FP%3E%3CBR%20%2F%3E%3CP%20style%3D%22padding-left%3A%2030px%22%3EIn%20this%20example%20we%20will%20use%20IMASynchronization.MapAttributesForJoin%3C%2FP%3E%3CBR%20%2F%3E%3CP%20style%3D%22padding-left%3A%2030px%22%3ERemove%20the%20value%20in%20the%20window%3C%2FP%3E%3CBR%20%2F%3E%3CP%20style%3D%22padding-left%3A%2030px%22%3Enow%20add%20the%20function%20name%20in%20this%20example%20we%20will%20use%20%22IMASynchronization.MapAttributesForJoin%22%20it%20should%20look%20like%20the%20following%3C%2FP%3E%3CBR%20%2F%3E%3CP%20style%3D%22padding-left%3A%2030px%22%3EClick%20on%20OK%3C%2FP%3E%3CBR%20%2F%3E%3CP%20style%3D%22padding-left%3A%2030px%22%3EAt%20this%20point%20if%20you%20click%20on%20OK%20you%20will%20probably%20receive%20the%20following%20message%20unless%20you%20have%20the%20rules%20extension%20selected%20under%20Configure%20Extensions%3C%2FP%3E%3CBR%20%2F%3E%3CP%20style%3D%22padding-left%3A%2030px%22%3EWhen%20you%20click%20on%20OK%20from%20this%20window%20you%20should%20be%20directed%20to%20the%20Configure%20Extensions%20Window%3C%2FP%3E%3CBR%20%2F%3E%3CP%20style%3D%22padding-left%3A%2030px%22%3EClick%20on%20Select%20next%20to%20the%20Rules%20Extension%20at%20the%20top%3C%2FP%3E%3CBR%20%2F%3E%3CP%20style%3D%22padding-left%3A%2030px%22%3EThis%20will%20open%20up%20a%20window%20which%20will%20display%20all%20.dll%20files%20within%20the%20default%20extensions%20directory%20%22C%3A%5CProgram%20Files%5CMicrosoft%20Forefront%20Identity%20Manager%5C2010%5CSynchronization%20Service%5CExtensions%5C*.dll%22%3C%2FP%3E%3CBR%20%2F%3E%3CP%20style%3D%22padding-left%3A%2030px%22%3ELocate%20the%20Extension%20you%20just%20Compiled%20and%20select%20and%20highlight%20it%2C%20click%20on%20OK%3C%2FP%3E%3CBR%20%2F%3E%3CP%20style%3D%22padding-left%3A%2030px%22%3EIt%20should%20now%20be%20listed%20in%20the%20Rules%20Extension%20Name%20section.%3C%2FP%3E%3CBR%20%2F%3E%3CP%20style%3D%22padding-left%3A%2030px%22%3EClick%20on%20OK%20to%20complete%20and%20save%20the%20configuration.%3C%2FP%3E%3CBR%20%2F%3E%3CP%20style%3D%22padding-left%3A%2030px%22%3EIf%20there%20are%20multiple%20functions%20that%20are%20using%20rules%20extensions%20you%20need%20to%20add%20all%20the%20functions%20to%20a%20single%20.dll.%3C%2FP%3E%3CBR%20%2F%3E%3CP%20style%3D%22padding-left%3A%2030px%22%3E%23%23%20Additional%20information%20on%20%22IMASynchronization.MapAttributesForJoin%20Method%22%26nbsp%3B%20can%20be%20located%20%3CA%20href%3D%22https%3A%2F%2Fmsdn.microsoft.com%2Fen-us%2Flibrary%2Fwindows%2Fdesktop%2Fmicrosoft.metadirectoryservices.imasynchronization.mapattributesforjoin(v%3Dvs.100).aspx%22%20target%3D%22_blank%22%20rel%3D%22noopener%20noreferrer%20noopener%20noreferrer%22%3E%20here%20%3C%2FA%3E%3C%2FP%3E%3CBR%20%2F%3E%3C%2FLINGO-BODY%3E%3CLINGO-TEASER%20id%3D%22lingo-teaser-974352%22%20slang%3D%22en-US%22%3EFirst%20published%20on%20MSDN%20on%20Feb%2008%2C%202016%20Update%201%2F19%2F2017When%20configuring%20your%20%22Join%20Logic%22%20via%20a%20Custom%20MA%20Extension%20we%20need%20to%20remember%20to%20try%20and%20keep%20it%20simple%20i%20know%20that's%20not%20always%20possible%20but%20the%20more%20complex%20the%20Join%20Logic%20the%20greater%20the%20risk%20of%20joining%20two%20objects%20up%20incorrectly%2C%20Also%20try%20not%20to%20get%20into%20the%20trap%20of%20trying%20to%20make%20a%20super%20complex%20join%20logic%20to%20cover%20every%20possible%20scenario%2C%20Join%20logic%20should%20not%20be%20a%20replacement%20for%20good%20old%20fashion%20Data%20Clean%20Up.%3C%2FLINGO-TEASER%3E%3CLINGO-LABS%20id%3D%22lingo-labs-974352%22%20slang%3D%22en-US%22%3E%3CLINGO-LABEL%3Ejoin%20logic%3C%2FLINGO-LABEL%3E%3CLINGO-LABEL%3Ema%20extensions%3C%2FLINGO-LABEL%3E%3CLINGO-LABEL%3Emapattributesforjoin%3C%2FLINGO-LABEL%3E%3CLINGO-LABEL%3Erules%20extension%3C%2FLINGO-LABEL%3E%3C%2FLINGO-LABS%3E
Microsoft
First published on MSDN on Feb 08, 2016
Update 1/19/2017
When configuring your "Join Logic" via a Custom MA Extension we need to remember to try and keep it simple i know that's not always possible but the more complex the Join Logic the greater the risk of joining two objects up incorrectly, Also try not to get into the trap of trying to make a super complex join logic to cover every possible scenario, Join logic should not be a replacement for good old fashion Data Clean Up. Yes using code can and will make Data Clean up easier but if you have 2 million objects and there is one object that has no real data to be used for joining do you waste countless hours to come up with logic to allow that 1 object to join up with something or do you find that object after and just clean it up at the source.
by modifying the following section you can build a more advance Join Logic, the below code is referenced from the following post Rules Extension -MAExtension

void IMASynchronization.MapAttributesForJoin (string FlowRuleName, CSEntry csentry, ref ValueCollection values)
{
//
// TODO: write join mapping code
//
throw new EntryPointNotImplementedException();
}

If you would like to join objects from a Source Directory that has samAccountNames with the format that includes "SP_" added to the accountName from other directories.
in a Disaster Recovery Scenario where you have to rebuild the Metaverse and join objects back up.
the following piece of code would remove "SP_" from the samAccountName of the source object and than attempt to join to an object in the metaverse with the accountName that matches the sAMAccountName of the source object minus the "SP_"
Example A
void IMASynchronization.MapAttributesForJoin (string FlowRuleName, CSEntry csentry, ref ValueCollection values)
{
//
// TODO: write join mapping code
//
values.Add(csentry["samAccountName"].StringValue.Replace("SP_", ""));
//throw new EntryPointNotImplementedException();
}

The problem with the above code is, I left no room for addition Join logic. If I wanted to use the Same extension across several Management Agents each with their own unique Join Statement I would need to modify the code like the following example
Example B
void IMASynchronization.MapAttributesForJoin(string FlowRuleName, CSEntry csentry, ref ValueCollection values)

{


switch (FlowRuleName)


{


case "SPAccountName":


values.Add(csentry["samAccountName"].StringValue.Replace("SP_", ""));


break;


case "BuildAccountName":


if (csentry["accountName"].IsPresent)


{


values.Add(csentry["accountName"].StringValue);


}


else if (csentry["firstName"].IsPresent && csentry["lastName"].IsPresent)


{


values.Add(csentry["firstName"].StringValue + "." + csentry["lastName"].StringValue);


}


break;


}


}


Example A would require the MA Join Logic to be configured like

joinLogicEXA
Example B would use the FlowRuleName making it easier to manage
joinLogicEXB

Once the code has been compiled See Rules Extensions - Build and Compile
Right Click on the Management Agent that the extension is for and click on Properties
in this example we wrote an extension for Join Logic so we will click on Configure Join and Projection Rules
Select the object type you wish to configure the Join Rule for, in this example we chose group.
now Select New Join Rule,
In the Data Source attribute: section we selected sAMAccountName
for Mapping Type we selected Rules Extension
For Metaverse object type: select the object type that you wish to join to in the metaverse do not leave as ANY, unless that is what you really need.
and for Metaverse Object type: we selected accountName

Once you have that selected click on Add Condition, you may get the following message about joining non-indexed
Click on OK
Now in the next window you need to define context or function in which will be called in the rules extension that will perform the action you desire.

If you dont know what it is open up the extension again in Visual Studios


In this example we will use IMASynchronization.MapAttributesForJoin


Remove the value in the window


now add the function name in this example we will use "IMASynchronization.MapAttributesForJoin" it should look like the following


Click on OK


At this point if you click on OK you will probably receive the following message unless you have the rules extension selected under Configure Extensions


When you click on OK from this window you should be directed to the Configure Extensions Window


Click on Select next to the Rules Extension at the top


This will open up a window which will display all .dll files within the default extensions directory "C:\Program Files\Microsoft Forefront Identity Manager\2010\Synchronization Service\Extensions\*.dll"


Locate the Extension you just Compiled and select and highlight it, click on OK


It should now be listed in the Rules Extension Name section.


Click on OK to complete and save the configuration.


If there are multiple functions that are using rules extensions you need to add all the functions to a single .dll.


## Additional information on "IMASynchronization.MapAttributesForJoin Method"  can be located here