So Long, and Thanks for All the Fish
2 years ago
Publishing
call iisreset
xcopy "$(TargetPath)" "C:\[CRM INSTALL FOLDER]\Server\bin\assembly" /i /d /y
xcopy "$(TargetDir)$(TargetName).pdb" "C:\[CRM INSTALL FOLDER]\Server\bin\assembly" /i /d /y
crmForm.gi_creditcard.style.display = "none";
var url = prependOrgName("/isv/controls/multipicklist.aspx");
url += "?toentity=gi_creditcard" ;
url += "&toattribute=gi_card";
url += "&fromentity=" + crmForm.ObjectTypeName;
url += "&id=" + (crmForm.ObjectId?crmForm.ObjectId:"");
url += "&orgname=" + ORG_UNIQUE_NAME;
document.all["IFRAME_CreditCards"].src = url;
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<style type="text/css">
.LISTBOX
{
width:100%;
height:103%;
border:0px solid;
}
</style>
<script language="javascript">
MultiPicklist = {};
MultiPicklist.CrmForm = null;
MultiPicklist.Storage = null;
MultiPicklist.OnLoad = function()
{
MultiPicklist.CrmForm = parent.document.all.crmForm;
MultiPicklist.Storage = MultiPicklist.CrmForm.<%=Entity2Name%>;
MultiPicklist.CrmForm.attachEvent( "onsave" , MultiPicklist.OnSave );
}
MultiPicklist.OnSave = function()
{
var items = "";
var MultiBox = document.all.MultiBox;
for( var i = 0 ; i < MultiBox.options.length ; i++ )
{
if( MultiBox.options[i].selected == true )
items += MultiBox.options[i].value + ",";
}
MultiPicklist.Storage.DataValue = items.replace(/,$/i,"");
}
</script>
</head>
<body leftmargin="0" onload="MultiPicklist.OnLoad()" scroll="no" topmargin="0">
<form id="form1" runat="server">
<ASP:LISTBOX CSSCLASS="listbox" ID="MultiBox" SELECTIONMODE="Multiple" RUNAT="server">
</ASP:LISTBOX>
</form>
</body>
</html>
using System;
using System.Data;
using System.Configuration;
using System.Collections;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using System.Xml;
using System.Text;
using Microsoft.Crm.Sdk;
using Microsoft.Crm.Sdk.Query;
using Microsoft.Crm.SdkTypeProxy;
namespace Controls
{
public partial class multipicklist : System.Web.UI.Page
{
/// <summary>
/// Current Organizaton Name
/// </summary>
private String OrganizationName;
/// <summary>
/// The Primary Entity (contact) ObjectId (crmForm.ObjectId)
/// </summary>
private Guid ObjectId;
/// <summary>
/// The Primary Entity (contact) Name (typename)
/// </summary>
private String Entity1Name;
/// <summary>
/// The Related N:N Entity (gi_creditcard) Name
/// This should also be the name of the transport attribute
/// on the Primary Entity (gi_creditcard attribute on contact entity)
/// </summary>
protected String Entity2Name;
/// <summary>
/// The Related Entity PrimaryField Name (gi_card)
/// This is the Picklist Option Text
/// </summary>
private String Entity2TextAttribute;
/// <summary>
/// The Primary Entity PrimaryKey Name (contactid)
/// </summary>
private String Entity1KeyAttribute;
/// <summary>
/// The Related N:N Entity PrimaryKey Name (gi_creditcardid)
/// </summary>
private String Entity2KeyAttribute;
/// <summary>
/// CrmService
/// </summary>
private CrmService Service;
protected void Page_Load(object sender, EventArgs e)
{
Page_ValidateParameters();
Page_CreateService();
Page_RetrievePicklistOptions();
Page_SetSelectedOptions();
}
/// <summary>
/// Retrieve Options From Relationship Entity Using Fetch Message
/// And Set the Listbox Selected Items
/// </summary>
private void Page_SetSelectedOptions()
{
if (!ObjectId.Equals(Guid.Empty))
{
String relationShipName = String.Format("gi_{0}_{1}", Entity2Name, Entity1Name);
StringBuilder fetchXml = new StringBuilder();
fetchXml.Append("<fetch mapping='logical'>");
fetchXml.Append("<entity name='").Append(relationShipName).Append("'>");
fetchXml.Append("<all-attributes />");
fetchXml.Append("<filter>");
fetchXml.Append("<condition attribute='contactid' operator='eq' value ='");
fetchXml.Append(ObjectId).Append("' />");
fetchXml.Append("</filter>");
fetchXml.Append("</entity>");
fetchXml.Append("</fetch>");
String resultXml = Service.Fetch(fetchXml.ToString());
XmlDocument fetchResult = new XmlDocument();
fetchResult.LoadXml(resultXml);
XmlNodeList relatedResults = fetchResult.SelectNodes("resultset/result");
foreach (XmlElement item in relatedResults)
{
XmlElement Entity2KeyAttributeNode = (XmlElement)item.SelectSingleNode(Entity2KeyAttribute);
ListItem CurrentItem = MultiBox.Items.FindByValue(Entity2KeyAttributeNode.InnerText.ToLower());
if( CurrentItem != null ) CurrentItem.Selected = true;
}
}
}
/// <summary>
/// Retrieve the listbox options from the related entity using
/// queryexpression and fill the listbox.
/// </summary>
private void Page_RetrievePicklistOptions()
{
QueryExpression creditQuery = new QueryExpression(Entity2Name);
creditQuery.ColumnSet.AddColumn(Entity2TextAttribute);
creditQuery.ColumnSet.AddColumn(Entity2KeyAttribute);
creditQuery.Distinct = true;
creditQuery.Orders.Add(new OrderExpression(Entity2TextAttribute, OrderType.Ascending));
RetrieveMultipleRequest retrieveMultipleRequest = new RetrieveMultipleRequest();
retrieveMultipleRequest.Query = creditQuery;
retrieveMultipleRequest.ReturnDynamicEntities = true;
RetrieveMultipleResponse retrieveMultipleResponse =
(RetrieveMultipleResponse)Service.Execute(retrieveMultipleRequest);
MultiBox.Items.Add( "" );
foreach (DynamicEntity creditcard in retrieveMultipleResponse.BusinessEntityCollection.BusinessEntities)
{
Key key = creditcard.Properties[Entity2KeyAttribute] as Key;
ListItem item = new ListItem(
creditcard.Properties[Entity2TextAttribute] + "",
key.Value.ToString("B"));
MultiBox.Items.Add(item);
}
}
/// <summary>
/// Create the crmservice
/// </summary>
private void Page_CreateService()
{
CrmAuthenticationToken token = new CrmAuthenticationToken();
token.AuthenticationType = 0;
token.OrganizationName = OrganizationName;
Service = new CrmService();
Service.CrmAuthenticationTokenValue = token;
Service.PreAuthenticate = false;
Service.UnsafeAuthenticatedConnectionSharing = true;
Service.Credentials = System.Net.CredentialCache.DefaultCredentials;
Service.Url = String.Format("{0}://{1}:{2}/mscrmservices/2007/crmservice.asmx", Request.Url.Scheme, Request.Url.Host, Request.Url.Port);
}
/// <summary>
/// Validate the listbox control parameters
/// </summary>
private void Page_ValidateParameters()
{
Entity1Name = Request.QueryString["fromentity"];
if (Entity1Name + "" == String.Empty)
throw new Exception("Entity1 Name is Missing");
Entity2Name = Request.QueryString["toentity"];
if (Entity2Name + "" == String.Empty)
throw new Exception("Entity2 Name is Missing");
OrganizationName = Request.QueryString["orgname"];
if (OrganizationName + "" == String.Empty)
throw new Exception("Organization Name is Missing");
ObjectId = Request.QueryString["id"] + "" == String.Empty ? Guid.Empty :
new Guid(Request.QueryString["id"]);
Entity2TextAttribute = Request.QueryString["toattribute"];
if (Entity2TextAttribute + "" == String.Empty)
throw new Exception("Picklist Text Attribute is Missing");
Entity1KeyAttribute = Entity1Name + "id";
Entity2KeyAttribute = Entity2Name + "id";
}
}
}
<Register LogFile="Plug-in Registration Log.txt" Server="http://moss:5555" Org="MicrosoftCRM" Domain="" UserName="administrator">
<Solution SourceType="1" Assembly="MPPlugIn.dll" Id="28f2c17f-2a16-4ce7-9a98-8e627ad2aecf">
<PluginTypes>
<Plugin TypeName="MPPlugIn.MPHandler" FriendlyName="3fe8c6c8-f928-43e3-b2e1-ccb55d651d6c" Id="93ecf707-c794-47df-a76e-9df3a3ee8e00">
<Steps>
<Step PluginTypeName="MPPlugIn.MPHandler" PluginTypeFriendlyName="3fe8c6c8-f928-43e3-b2e1-ccb55d651d6c" CustomConfiguration="" SecureConfiguration="" Description="Create of contact in Parent Pipeline" FilteringAttributes="" ImpersonatingUserId="" InvocationSource="0" MessageName="Create" Mode="0" PrimaryEntityName="contact" SecondaryEntityName="none" Stage="50" SupportedDeployment="0" Rank="1" Id="a0631824-7fc0-dd11-b17c-0003ff2f0264">
<Images>
<Image EntityAlias="gi_gi_creditcard_contact" ImageType="1" MessagePropertyName="Id" Attributes="contactid,gi_creditcard" Id="405a617d-7fc0-dd11-b17c-0003ff2f0264" />
</Images>
</Step>
<Step PluginTypeName="MPPlugIn.MPHandler" PluginTypeFriendlyName="3fe8c6c8-f928-43e3-b2e1-ccb55d651d6c" CustomConfiguration="" SecureConfiguration="" Description="Update of contact in Parent Pipeline" FilteringAttributes="" ImpersonatingUserId="" InvocationSource="0" MessageName="Update" Mode="0" PrimaryEntityName="contact" SecondaryEntityName="none" Stage="50" SupportedDeployment="0" Rank="1" Id="a0d1a8fe-82c0-dd11-b17c-0003ff2f0264">
<Images>
<Image EntityAlias="gi_gi_creditcard_contact" ImageType="2" MessagePropertyName="Target" Attributes="contactid,gi_creditcard" Id="f0d85819-83c0-dd11-b17c-0003ff2f0264" />
</Images>
</Step>
</Steps>
</Plugin>
</PluginTypes>
</Solution>
</Register>
using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.Crm.Sdk;
using Microsoft.Crm.SdkTypeProxy;
namespace MPPlugIn
{
public class MPHandler : IPlugin
{
#region IPlugin Members
/// <summary>
/// A Multipicklist context Object
/// </summary>
public class MPContext
{
/// <summary>
/// MS Context
/// </summary>
public IPluginExecutionContext context;
/// <summary>
/// The Entity 1 (Primary: contact in this case) Primary Key e.g. contactid
/// </summary>
public String Entity1PrimaryAttributeName;
/// <summary>
/// The Entity 2 (related: gi_creditcard in this case) Name
/// </summary>
public String Entity2Name;
/// <summary>
/// An Entity 1 Attribute that is used as a transport form selected options.
/// in this case i called it gi_creditcard (same and the related entity name)
/// You can give it any name you like.
/// </summary>
public String Entity1PicklistOptionsAttribute;
/// <summary>
/// The relationship name of contact and gi_creditcard
/// e.g. gi_gi_creditcard_contact. this is also used as the
/// PreImage and PostImage ALIAS names.
/// </summary>
public String N2NRelationShipName;
/// <summary>
/// Entity 1 (Primary) Name
/// Primary means the entity where the multipicklist is put.
/// Related means the entity from which the multipicklist options are taken.
/// </summary>
private String _Entity1Name;
public String Entity1Name
{
get
{
return this._Entity1Name;
}
set
{
this._Entity1Name = value;
this.Entity1PrimaryAttributeName = value + "id";
}
}
/// <summary>
/// Initialize a new MP context
/// </summary>
/// <param name="context"></param>
public MPContext(IPluginExecutionContext context) {
this.context = context;
}
}
/// <summary>
/// PlugIn Implementation:
/// 1. Create a new MPContext
/// 2. Fill the MPContext parameters
/// 3. Disassociate old options
/// 4. Associate new options
/// </summary>
/// <param name="context"></param>
public void Execute(IPluginExecutionContext context)
{
MPContext mpContext = new MPContext(context);
mpContext.Entity1Name = "contact";
mpContext.Entity2Name = "gi_creditcard";
mpContext.Entity1PicklistOptionsAttribute = "gi_creditcard";
mpContext.N2NRelationShipName = "gi_gi_creditcard_contact";
DisAssociateMultiplePicklist(mpContext);
AssociateMultiplePicklist(mpContext);
}
/// <summary>
/// Retrieves the existing options from the storage (transport) attribute
/// on the primary entity (contact) and call DisassociateEntitiesRequest
/// to remove the association
/// </summary>
/// <param name="context"></param>
private void DisAssociateMultiplePicklist(MPContext context)
{
IPluginExecutionContext msContext = context.context;
/*
Validates that the relationship name (e.g. gi_gi_creditcard_contact)
is the name you gave the PreImage Alias.
*/
if (msContext.PreEntityImages.Properties.Contains(context.N2NRelationShipName) == true)
{
//Retrieve the PreImage dynamic (Primary) entity 1 (contact)
DynamicEntity Entity1 = msContext.PreEntityImages.Properties[context.N2NRelationShipName] as DynamicEntity;
/*
Validates that the image contains the primarykey (contactid) in the property bag.
the contactid represents one side of the link (Moniker).
*/
if (Entity1.Properties.Contains(context.Entity1PrimaryAttributeName) == false)
return;
/* Extract the id (contactid) */
Guid primaryEntityId = ((Key)Entity1.Properties[context.Entity1PrimaryAttributeName]).Value;
/*
If the options (transport) attribute is missing
meaning that the its value is null then exit
*/
if( Entity1.Properties.Contains( context.Entity1PicklistOptionsAttribute ) == false )
return;
/* get the existing options */
String strOptions = Entity1.Properties[context.Entity1PicklistOptionsAttribute] + "";
if (strOptions.Equals(String.Empty)) return;
/* create an option array */
String[] mpOptions = strOptions.Split(',');
/* create a crmservice */
ICrmService Service = msContext.CreateCrmService(true);
/* for each option disassociate (remove) the link */
foreach (String option in mpOptions)
{
Guid relatedEntityId = new Guid(option);
DisassociateEntitiesRequest assocRequest = new DisassociateEntitiesRequest();
assocRequest.Moniker1 = new Moniker(context.Entity1Name, primaryEntityId);
assocRequest.Moniker2 = new Moniker(context.Entity2Name, relatedEntityId);
assocRequest.RelationshipName = context.N2NRelationShipName;
Service.Execute(assocRequest);
}
}
}
/// <summary>
/// Associates the new selected options with the primary entity (contact)
/// using the selected options taken from the PostImage Propery bag.
/// See DisAssociateMultiplePicklist method for code details.
/// </summary>
/// <param name="context"></param>
private void AssociateMultiplePicklist( MPContext context )
{
IPluginExecutionContext msContext = context.context;
if (msContext.PostEntityImages.Properties.Contains(context.N2NRelationShipName) == true)
{
DynamicEntity Entity1 = msContext.PostEntityImages.Properties[context.N2NRelationShipName] as DynamicEntity;
if (Entity1.Properties.Contains(context.Entity1PrimaryAttributeName) == false)
return;
Guid primaryEntityId = ((Key)Entity1.Properties[context.Entity1PrimaryAttributeName]).Value;
if (Entity1.Properties.Contains(context.Entity1PicklistOptionsAttribute) == false)
return;
String strOptions = Entity1.Properties[context.Entity1PicklistOptionsAttribute] + "";
if (strOptions.Equals(String.Empty)) return;
String[] mpOptions = strOptions.Split(',');
ICrmService Service = msContext.CreateCrmService(true);
foreach (String option in mpOptions)
{
Guid relatedEntityId = new Guid(option);
AssociateEntitiesRequest assocRequest = new AssociateEntitiesRequest();
assocRequest.Moniker1 = new Moniker(context.Entity1Name, primaryEntityId);
assocRequest.Moniker2 = new Moniker(context.Entity2Name, relatedEntityId);
assocRequest.RelationshipName = context.N2NRelationShipName;
Service.Execute( assocRequest );
}
}
}
#endregion
}
}
Spread dynamics magic when ever possible. Share GI knowledge and help others achieve outstanding results with their CRM implementations. In my blog I’ll post many interesting examples and reveal many of dynamics “Unleashed” secrets. |