This is the second time recently I came across this requirement so I guess others need it too. This post describes how to set a destintation node to null based upon a condition.
My situation was the source node contained a DateTime which was either valid or set to a zero length string. As some of you will know setting a date to a zero length string will actually set the date to 0001-01-01. That is the date when the world began, allegedly. My destination node is a date field too so I want to ignore the invalid date. But here's the thing - I need to set the target node to null because I need the node present in the output.
The solution is to use a logical operator (= or <>) and a value mapping functoid. In my case I am using a Script functoid to convert the source node value from DateTime to Date. So the Script output is a date string. By the way if you are wondering why I just don't test for this in the Script and set the return parameter to null, its becasue this doesn't work!
The <> functoid checks if the output is 0001-01-01 and sends true or false to the Value Mapping Functoid. As you can see I added 0001-01-01 as a constant for the second parameter. Remember this is a Not Equal operator so it will return true if its a valid date and false if it is 0001-01-01.
The magic happens in the Value Flattening functoid. The description explains what it does. If the value of the first input parameter is true then the value of the second input parameter is returned. It should add if the first input parameter is false, then the destination node is set to null.
So all you have to do is select the correct logical operator (either = or <>) so that its output is true if you want to pass the value to the destination and false when you want to set it to null. But be sure you have the parameters the right way round. The logical operator needs to be at the top, the value of the source node is below.
No Intelligent Life
Tuesday, November 29, 2011
Saturday, November 19, 2011
Dynamics CRM 2011 Date Picker Displays US format
This post will only help if you are using the On Premise version - I don't have a solution for the Online version. BTW, I was using SQL Server 2008 R2.
But when you select a date, the picker puts the date in as US format. It will still filter the data correctly but I wanted UK format displayed.
The clue came from this blog. Now in fact when I ran my report in Report Server (i.e. outside CRM) the date format displays correctly.
So I finally found the solution. You need to add Culture="en-GB" to the reportviewer.aspx page located at C:\Program Files\Microsoft Dynamics CRM\CRMWeb\CRMReports\rsviewer. Note its the rsviewer directory not the viewer directory. I added it to the end of the first line - the <%@ Page declaration.
Then the date displayed in UK format in CRM.
If you add date parameters to a report that you want to run in Dynamics CRM 2011 then you get prompted to enter the dates. If you set the parameters as type DateTime then a date picker is also displayed.
But when you select a date, the picker puts the date in as US format. It will still filter the data correctly but I wanted UK format displayed.
The clue came from this blog. Now in fact when I ran my report in Report Server (i.e. outside CRM) the date format displays correctly.
Then the date displayed in UK format in CRM.
Labels:
Date Picker,
Dynamics CRM 2011,
SQL Server 2008 R2,
SSRS,
US Format
Wednesday, November 16, 2011
Filtered Fetch XML Reports for CRM 2011 On-line
I found very few blogs that explained how to create a Filtered Report for CRM 2011 using Fetch XML. My approach had been to use Advanced Find to create the Fetch XML and then copy and paste that into a Report in Business Intelligence Development Studio. Now that works fine but when you publish the report to CRM it will only run on all records of the entity, it does not work on selected rows or on a single entity record. The report just does not show up as selectable on the entity view of on the entity form.
The missing attributes are on the the entity element of the Fetch XML. Mine is a custom entity called new_identifiedneed and so I need to change
<entity name="new_identifiedneed">
to
<entity="new_identifiedneed" enableprefiltering="1" prefilterparametername="CRM_Filterednew_identifiedneed">
Now what is not made clear is that setting the correct prefilterparametername is crucial. It needs to be the name of the Filtered View for the entity prefixed by CRM_ (not CRMAF_ as for SQL based reports).
If you do this on the query you will find that it will automatically add a parameter to your dataset. When you run the Query you will get this prompt for the parameter.
Don't bother with entering a value, just click OK and you should get unfiltered results.
Check out the parameters on the DataSet which should look like this:
If that is present you're home free. Make the report look pretty, build it to create the rdl and then load it into CRM. When you add the report be sure to set the Related Records (Identified Needs in my case) and select the Display in properties to include both the Form and the List.
Now go to the entity view and select on or more records. Click on the Run Report icon on the ribbon and you should see your report. When you run it on Selected Records you should see what you wanted. The same applies when you open a form on a selected entity record.
Happy Reporting!
BTW I found this out by using the Report Wizard for ad hoc reports in CRM. It will not only create the appropriate Fetch XML but gives you an RDL file that you can open up and play with in Business Intelligence Development Studio.
The missing attributes are on the the entity element of the Fetch XML. Mine is a custom entity called new_identifiedneed and so I need to change
<entity name="new_identifiedneed">
to
<entity="new_identifiedneed" enableprefiltering="1" prefilterparametername="CRM_Filterednew_identifiedneed">
Now what is not made clear is that setting the correct prefilterparametername is crucial. It needs to be the name of the Filtered View for the entity prefixed by CRM_ (not CRMAF_ as for SQL based reports).
If you do this on the query you will find that it will automatically add a parameter to your dataset. When you run the Query you will get this prompt for the parameter.
Don't bother with entering a value, just click OK and you should get unfiltered results.
Check out the parameters on the DataSet which should look like this:
If that is present you're home free. Make the report look pretty, build it to create the rdl and then load it into CRM. When you add the report be sure to set the Related Records (Identified Needs in my case) and select the Display in properties to include both the Form and the List.
Now go to the entity view and select on or more records. Click on the Run Report icon on the ribbon and you should see your report. When you run it on Selected Records you should see what you wanted. The same applies when you open a form on a selected entity record.
Happy Reporting!
BTW I found this out by using the Report Wizard for ad hoc reports in CRM. It will not only create the appropriate Fetch XML but gives you an RDL file that you can open up and play with in Business Intelligence Development Studio.
Monday, November 14, 2011
Problems Configuring BizTalk 2010
I had two problems configuring BizTalk 2010 in a distributed environment I thought I would share. The first was a problem on assigning the SSO Administrators group. Since I was using a distributed environment I had to replace the local group name with the domain group name. When I did so I got the warning icon with the detail.
Failed to add the user 'Domain\btsadmin' to the domain group 'Domain\SSO Administrators'
Now this user was already in the group and I was logged on as a Domain Admin so the message could not be correct.
There are blogs that say you need to re-register SSOSQL.DLL that is located in C:\Program Files\Common Files\Enterprise Single Sign-On (and also in the sub-directory \Win32) but I had done that. The answer was: delete the existing entry and manually type in the account name -DON'T click on the ellpises (...). Stupid error I know, but that fixes it.
The second problem arose when configuring BAM. I had installed the pre-requisites including SQLServer2005_NS_x64.MSI as well as installing SQL Server 2008 R2 Integration Services locally which is a requirement. But I got the following error when applying the configuration
Could not load file or assembly 'Microsoft.SqlServer.Instapi, Version=9.0.242.0, Culture=neutral, PublicKeyToken=89845dcd8080cc91' or one of its dependencies. The system cannot find the file specified.
Sure enough, this DLL was not in the GAC, although the 10.0 one was there.
Turns out you need to install the correct versions of the MSIs - I had somehow managed to download the wrong ones. They correct ones are:
sqlncli_x64.msi 6430KB
SQLServer2005_NS_x64.msi 3337KB
SQLServer2005_XMO_x64.msi 15066KB
sqlxml.msi 06 12683KB
They can be downloaded from here
Aftr that, the configuration went smoothly
Failed to add the user 'Domain\btsadmin' to the domain group 'Domain\SSO Administrators'
Now this user was already in the group and I was logged on as a Domain Admin so the message could not be correct.
There are blogs that say you need to re-register SSOSQL.DLL that is located in C:\Program Files\Common Files\Enterprise Single Sign-On (and also in the sub-directory \Win32) but I had done that. The answer was: delete the existing entry and manually type in the account name -DON'T click on the ellpises (...). Stupid error I know, but that fixes it.
The second problem arose when configuring BAM. I had installed the pre-requisites including SQLServer2005_NS_x64.MSI as well as installing SQL Server 2008 R2 Integration Services locally which is a requirement. But I got the following error when applying the configuration
Could not load file or assembly 'Microsoft.SqlServer.Instapi, Version=9.0.242.0, Culture=neutral, PublicKeyToken=89845dcd8080cc91' or one of its dependencies. The system cannot find the file specified.
Sure enough, this DLL was not in the GAC, although the 10.0 one was there.
Turns out you need to install the correct versions of the MSIs - I had somehow managed to download the wrong ones. They correct ones are:
sqlncli_x64.msi 6430KB
SQLServer2005_NS_x64.msi 3337KB
SQLServer2005_XMO_x64.msi 15066KB
sqlxml.msi 06 12683KB
They can be downloaded from here
Aftr that, the configuration went smoothly
Sunday, October 9, 2011
There is a problem communicating with the Microsoft Dynamics CRM Server
I was trying to configure the CRM Client for Outlook by adding an organization and I ran into this error.
Now I had just deployed my customizations and I was able to access CRM using IE from the same client and could see all my customizations. I didn't get any errors when importing or publishing the customizations.
What I tried was to create a brand new organization with no customizations and I was able to add that organization to the Outlook client without problems. So the issue was that there was something in the customizations that was causing an error only in the Outlook client. After several days of effort we tracked it down to a site map customization.
We had added a custom section under Workplace that had some links to a particular view of the Account entity. BAD IDEA. That won't work in the Outlook client. After removing the link I was able to connect to my organization without this error.
Some things you find out the hard way.
Now I had just deployed my customizations and I was able to access CRM using IE from the same client and could see all my customizations. I didn't get any errors when importing or publishing the customizations.
What I tried was to create a brand new organization with no customizations and I was able to add that organization to the Outlook client without problems. So the issue was that there was something in the customizations that was causing an error only in the Outlook client. After several days of effort we tracked it down to a site map customization.
We had added a custom section under Workplace that had some links to a particular view of the Account entity. BAD IDEA. That won't work in the Outlook client. After removing the link I was able to connect to my organization without this error.
Some things you find out the hard way.
Saturday, September 10, 2011
Consume a WCF service that uses Federated Security
This post is not about Active Directory Federated Security, but it is about using a custom Security Token Service (STS) to create a token. I needed to connect to a third party web service that used Federated Security. Now they supported ADFS but I only needed to access using a single account and I really didn't want to set up ADFS just for that. But I could use a custom STS service to create the token and avoid all the infrastruture overhead of ADFS.
Setup begins with the third party sending me the url to their STS and a copy of the public key certificate they will use to sign their token. I also need to have the url to their web service I want to call.
I'll say right away I'm no expert on this. There are examples in the Windows Identity SDK and that is a good starting point. The way it would work is my client application (a Windows Service) would call a local STS and pass it a username and password. My STS would check the credentials and if OK issue a token. Now the token is signed and encrypted by my X509 certificate so I have to get one of those to begin with. I need to install my X509 certificate in the Personal store of the computer I run the code on.
Start MMC, add the Certficate add-in and select the Local Computer. Navigate to the Personal node, and Certificates, right click and import my X509 certificate. Since I am running my Windows Service under the Network Service account I need to assign permissions. On the Certificate, right click, select All Tasks then Manage Private key. On the Security tab, add Network Service and give it full permissions. I can also add the thrid party's certificate here too - it is imported into the Personal Certificate store in the same way but since they gave me the public key, I don't need to bother with the permissions step (its not available anyway).
I also need to send the public key of my certificate to the third party. Right click on the certificate, select Export and choose the option to export the public key only.
Now the token issued by my STS contains a claim, in my case it is simply the role of Reader. I then pass my token to the third party's STS. These guys will want to check the token is from me and they use the certificate I sent them to do so. They check the claim, and if all is well issue me a token from their STS.
I suppose I should validate their token with the certificate they sent me, but I'm not going to bother as I'm going to send it straight back to them when I call their web service.
When I look at the WSDL of their STS service I can see it is different from a typical WCF service because it has a section at the bottom which looks like this.
<identity xmlns="http://schemas.xmlsoap.org/ws/2006/02/addressingidentity">
<keyinfo xmlns="http://www.w3.org/2000/09/xmldsig#">
<x509data>
<x509certificate>MIIE8zCCA9ugAwIBAgILAQAAAAABLl3i0lAwDQYwSQY2ZNWvOf2k</x509certificate> <x509data>
</keyinfo>
</identity>
The trick is to find a way to send my token to their WCF web service. Add a Service Reference to their WCF web service in the usual way. My example uses MyWS.Service with the url of http://company.co.uk/service.svc. Note that when I setup the binding to this WCF service I have to include a reference to the issuer of the token (the url to their STS). I also needed to include a reference to the DNS identity. You can usually assume the DNS Identity from the Subject name on the third party certificate so if that is CN=company.co.uk then the DNS Identity will be company.co.uk.
// add constants for their STS service and DNS identity
public const string ServiceAddress = "http://company.co.uk/service.svc";
public const string DNSIdentity = "company.co.uk";
public const string STSAddress = "http://security.company.co.uk/security.svc";
public void RetrieveData(SecurityToken smToken)
{
// Instantiate the ChannelFactory as usual.
//Be sure to set the DNS Identity on the Endpoint
EndpointAddress endpointAddress = new EndpointAddress(new Uri(ServiceAddress), new DnsEndpointIdentity(DNSIdentity), new AddressHeaderCollection());
ChannelFactory clientFactory = new ChannelFactory(GetServiceBinding(ServiceAddress), endpointAddress);
clientFactory.Credentials.SupportInteractive = false;
// Make sure to call this prior to using the
//CreateChannelWith...()
// extension methods on the channel factory that the Windows
//Identity Foundation provides.
clientFactory.ConfigureChannelFactory();
ICommunicationObject channel = null;
bool succeeded = false;
try
{ // create an instance of the Pension Service client
MyWS.Service client = clientFactory.CreateChannelWithIssuedToken(smToken);
channel = (ICommunicationObject)client;
// Now its plain sailing
// I can call the method on the WCF service
// in may case GetData returns an array of objects
MyWS.MyObject[] psArray = client.GetData();
// TO DO something with psArray
channel.Close();
succeeded = true;
}
catch (CommunicationException e)
{ // TO DO log error
channel.Abort();
}
catch (TimeoutException)
{ // TO DO log error
channel.Abort();
}
finally
{
if (!succeeded && channel != null)
{
channel.Abort();
}
}
return ;
}
public Binding GetServiceBinding(string uri)
{
// Use the standard WS2007FederationHttpBinding
WS2007FederationHttpBinding binding = new WS2007FederationHttpBinding();
binding.Security.Message.IssuerAddress = new EndpointAddress(STSAddress);
binding.Security.Message.IssuerBinding = GetSMSecurityTokenServiceBinding(STSAddress);
binding.Security.Message.IssuerMetadataAddress = new EndpointAddress(STSAddress + "/mex");
return binding;
}
Good luck. In terms of difficulty on a scale of 1-10 this is a twelve. I wish you success.
Setup begins with the third party sending me the url to their STS and a copy of the public key certificate they will use to sign their token. I also need to have the url to their web service I want to call.
I'll say right away I'm no expert on this. There are examples in the Windows Identity SDK and that is a good starting point. The way it would work is my client application (a Windows Service) would call a local STS and pass it a username and password. My STS would check the credentials and if OK issue a token. Now the token is signed and encrypted by my X509 certificate so I have to get one of those to begin with. I need to install my X509 certificate in the Personal store of the computer I run the code on.
Start MMC, add the Certficate add-in and select the Local Computer. Navigate to the Personal node, and Certificates, right click and import my X509 certificate. Since I am running my Windows Service under the Network Service account I need to assign permissions. On the Certificate, right click, select All Tasks then Manage Private key. On the Security tab, add Network Service and give it full permissions. I can also add the thrid party's certificate here too - it is imported into the Personal Certificate store in the same way but since they gave me the public key, I don't need to bother with the permissions step (its not available anyway).
I also need to send the public key of my certificate to the third party. Right click on the certificate, select Export and choose the option to export the public key only.
Now the token issued by my STS contains a claim, in my case it is simply the role of Reader. I then pass my token to the third party's STS. These guys will want to check the token is from me and they use the certificate I sent them to do so. They check the claim, and if all is well issue me a token from their STS.
I suppose I should validate their token with the certificate they sent me, but I'm not going to bother as I'm going to send it straight back to them when I call their web service.
When I look at the WSDL of their STS service I can see it is different from a typical WCF service because it has a section at the bottom which looks like this.
<identity xmlns="http://schemas.xmlsoap.org/ws/2006/02/addressingidentity">
<keyinfo xmlns="http://www.w3.org/2000/09/xmldsig#">
<x509data>
<x509certificate>MIIE8zCCA9ugAwIBAgILAQAAAAABLl3i0lAwDQYwSQY2ZNWvOf2k</x509certificate> <x509data>
</keyinfo>
</identity>
The trick is to find a way to send my token to their WCF web service. Add a Service Reference to their WCF web service in the usual way. My example uses MyWS.Service with the url of http://company.co.uk/service.svc. Note that when I setup the binding to this WCF service I have to include a reference to the issuer of the token (the url to their STS). I also needed to include a reference to the DNS identity. You can usually assume the DNS Identity from the Subject name on the third party certificate so if that is CN=company.co.uk then the DNS Identity will be company.co.uk.
// add constants for their STS service and DNS identity
public const string ServiceAddress = "http://company.co.uk/service.svc";
public const string DNSIdentity = "company.co.uk";
public const string STSAddress = "http://security.company.co.uk/security.svc";
public void RetrieveData(SecurityToken smToken)
{
// Instantiate the ChannelFactory as usual.
//Be sure to set the DNS Identity on the Endpoint
EndpointAddress endpointAddress = new EndpointAddress(new Uri(ServiceAddress), new DnsEndpointIdentity(DNSIdentity), new AddressHeaderCollection());
ChannelFactory
clientFactory.Credentials.SupportInteractive = false;
// Make sure to call this prior to using the
//CreateChannelWith...()
// extension methods on the channel factory that the Windows
//Identity Foundation provides.
clientFactory.ConfigureChannelFactory();
ICommunicationObject channel = null;
bool succeeded = false;
try
{ // create an instance of the Pension Service client
MyWS.Service client = clientFactory.CreateChannelWithIssuedToken(smToken);
channel = (ICommunicationObject)client;
// Now its plain sailing
// I can call the method on the WCF service
// in may case GetData returns an array of objects
MyWS.MyObject[] psArray = client.GetData();
// TO DO something with psArray
channel.Close();
succeeded = true;
}
catch (CommunicationException e)
{ // TO DO log error
channel.Abort();
}
catch (TimeoutException)
{ // TO DO log error
channel.Abort();
}
finally
{
if (!succeeded && channel != null)
{
channel.Abort();
}
}
return ;
}
public Binding GetServiceBinding(string uri)
{
// Use the standard WS2007FederationHttpBinding
WS2007FederationHttpBinding binding = new WS2007FederationHttpBinding();
binding.Security.Message.IssuerAddress = new EndpointAddress(STSAddress);
binding.Security.Message.IssuerBinding = GetSMSecurityTokenServiceBinding(STSAddress);
binding.Security.Message.IssuerMetadataAddress = new EndpointAddress(STSAddress + "/mex");
return binding;
}
Good luck. In terms of difficulty on a scale of 1-10 this is a twelve. I wish you success.
Labels:
Federated Security,
Security Token Service,
WCF
Attach to Process is Greyed Out in Visual Studio
If you Google "Attach to Process is greyed out" as I have, all the responses will tell you to make sure you check the boxes "Show processs from all users" and "Show processs in all sessions".
What if you do that and it's still greyed out?
Answer: Use a different approach. Add the line
System.Diagnostics.Debugger.Launch();
to your code and it will launch the dialog box which allows you to connect to a new Visual Studio session or an existing one.
Once you do so, the debugger will stop at the line you just added and allow you to step through the code.
Tip: If you are using a timer in your windows service then disable the timer before you call the debugger. That way you stop the timer from kicking you back to the start every time it fires.
For example:
timer1.Dispose();
System.Diagnostics.Debugger.Launch();
What if you do that and it's still greyed out?
Answer: Use a different approach. Add the line
System.Diagnostics.Debugger.Launch();
to your code and it will launch the dialog box which allows you to connect to a new Visual Studio session or an existing one.
Once you do so, the debugger will stop at the line you just added and allow you to step through the code.
Tip: If you are using a timer in your windows service then disable the timer before you call the debugger. That way you stop the timer from kicking you back to the start every time it fires.
For example:
timer1.Dispose();
System.Diagnostics.Debugger.Launch();
Labels:
attach,
Disabled,
Grayed Out,
Greyed out,
Process,
Visual Studio
Subscribe to:
Posts (Atom)








