Sunday, December 30, 2012
Displaying associated views for the relationships missing in relationship explorer.
In CRM2011 we have relationship explorer as shown in screen shot.
We can drag any available relationship from the relationship explorer to the form navigation. The navigation link will display the associated view for that relationship.
The problem is that the relationship explorer does not display all the relationships. For e.g. system relationship between user and leads(to display all the leads owned by the user).
We can use the following URL to display any associated view.
http://servername/orgname/userdefined/areas.aspx?oId=<guid of the entity>&oType=<entity type code>&pagemode=iframe&security=852023&tabSet=<relationship shema name>
I got this URL from the existing associated views. There are few more parameters that can be passed to this URL like formid but they are optional.
Replace the highlighted values with the values from your deployment.
Here is an example of the URL with all the values. This URL will display the associated view of the leads owned by the user specified in the URL.
http://servername/orgname/userdefined/areas.aspx?oId=%7b734F5966-827C-E111-A07F-00155DDBE211%7d&oType=8&pagemode=iframe&security=852023&tabSet=lead_owning_user
I hope this helps.
Saturday, December 22, 2012
Strange behaviour when using security roles with the teams in CRM2011
I was trying to setup the security roles on teams instead of assigning security role to the individual users. The end result is that it does not work very well.
Here are the details of what happened.
I had a user with security role named “Manager”. Everything was working as expected. The user was able to create and update the entities defined in the security role. We decided to the create a team named “Manager” and assign the role to the team. I added the user to the team and remove the security role from the user. Here is what happened after that
I was able to open , create and update the entities as defined in the security roles until we created a new for form for an existing entity.
When I tried to open the newly created form for the entity, I received the following error message.
I had a look in the event viewer. It was showing the following warning message.
Exception message: SecLib::AccessCheckEx failed. Returned hr = -2147187962, ObjectID: 3be48aca-0f39-e211-bce1-005056b8253f, OwnerId: 9cc2541a-9137-e211-bce1-005056b8253f, OwnerIdType: 8 and CallingUser: 9cc2541a-9137-e211-bce1-005056b8253f. ObjectTypeCode: 2500, objectBusinessUnitId: bf221f51-8537-e211-bce1-005056b8253f, AccessRights: WriteAccess
The object type code 2500 represents the entity “User Entity UI Settings”. I checked the permissions on the entity. The user had the required permissions on the entity. The most annoying part was that I was able to open the existing form without a problem.
So I decided to look a bit deeper into the problem and here are my findings.
1. I created a new user and add the user to the team without assigning any role to the user.
I received an error message “Access Is Denied” every time I tried to open any entity form.
2. I added the same security role to the user as security role assigned to the team.
I tried to open account and contact entity form and I was able to open them without an error.
3. I removed the security role from the user again
I was able to open the entity forms I tried in step 2 but, I was unable to open the form for any other entity or different form for the same entity.
Conclusion:
You have to have a security role assigned to the user to open any entity form minimum for the first time.
Tuesday, December 11, 2012
CRM fields and "Duplicate Field Name” error
Every time you create an option set or a lookup field in CRM, the system creates 2 fields. For example if you create a lookup field named “new_contact”, the system will create the following 2 fields:
- “new_contact”
- “new_contactname” ( the second field will have “name” at the end)
The first field is created as expected. But the system creates the second field automatically. If you ever looked into the filtered views, you must have noticed the extra name columns for lookup and option set fields. If you open a FilteredAccount view, you will notice primarycontactid and primarycontactidname columns. The primarycontactid column contains the guid of the primary contact and primarycontactidname contains the actual name of the contact.
In case of optionset field, the first field contains the integer value of the optionset and second field contains the optionset text value.
The problem is that the CRM UI does not display the second field. You won’t find primaryconactidname in the field’s grid of account entity.
To verify this behaviour, I created a lookup field name “new_contact” and then I tried to create a new field “new_contactname”. I received the following error message.
If you receive the “Duplicate Field Name” error, the reason can be a existing lookup or optionset field as explained above.
Friday, November 30, 2012
Error on load of queue form in CRM 2011
I was getting the following error message.
I had a look in the event viewer. It was showing a warning message as shown in the screen shot.
I could not figure out the problem. I tried to repair the CRM. This happened after I setup the email router.
So start looking what I did. I found out that I was using “User Specified” access credential for incoming profile. By default, it is not allowed if you are not using SSL (HTTPS). But there is workaround as explained on TECHNET. The article mentioned that I have to manually add registry key DisableSecureDecryptionKey with value 1. That’s what I did and that was a problem. I created a key instead of creating a DWORD value. To make this work, it should be a “DWORD” not a “Key”.
The DisableSecureDecryptionKey entry should look like following screen.
I made the change and it worked like a charm….
Thursday, November 22, 2012
My experience with Microsoft Dynamics CRM 2011 Custom Code Validation Tool
Microsoft released the “Microsoft Dynamics CRM 2011 Custom Code Validation Tool” in May 2012. The purpose of this tool is to detect the potentials issues in HTML and JavaScript web resources when CRM2011 starts supporting multiple browsers.
The cross browser functionality was supposed to be released in Q2 2012 but, that did not happen. The next release of CRM2011 code name Polaris is coming out in December 2012. One of the many features included in Polaris is cross browser compatibility. This blog lists “What’s included in Polaris?”.
After reading about Polaris, I decided to try “CRM 2011 Custom Code Validation Tool”. Here is the link to download the tool. Here are my findings. The results are mixed but you can make up your own mind.
The following screen shot displays the results from the tool. To check the results, the user has to scroll down the list of web resources one by one.
Issues found by the tool
I included some old and unsupported code in the libraries to test the tool. Here are some of the screen shots of potential issues found by the tool.
So far so good. Here is the screen shot of the JavaScript webresource with most issues.
The thing that shocked me the most is that this code is straight from the CRM SDK sample provided by Microsoft.
Issues ignored by the tool
I intentionally added some unsupported code to the JavaScript web resource. But the tool did not identify this code as potential issue.
Here is the screen shot of one such unsupported code. I am using code to attach the custom CSS on form onload.
Conclusion
This is very good to identify the potential issue. But I can’t say how reliable it is.
Anyway don’t use any unsupported code intentionally.
Monday, November 5, 2012
List of Currencies in CRM2011
If we choose “system” for currency type which is the default selection, we can select currency code from a look up view as shown in the following screen shot.
The selection from the lookup will fill all the required fields (“currency name”, “currency precision”, “currency symbol”) for the currency. We have to manually provide the value for the “exchange rate” field.
Now if you want all the currencies in your system then you have to repeat this process hundred plus times.
I had a look around to find a list of currencies to import into the system instead of creating these record one by one.There is a URL in currency lookup view with the view id. Here is the URL from my environment.
http://servername/orgname/_controls/lookup/lookupinfo.aspx?AllowFilterOff=1&DefaultType=9105&DefaultViewId=%7b1A364391-BF41-407B-B91F-5C326BAF0A3B%7d&DisableContextMenu=1&DisableQuickFind=0&DisableViewPicker=1&LookupStyle=single&ShowNewButton=1&ShowPropButton=1&browse=1&objecttypes=9105
I looked into the database and found a saved query record with a name “Currency List” with the viewid shown in the above URL. But the “Query API” field value of the record was showing “TransactionCurrency.RetrieveDotNetCurrencies”. It suggested me that this currency list is not stored in the database table. It may be residing in the database but I did not find it.
I used “Fiddler” and internet “Developer tools” and compile the list of currencies in the lookup view. The list is XML spread sheet 2003 format. Here is the link to download the file. This file can be imported into the system using data import tool. Here is screen shot of some sample data from the file.
The “regionname” does not get stored in the currency record. You need to provide the exchange rate for the currencies against your base currency.
When you import this file into CRM map the fields of this file to the currency entity of the system. The mapping screen will look like this.
Import process will import 102 records and 62 records will fail. The reason for the failed records is duplicate currency code.
If you look into the currency list, there are a lot of duplicate currency codes. For example “CAD” currency code is repeated 4 times.
INR, EUR and some other currencies are repeated multiple time too.
Make the changes to the file as required and import it into CRM using built-in import tool.
I hope this helps.
Tuesday, October 30, 2012
Workflow assembly to cancel waiting workflows - Part 2
I did not like the fact that I need to pass the name of workflow as a parameter to the assembly. Then this thought across my mind that I may be able to use this workflow for some other scenarios. For e.g What will happen if I deactivate an account which have one or more workflows in a waiting status?
Personally, I would like to cancel all waiting workflows if I deactivate the account. So I change the code.
Now this workflow assembly can be used in 2 different scenarios.
- If I pass the name of the workflow to the assembly. It will update the status of waiting instance of the workflow to “Cancelled” .
- If I pass nothing, then it will update the status of all the waiting workflows to “Cancelled” for an entity regardless, of the name of the workflow. In the following screen shot, I am leaving the work flow name empty.
Click here to download the workflow.zip. I have uploaded the whole solution.
Workflow assembly to cancel waiting workflows - Part 1
The ideal situation will be a workflow that can cancel any waiting workflows on start of a new instance of the workflow. The original idea is from Ayaz Ahmed’s blog. I took that idea and came up with this CRM 2011 workflow assembly. It checks for any waiting instances of the workflow and update their status to “Cancelled”. Here is the code.
using System; using System.Activities; using Microsoft.Xrm.Sdk; using Microsoft.Xrm.Sdk.Messages; using Microsoft.Xrm.Sdk.Query; using Microsoft.Xrm.Sdk.Workflow; using Microsoft.Crm.Sdk.Messages; using Microsoft.Xrm.Sdk.Client; namespace Workflow { public class KillWaitingWorkflows: CodeActivity { protected override void Execute(CodeActivityContext executionContext) { //Get the tracing service //ITracingService tracingService = executionContext.GetExtension<ITracingService>(); //Get the context IWorkflowContext context = executionContext.GetExtension<IWorkflowContext>(); IOrganizationServiceFactory serviceFactory = executionContext.GetExtension<IOrganizationServiceFactory>(); IOrganizationService service = serviceFactory.CreateOrganizationService(context.UserId); //get workflow name from the input property string sWorkflow = workflowName.Get<string>(executionContext); //Get a service context to use linq queries and var ServiceContext = new OrganizationServiceContext(service); try { QueryExpression query = new QueryExpression("asyncoperation"); //get columns ColumnSet cols = new ColumnSet(new string[] { "asyncoperationid", "statecode" }); //create conditions ConditionExpression c1 = new ConditionExpression("name", ConditionOperator.Equal, sWorkflow); // name of the workflow -input property ConditionExpression c2 = new ConditionExpression("regardingobjectid", ConditionOperator.Equal, context.PrimaryEntityId);// entity id ConditionExpression c3 = new ConditionExpression("statecode", ConditionOperator.Equal, 1);//statecode of waiting //create the filter FilterExpression filter = new FilterExpression(); filter.FilterOperator = LogicalOperator.And; filter.AddCondition(c1); filter.AddCondition(c2); filter.AddCondition(c3); query.ColumnSet = cols; query.Criteria.AddFilter(filter); //get the collection of results EntityCollection colResults = service.RetrieveMultiple(query); foreach (Entity async in colResults.Entities) { Entity e = async; //change the status of the system job e["statecode"] = new OptionSetValue(3); //cancelled //update the object service.Update(e); } }//end try // Catch any service fault exceptions that Microsoft Dynamics CRM throws. catch (Exception ex) { // You can handle an exception here or pass it back to the calling method. throw; } } [Input("Work Flow Name")] [Default("workflow name")] public InArgument<string> workflowName { get; set; } } }
- Compile the workflow assembly and register it using plugin registration tool.
- If everything goes smoothly, you can see this workflow assembly available in workflow. It will look like the following screens.
- I am calling the assembly before the waiting condition. Click on the “View properties” link next to assembly name highlighted in yellow to specify the name of the workflow.
- Activate the workflow and test it.
Sunday, September 30, 2012
Outer Joins in Fetch XML queries in CRM2011
Here are some of the examples.
Example 1
Creating a query to retrieve opportunities with fields from related account entity. Here is the query.<fetch version="1.0" output-format="xml-platform" mapping="logical" distinct="false">
<entity name="opportunity">
<attribute name="name" />
<attribute name="customerid" />
<attribute name="estimatedvalue_base" />
<order attribute="name" descending="false" />
<link-entity name="account" from="accountid" to="customerid" visible="false" link-type="outer" alias="accountid">
<attribute name="telephone1" />
</link-entity>
</entity>
</fetch>
This query will return name(Topic), customerid(Potential Customer), estimatedvalue_base(Estmated Revenue), telephone1(Main Phone from account entity).
This query will return the above columns for all the opportunities. What will happen if the potential customer on opportunity is a contact instead of an account? The answer is it will still return all the opportunities as there is an outer join between the two entities. It will return the empty telephone 1 column. If we remove the link-type="outer" then the query won’t return any opportunities that have contacts as potential customers.
This query is also possible using advance find.
Example 2
What if we want to return all the opportunities and also any phone call activities related to these opportunities. This is also achievable using outer joins. There is 1:N relationship between opportunity and activitypointer entity. Therefore the query will return multiple records for the same opportunity if there are more than one phone call recorded against an opportunity. Here is fetch xml for the query<fetch version="1.0" output-format="xml-platform" mapping="logical" distinct="false"> <entity name="opportunity"> <attribute name="name" /> <attribute name="customerid" /> <attribute name="estimatedvalue_base" /> <order attribute="name" descending="false" /> <link-entity name="account" from="accountid" to="customerid" visible="false" link-type="outer" alias="accountid"> <attribute name="telephone1" /> </link-entity> <link-entity name="activitypointer" from="regardingobjectid" to="opportunityid" visible="false" link-type="outer" alias="phonecall"> <attribute name="subject" /> <attribute name="description" /> <attribute name="createdon" /> <filter type="and"> <condition attribute="activitytypecode" operator="eq" value="4210" /> </filter> </link-entity> </entity> </fetch>
The above fetch xml will retrieve the subject, description, createdon columns for related phone call activities as well as the columns mentioned in example one.
I have created a sample SSRS report using the above fetch xml query. Here is result. You can change the display name for the columns in the data set as required.
Saturday, September 22, 2012
Single Sign On for CRM 2011 Online
I did some research and found these 2 blogs on how to setup ADFS for CRM Online/ Office 365.
http://blogs.msdn.com/b/girishr/archive/2012/09/05/dynamics-crm-identity-federation-demo-setup.aspx
http://www.messageops.com/documentation/office-365-documentation/ad-fs-with-office-365-step-by-step-guide
Go Dynamics CRM….
Wednesday, September 5, 2012
Error message on running SDK samples for CRM Online on Office 365
Here is the screen shot.
The problem is the authentication process. I debugged the code and find out that SDK samples are using the following code to the username.
//For OnlineFederation environments, initially try to authenticate with the current UserPrincipalName for single sign-on scenario. else if (config.EndpointType == AuthenticationProviderType.OnlineFederation && config.AuthFailureCount == 0) { config.UserPrincipalName = UserPrincipal.Current.UserPrincipalName; return null; }The value of "UserPrincipal.Current.UserPrincipalName" is always null and hence the error message. This code sits in CrmServiceHelpers.cs.
If we comment out the above mentioned code. The system will prompt you to enter your username and password and you are good to go.
You will receive the similar error message if you are trying to use developer’s toolkit with CRM Online on Office 365.The exact message is “Value Can not be null”. Here is the screen shot.
I don’t have a solution for this problem. I know the Visual Studio stores the CRM connection string for developer toolkit in .suo file. I was hoping if I can create this file manually or update this file. But I don’t have a solution yet. If you guys have a solution, please let me know.
Thanks…
Wednesday, August 22, 2012
Problem with JavaScript text editor after installing Roll Up 10 (CRM2011)
If you click on “OK”, it will truncate your JavaScript. The good news that you can still create new webresource or update existing resources using some external text editor and upload that file into your JavaScript webresource.
Thanks.
Sunday, August 19, 2012
How to create meaningful device credentials using Device Registration Tool
To connect to CRMOnline, we need to specify the device credentials as well as LIVE username and password. Here is an example of CRMOnline connection string.
Url=https://contoso.crm.dynamics.com; Username=jsmith@live-int.com; Password=passcode; DeviceID=contoso-ba9f6b7b2e6d; DevicePassword=passcode
The device credentials sit in “C:\Users\username\LiveDeviceID\LiveDeviceID.XML” file.
If the file does not exist then it means your device is not registered. If it does exist then the file contents will look like the following screen.
If you look at username and pwd in the above screen shot, they look like random letters and numbers.
Microsoft provides the “Device Registration Tool” to register the device for CRMOnline. This tool can be found at “\sdk\tools\deviceregistration\bin\Debug.DeviceRegisteration.exe” location.
The DeviceRegistration.exe supports 2 operations.
- Show
- Register
The second screen shot displays the outcome of register operation. The tool created a device id and device password. As I mentioned earlier in the blog, these credentials are not readable and you can’t really remember them. But we can actually specify the device id and password by passing username and password parameter in the register operation. Have a look at the following screen.
That's how you can specify your own device id and device password for device registration. The only thing I can’t work it out is that registration tool adds 11 in front of the specified device id.
Thanks….
Monday, August 13, 2012
Check if the date is a business day in CRM2011
I have written this code to check if current date is a business day. The code is checking if the date is a weekend or a “Business Closure” day defined in CRM. Here is the code. Make the changes according to your requirements.
using System; using System.Collections.Generic; using System.Linq; using System.Text; using Microsoft.Xrm.Sdk; using Microsoft.Xrm.Client; using Microsoft.Xrm.Client.Services; using Microsoft.Xrm.Sdk.Query; using Microsoft.Crm.Sdk.Messages; namespace dateCheck { class dateCheck { static void Main(string[] args) { //Date to be checked DateTime dateBeingTested = DateTime.Now; if (IsItWeekend(dateBeingTested) || CheckHolidays(dateBeingTested)) { Console.WriteLine(dateBeingTested.ToString("d") + " is not working day."); } else { Console.WriteLine(dateBeingTested.ToString("d") + " is a working day."); } } static bool IsItWeekend(DateTime date) { if ((date.DayOfWeek== DayOfWeek.Saturday) || (date.DayOfWeek==DayOfWeek.Sunday)) { return true; } return false; } static bool CheckHolidays(DateTime date) { var connection = new CrmConnection("Crm"); var service = new OrganizationService(connection); QueryExpression query = new QueryExpression("calendar"); query.ColumnSet = new ColumnSet(true); ConditionExpression condition = new ConditionExpression(); condition.AttributeName = "name"; condition.Operator = ConditionOperator.Equal; condition.Values.Add("Business Closure Calendar"); query.Criteria.Conditions.Add(condition); EntityCollection calendars = service.RetrieveMultiple(query); EntityCollection calendarrule = calendars[0].GetAttributeValue<EntityCollection>("calendarrules"); return calendarrule.Entities .Where(e => ((DateTime)e["starttime"]).Date == date.Date).Any(); } } }
To make this code works, we need to define a connection string “Crm” in app.config file. Change the server name and credentials to match your deployment.
<?xml version="1.0"?> <configuration> <connectionStrings> <!--<add name="Crm" connectionString="ServiceUri=http://servername/orgname; Domain=domainname; Username=username; Password=password"/>--> <add name="Crm" connectionString="ServiceUri=https://orgname.crm5.dynamics.com; Username=username; Password=password; DeviceID=deviceid; DevicePassword=password"/> </connectionStrings> </configuration>
Happy Programming…Thanks Russel for the code.
Monday, July 23, 2012
CRM2011 and Cross Domain calls Part 2
How to make a JSONP call using jQuery
Here is the code. The code is using the twitter APIs. The code will retrieve the tweets by Donna Edward( CRM MVP) and display the text of the first tweet.<HTML><HEAD><TITLE></TITLE> <SCRIPT src="http://servername/SandpitAmreek//WebResources/new_/jquery1.7.2.js"></SCRIPT> <SCRIPT type=text/javascript> function callTheJsonp() { //debugger; // the url of the script where we send the asynchronous call //var url = "http://openexchangerates.org/api/latest.json?callback=?"; jQuery.getJSON("https://api.twitter.com/1/statuses/user_timeline.json?callback=?", { include_entities: "true", include_rts: "true", screen_name: "edwardsdna" }, function(data) { alert(data[0].text); }); } } </SCRIPT> <META charset=utf-8></HEAD> <BODY onload=callTheJsonp() contentEditable=true>hey hey</BODY></HTML>
Run the code and we will received the similar to the following screen.
How to make a JSONP call using AJAX
Here is the code call the JSONP call using AJAX.<HTML><HEAD><TITLE></TITLE> <SCRIPT src="http://auntmsftv23/SandpitAmreek/WebResources/new_/jquery1.7.2.js"></SCRIPT> <SCRIPT type=text/javascript> function callTheJsonp() { debugger; // the url of the script where we send the asynchronous call var url = "http://openexchangerates.org/api/latest.json?callback=parseRequest"; $.ajax({ url: url, dataType: "jsonp", jsonpCallback: "parseRequest" }); } // this function should parse responses.. you can do anything you need.. // you can make it general so it would parse all the responses the page receives based on a data field function parseRequest(data) { try // try to output this to the javascript console { alert("AUD: " + data.rates.AUD);} catch(an_exception) // alert for the users that don't have a javascript console { alert(data); } } </SCRIPT> <META charset=utf-8></HEAD> <BODY onload=callTheJsonp() contentEditable=true>Testing Cross Domain Calls</BODY></HTML>
Run the code and we will received message USD/AUD exchange rate .
Monday, July 16, 2012
CRM2011 and Cross Domain calls Part 1
What are cross domain calls?
These are the calls we make from a web page using JavaScript to access resources at a different URL. This URL can be separate website or domain or port name. This can be calling a same URL using ip address instead of using computer name as I discussed in my previous post.In IE, these calls are not allowed. If you try to call a web service using ajax, you will get an error message “Access is denied”. The problem is XMLHttpRequest object used in the AJAX calls. This object stops us making calls to other domains. AJAX communication is restricted to the server of origin. It is by design and it protects as against the malicious hack these calls can cause. But sometimes these calls are essential. In day to day basis we do need to make these calls. For example, if you would like display exchange rates in CRM2011, we have to make a call to some external API/web service. In this blog we will discuss how to make cross domain calls in JavaScript.
I found this free currency exchange API http://openexchangerates.org/api/latest.json. This URL will return the exchange rates for about 150 currencies in JSON format. I have created an html web resource in CRM2011 to retrieve the exchange rates using JQuery AJAX call. Here is the code. I have also added a reference to JQuery web resource to this html web resource.
<HTML><HEAD><TITLE></TITLE> <SCRIPT src="https://crm5org01a03.crm5.dynamics.com//WebResources/new_/jquery1.7.2.js"></SCRIPT> <SCRIPT type=text/javascript> function callExchangeRate() { //debugger; jQuery.support.cors = true; var myurl = "http://openexchangerates.org/api/latest.json"; $.ajax({ type: "GET", contentType: "application/json; charset=utf-8", datatype: "json", url: myurl, beforeSend: function (XMLHttpRequest) { XMLHttpRequest.setRequestHeader("Accept", "application/json"); }, success: function (data, textStatus, XmlHttpRequest) { // Use for a single selected entity alert(data.rates.AUD); // this line will display the exchange rate of AUD aganst USD }, error: function (xmlHttpRequest, textStatus, errorThrown) { alert("Status: " + textStatus + "; ErrorThrown: " + errorThrown); } }); } </SCRIPT> <META charset=utf-8></HEAD> <BODY onload=callExchangeRate() contentEditable=true>Testing Cross Domain Calls</BODY></HTML>
When we run this web resource, we will receive the following error message.
How to make a cross domain calls
So how can we get around this problem? There are few solutions to this problem. I will discuss the following 2 options.- JSONP
- XDomainRequest (Cross Domain Request)
Using JSONP
JSONP stands for JSON with padding but it has nothing to do with JSON. This is an old technique of using <script> tag to load external resources. JSONP dynamically creates a <script> tag to get the data instead of using XMLHttpRequest object. The <script> tag will load whatever is returned from the URL specified as its “src” attribute. The other cool feature of JSONP calls is Callback function.For example look at the following URL
http://openexchangerates.org/api/latest.json. If we use this URL in <script> tag it will attached the response to “src” tag. But if we use http://openexchangerates.org/api/latest.json?callback=parseRequest, the response will be wrapped in a parseRequest method. We can use this method to process the response.
I have created an html web resource using this technique. Here is the code.
<HTML><HEAD><TITLE></TITLE> <SCRIPT type=text/javascript> function callTheJsonp() { //debugger; // the url of the script where we send the asynchronous call var url = "http://openexchangerates.org/api/latest.json?callback=parseRequest"; // create a new script element var script = document.createElement('script'); // set the src attribute to that url script.setAttribute('src', url); // insert the script in out page document.getElementsByTagName('head')[0].appendChild(script); } // this function should parse responses.. you can do anything you need.. // you can make it general so it would parse all the responses the page receives based on a response field function parseRequest(data) { try // try to output this to the javascript console { alert("AUD: " + data.rates.AUD); } catch(an_exception) // alert for the users that don't have a javascript console { alert(data); } } </SCRIPT> <META charset=utf-8></HEAD> <BODY onload=callTheJsonp() contentEditable=true>Testing Cross Domain Calls</BODY></HTML>
When we open the html web resource, it will display the following message.
Note: To work with JSONP, the web service has to be JSONP compatible. If you are creating your own web services and you would like to consume them in JavaScript using JSONP, make sure they are JSONP compatible. The currency conversion API, I am using in this example supports JSONP so does flicker, twitter and Google APIs etc.
In my next blog I will explain how to make JSONP calls using JQuery and AJAX and also how to use XDomainRequest.
Friday, July 6, 2012
How to change the form header colour based on the field value in CRM2011
Scenario
I am changing the account form header based on the value of customertypecode option set field.- If the option set value is 1 then change the form header to red.
- If the option set value is 2 then change the form header to green.
- Else keep the default colour.
Solution
The solution consists of 3 web resources- CSS web resource for red colour
I have named this web resource “new_/ColoredHeaderRed.css”. Here is the code.
.ms-crm-Form-HeaderContainer{ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr=#FF0000, endColorstr=#fff6f8faE); }
- CSS web resource for green colour
I have named this web resource “new_/ColoredHeaderGreen.css”. Here is the code.
.ms-crm-Form-HeaderContainer{ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr=#008000, endColorstr=#fff6f8faE); }
- JavaScript web resource to attach the relevant CSS file to the form
I have named this web resource “new_/ColoredHeaderScript.js”. The code is using a switch statement to attach an appropriate CSS file to the form, based on the value of customertypecode field. I am not using default in my switch statement as I don’t want to create a CSS file for default colour. Here is a code.
function loadCSS() { // get the value picklist field var relType = Xrm.Page.getAttribute("customertypecode").getValue(); var filename; switch (relType) { case 1: filename="/WebResources/new_/ColoredHeaderRed.css"; attachCSS(filename); break; case 2: filename="/WebResources/new_/ColoredHeaderGreen.css"; attachCSS(filename); break; } }// end function function attachCSS(filename){ var fileref = document.createElement("link"); fileref.setAttribute("rel", "stylesheet"); fileref.setAttribute("type", "text/css"); fileref.setAttribute("href", filename); document.getElementsByTagName("head")[0].appendChild(fileref); }Now call the loadCSS() function on account form load event.
Save and publish the changes and test the solution.
Results
If the option set value is 1.If the option set value is 2.
Supported or Non Supported
CSS web resources are not meant to be used to change the style of built in forms. So technically it is unsupported. But, we are not trying to retrieve the value of field or DOM object. We are just attaching a style sheet. If the Microsoft decided to change the name of the header class, it may stop the code to change the header colour but it won’t break the system.Saturday, June 30, 2012
CRM2011 Workflow
- Workflow Templates
- Automatically deleting the completed workflow jobs
- Use of “Activity Count” and “Activity Count Including Process”
Workflow Templates
When we create a workflow , we have an option to activate the workflow as templates.We can also activate an existing workflow as a ”Process Template” as long the workflow is in draft/deactivate state.
One of the biggest benefit of saving/activating a workflow as template is that we can create a copies of existing workflow without creating a workflow from scratch.
Automatically deleting the completed workflow jobs
In CRM, when the workflow is completed, it still appears in the system jobs as shown in the following screen.We can delete these succeeded workflow entries automatically by checking the “Automatically delete completed workflow jobs(to save disk space” on the Administration tab of the workflows as shown in the following screen shot.
Use of “Activity Count” and “Activity Count Including Process”
When we use wait condition or check condition in workflows, under the “Local Values” there is a “Process” option and there are 4 sub options available for “Process” as shown the screen shot. The 4 options are :- Execution Time
- Activity Count
- Activity Count Including Process
- Timeout
Execution Time
It will give you the execution time (date and time) of the workflow.Activity Count
It will return the total number of activities excluding activities created through workflow steps associated to the workflow entity.Activity Count Including Process
It will return the total number of activities including activities created through workflow steps associated to the workflow entity.Timeout
It will pause the workflow execution for specified data and time. Look at the following blog for detail explainationhttp://www.dynamicscrmtrickbag.com/2009/07/12/waits-timeouts/
Monday, June 25, 2012
Importing notes attachments in CRM2011
After some searching on Google, I found few dynamic forums and a LinkedIn group that were very helpful. Here is a link to the LinkedIn group. Here is scenario. I have 2 separate deployments of CRM2011. They are not connected to each other. I need to move the accounts and file attachments (notes) from one deployment to another.
The solution is consists of 2 parts
- On CRM deployment 1, I will write some custom code to create a zip file that will contain 2 CSV file and “Attachments” folder containing all the attachments.
- On CRM deployment 2. I will use built-in “Data Import” tool to import this zip file into the system.
Creation of Zip files
In this blog, I won’t be writing any custom code to create a zip file but will explain the structure of zip file.I have created a folder named “Import”. In “Import” folder, I have created 2 files and folder as shown in the screen shot.The account.csv file will look like the following screen
The note.csv will like the following screen.
The fieldnames “File Name”, “PhysicalFileName” and “Regarding” are very important here. They are important to import the attachments and linking to the proper account records.
- Column “Filename” will be mapped to “FileName” field on the notes entity.
- Column “PhysicalFileName” be mapped to the “Document” field on the notes entity.
- Column “Regarding” will be mapped to the “Regarding” field in the notes entity.
Now the next step will be to zip this “Import” folder into “Import.zip” file.
Importing the zip file
Now take this “Import.zip” file to the second deployment and import the file using “Data Import” tool. Here are the steps:If the names of CSV files match the crm entities, “Data Import” wizard will map them to the appropriate CRM entities as shown the screen shot above.
Now here you can click on the entities and map the fields between your CSV files and CRM entities. I am going to map the notes entity fields in the next step
Make sure these fields are mapped as shown in the above screen shot.
If you are going to use this process on regular basis, save the data map by providing a “Data Map Name” highlighted by yellow in the above screen shot.
Click on finish. Check the record on completion of the import process.
I have attached the sample zip file here. Download it and import into your system to test it.