Wednesday, 2 December 2015

CRM 2011 Plugin Assembly not updating with new code

With CRM 2011, recently had a really odd situation, deploying the CRM 2011 plugin assembly wasn't overwriting the old code in the CRM database.  Even after I tried de-registering the assembly and redeploying the old code was still used.
How I fixed this was incrementing the assembly version, it then updated the plugin assembly properly in the database.

CRM 2011 - Ghost Dependencies

Long time since the last post sorry, but figured I would post about something odd I found in our CRM 2011 environment here.

When we were trying to delete an entity we were getting a message that we couldn't delete the entity due to dependencies showing a blank list!

After a lot of searching we found the error to be related to some orphaned records in the ReportEntityBase table that were set as a managed solution component.

I first attempted to remove this the supported way to no avail so had to come up with a 'hack' to get them out of the database.  I have no idea how you would do this with Cloud CRM.

First step was to backup the data about to be removed, just in case we had some downstream impact.

--Back the Dependencies, nodes and offending records
SELECT db.* INTO DependencyBase_backup FROM DependencyBase db 
JOIN DependencyNodeBase dnb ON dnb.DependencyNodeId = db.DependentComponentNodeId
JOIN ReportEntity rpe ON rpe.ReportEntityId = dnb.ObjectId
WHERE ComponentType = 32 and rpe.ObjectTypeCode = 10001

SELECT dnb.* INTO DependencyNodeBase_backup FROM DependencyNodeBase dnb
JOIN ReportEntity rpe ON dnb.ObjectId = rpe.ReportEntityId
WHERE ComponentType = 32 and rpe.ObjectTypeCode = 10001 

SELECT * INTO ReportEntityBase_backup FROM ReportEntityBase WHERE ObjectTypeCode = 10001

Next delete out the dependency records pointing to the problem records
 
DELETE db FROM DependencyBase db 
JOIN DependencyNodeBase dnb ON dnb.DependencyNodeId = db.DependentComponentNodeId
JOIN ReportEntity rpe ON rpe.ReportEntityId = dnb.ObjectId
WHERE ComponentType = 32 and rpe.ObjectTypeCode = 10001

Now delete the joining node records
 
DELETE dnb FROM DependencyNodeBase dnb
JOIN ReportEntity rpe ON dnb.ObjectId = rpe.ReportEntityId
WHERE ComponentType = 32 and rpe.ObjectTypeCode = 10001 
Delete the Orphaned records
DELETE FROM ReportEntityBase WHERE ObjectTypeCode = 10001 

Friday, 7 June 2013

CRM 2011 HTTPS Endpoint with SSIS and ADFS

After quite a bit of work, I finally managed to get a connection working with the CRM 2011 Https endpoint, using no config file, below is the code I used to achieve this.

private static IOrganizationService GetHttpsCRMService(string serverUrl, string adfsUrl, string username, string password)
        {
            Uri organizationUriIFD = new Uri(serverUrl + "/XRMServices/2011/Organization.svc");
                        
            EndpointAddress endpointAddress = new EndpointAddress(organizationUriIFD);

            CustomBinding customBinding = new CustomBinding();
            customBinding.Name = "CustomBinding";
            
            var tsBE = new TransportSecurityBindingElement();
            tsBE.AllowInsecureTransport = false;
            tsBE.IncludeTimestamp = true;


            EndpointAddress usernameMixed = new EndpointAddress(adfsUrl + "/adfs/services/trust/13/usernamemixed");
            WS2007HttpBinding wsbinding = new WS2007HttpBinding(SecurityMode.TransportWithMessageCredential);
            wsbinding.MaxReceivedMessageSize = 65536;
            wsbinding.MaxBufferPoolSize = 524288;
            wsbinding.Security.Transport.ClientCredentialType = HttpClientCredentialType.None;
            wsbinding.Security.Message.ClientCredentialType = MessageCredentialType.UserName;
            wsbinding.Security.Message.EstablishSecurityContext = false;

            IssuedSecurityTokenParameters stP = new IssuedSecurityTokenParameters(null, usernameMixed, wsbinding);
            stP.IssuerMetadataAddress = new EndpointAddress(new Uri(adfsUrl + "/adfs/services/trust/mex"));

            var additionalRquestParameters =
                @"<trust:SecondaryParameters xmlns:trust='http://docs.oasis-open.org/ws-sx/ws-trust/200512'>" +
                @"    <trust:KeyType xmlns:trust='http://docs.oasis-open.org/ws-sx/ws-trust/200512'>http://docs.oasis-open.org/ws-sx/ws-trust/200512/SymmetricKey</trust:KeyType>" +
                @"    <trust:KeySize xmlns:trust='http://docs.oasis-open.org/ws-sx/ws-trust/200512'>256</trust:KeySize>" +
                @"    <trust:Claims Dialect='http://schemas.xmlsoap.org/ws/2005/05/identity' xmlns:trust='http://docs.oasis-open.org/ws-sx/ws-trust/200512'>" +
                @"        <wsid:ClaimType Uri='http://schemas.xmlsoap.org/ws/2005/05/identity/claims/upn' xmlns:wsid='http://schemas.xmlsoap.org/ws/2005/05/identity' />" +
                @"    </trust:Claims>" +
                @"    <trust:KeyWrapAlgorithm xmlns:trust='http://docs.oasis-open.org/ws-sx/ws-trust/200512'>http://www.w3.org/2001/04/xmlenc#rsa-oaep-mgf1p</trust:KeyWrapAlgorithm>" +
                @"    <trust:EncryptWith xmlns:trust='http://docs.oasis-open.org/ws-sx/ws-trust/200512'>http://www.w3.org/2001/04/xmlenc#aes256-cbc</trust:EncryptWith>" +
                @"    <trust:SignWith xmlns:trust='http://docs.oasis-open.org/ws-sx/ws-trust/200512'>http://www.w3.org/2000/09/xmldsig#hmac-sha1</trust:SignWith>" +
                @"    <trust:CanonicalizationAlgorithm xmlns:trust='http://docs.oasis-open.org/ws-sx/ws-trust/200512'>http://www.w3.org/2001/10/xml-exc-c14n#</trust:CanonicalizationAlgorithm>" +
                @"    <trust:EncryptionAlgorithm xmlns:trust='http://docs.oasis-open.org/ws-sx/ws-trust/200512'>http://www.w3.org/2001/04/xmlenc#aes256-cbc</trust:EncryptionAlgorithm>" +
                @"</trust:SecondaryParameters>";

            System.Xml.XmlDocument additionalParamDoc = new System.Xml.XmlDocument();
            additionalParamDoc.LoadXml(additionalRquestParameters);

            stP.AdditionalRequestParameters.Add(additionalParamDoc.DocumentElement);
            stP.RequireDerivedKeys = false;
            stP.KeySize = 256;
            stP.KeyType = System.IdentityModel.Tokens.SecurityKeyType.SymmetricKey;
            
            tsBE.LocalClientSettings.DetectReplays = false;
            tsBE.LocalServiceSettings.DetectReplays = false;
            tsBE.EndpointSupportingTokenParameters.Endorsing.Add(stP);



            customBinding.Elements.Add(tsBE);

            var textEncoding = new System.ServiceModel.Channels.TextMessageEncodingBindingElement();
            var httpsTransport = new System.ServiceModel.Channels.HttpsTransportBindingElement();

            customBinding.Elements.Add(textEncoding);

            customBinding.Elements.Add(httpsTransport);
            customBinding.ReceiveTimeout = new TimeSpan(0, 10, 0);
            customBinding.SendTimeout = new TimeSpan(0, 1, 0);
            customBinding.OpenTimeout = new TimeSpan(0, 1, 0);
            customBinding.CloseTimeout = new TimeSpan(0, 1, 0);

            var contract = new System.ServiceModel.Description.ContractDescription("IOraganizationService", "http://schemas.microsoft.com/xrm/2011/Contracts/Services");
            contract.ContractType = typeof(IOrganizationService);

            OrganizationServiceClient osClient = new OrganizationServiceClient(customBinding, endpointAddress);
            osClient.ClientCredentials.UserName.UserName = username;
            osClient.ClientCredentials.UserName.Password = password;
            
            return (IOrganizationService)osClient;
        }

Tuesday, 5 March 2013

CRM 2011 Date Only Issue Plugin

As explained quite well in Kelvin's blog, CRM 2011 handles Date Only fields in a strange way.  So I have developed a plugin that will get round this.

The code for this is below and it should be deployed pre validation for the entities you wish to use it with, create or update.


/// <summary>
/// Fix for getting round the timezone issues with date only fields
/// </summary>
public class TimeZoneFix : IPlugin
{
    public void Execute(IServiceProvider serviceProvider)
    {
        //Get an instance of the helper class.
        PluginHelper helper = new PluginHelper(serviceProvider);
        helper.tracer.Trace("Loaded Helper");
        if (helper.targetEntity.Attributes.Any(a => a.Value != null && a.Value.GetType() == typeof(DateTime)))
        {
            IOrganizationService service = helper.service;
            helper.tracer.Trace("Building Request");
            RetrieveEntityRequest request = new RetrieveEntityRequest();
            request.LogicalName = helper.context.PrimaryEntityName;
            request.EntityFilters = EntityFilters.Attributes;
            RetrieveEntityResponse response =  (RetrieveEntityResponse)service.Execute(request);
            if (response != null && response.EntityMetadata != null)
            {
                List<KeyValuePair<string, object>> attribs = helper.targetEntity.Attributes.Where(a => a.Value != null && a.Value.GetType() == typeof(DateTime)).ToList();
                foreach (var att in attribs)
                {
                    DateTime date = (DateTime)helper.targetEntity[att.Key];
                    DateTime localDate = date.ToLocalTime();
                    TimeSpan dateDiff = localDate - date;
                    //Get the attribute metadata
                    AttributeMetadata meta = response.EntityMetadata.Attributes.FirstOrDefault(am => am.LogicalName.ToLower().Equals(att.Key));
                    //Check in the attribute metadata if the attribute is a date only.
                    if (meta != null && meta.AttributeType != null &&
                        meta.AttributeType == AttributeTypeCode.DateTime &&
                        ((DateTimeAttributeMetadata)meta).Format == DateTimeFormat.DateOnly)
                    {
                        helper.targetEntity[att.Key] = localDate.AddHours(dateDiff.Hours + 10);
                    }
                }
            }
        }
    }
}

Friday, 21 December 2012

AX Dynamics Connector

I recently hit this random error with the Microsoft AX Dynamics connector when try to configure the CRM org.

The following exception occurred while attempting to retrieve all companies: Could not load type 'Microsoft.Xrm.Sdk.Client.IServiceManagement`1' from assembly 'Microsoft.Xrm.Sdk, Version=5.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35'.

All I did to fix it was move the Microsoft.Xrm.Sdk.dll from the C:\Program Files (x86)\Microsoft Dynamics\Microsoft Dynamics Adapter\Adapters\Microsoft.Dynamics.Integration.Adapters.Crm2011 folder and copy it into the root folder for the dynamics adapter install.

It seems the installer may have not moved that required file and the configuration wizard is from within that folder.

Monday, 10 September 2012

Tech Ed 2012

It has been a long time since my last post, anyhow currently I'm at Tech Ed and I figured I would blog about a cool session I attended regarding CRM 2011 and tips and tricks.

Gayan Perera from Magnetism ran the session and mentioned a really cool generation tool to replace the crmsvcutil tool from the sdk.  It has now been released on code plex and allows generation of code using templating, this is a lot more flexible than the current tool and easier to work with.  Check it out here: http://crm2011codegen.codeplex.com/

The other cool information was turning managed solutions into unmanaged solutions using SQL, it makes the org unusable but if done on an import of a copied database the solution can be exported and imported where required.

Kudos to Gayan and Thomas getting this SQL running:

declare @solutionId uniqueidentifier, @systemSolutionId uniqueidentifier -- specify the uniquename of the managed solution you'd like to unmanage
select @solutionId = solutionid from SolutionBase where UniqueName='Your Solution Name'
select @systemSolutionId = solutionid from SolutionBase where UniqueName='Active'

declare @sql nvarchar(max)
select @sql ='update PublisherBase set IsReadonly=0 where PublisherId in (select PublisherId from SolutionBase where SolutionId=N'''+cast(@solutionId as nvarchar(100))+''')'
print (@sql)
exec (@sql)

declare @isManagedTables table (id int identity, name nvarchar(100))
declare @count int, @currentTable nvarchar(100), @currentM bit, @currentS bit
-- go through all the tables that have the ismanaged/solutionid flag, find the related records for the current solution and move them to the crm active solution.
insert into @isManagedTables (name)
select name from sysobjects where id in 
(select id from syscolumns where name in ('IsManaged')) 
and type='U'
order by name
select @count = count(*) from @isManagedTables
while (@count > 0)
begin
select @currentTable =name from @isManagedTables where id=@count
select @sql ='update ' + @currentTable + ' set IsManaged=0 where SolutionId=N''' + cast(@solutionId as nvarchar(100)) + ''''
print (@sql)
exec (@sql)
select @count = @count -1, @currentTable = NULL
end

declare @isSolutionIdTables table (id int identity, name nvarchar(100))
insert into @isSolutionIdTables (name)
select name from sysobjects where id in 
(select id from syscolumns where name in ('SolutionId')) 
and type='U' and name not in ('SolutionComponentBase') -- ignore this table because it doesn't make a difference. it does cause dependency errors on the exported solution but we can manually edit the xml for that.
order by name

select @count = count(*) from @isSolutionIdTables
while (@count > 0)
begin
select @currentTable =name from @isSolutionIdTables where id=@count
select @sql ='update ' + @currentTable + ' set SolutionId=N''' + cast(@systemSolutionId as nvarchar(100)) + ''' where SolutionId=N''' + cast(@solutionId as nvarchar(100)) + ''''
print (@sql)
exec (@sql)
select @count = @count -1, @currentTable = NULL
end

-- Remove dependencies BaseSolutionId
delete from DependencyBase where DependentComponentNodeId in (
select DependencyNodeId from DependencyNodeBase where BaseSolutionId=@solutionId
)
alter table DependencyBase NOCHECK CONSTRAINT dependencynode_ancestor_dependency 
delete from DependencyNodeBase where BaseSolutionId=@solutionId
alter table DependencyBase CHECK CONSTRAINT dependencynode_ancestor_dependency

-- Remove dependencies TopSolutionId
delete from DependencyBase where DependentComponentNodeId in (
select DependencyNodeId from DependencyNodeBase where TopSolutionId=@solutionId
)
alter table DependencyBase NOCHECK CONSTRAINT dependencynode_ancestor_dependency 
delete from DependencyNodeBase where TopSolutionId=@solutionId
alter table DependencyBase CHECK CONSTRAINT dependencynode_ancestor_dependency

Saturday, 30 April 2011

Crm 2011 Rollup 1 Subgrids

If you install rollup 1 for CRM 2011 and suddenly notice that subgrids are no longer working for Windows XP machines, ensure that you have 'Enable native XMLHTTP support' turned on in the internet explorer settings.
The specific issue we noticed was just a Grey outline of where the subgrid should be and a js error when closing the form.