1. It is upgraded to CRM 2013 now.
Thanks.
I’m feeling really happy while writing this blog, because it’s over a year that I got a chance to write it. I have been too busy for last year to write even a single blog. From now on, I’m hoping to keep this activity continued.
In this blog I would like to explain how to create a new record and open the same on click of custom ribbon button in Dynamics CRM. The steps are as following:
1. Create a custom ribbon button on a specific entity, the source entity. Use the Ribbon Workbench tool to add a button on this entity. This tool can be downloaded using following link.
http://www.develop1.net/public/page/Ribbon-Workbench-for-Dynamics-CRM-2011.aspx
2. Create a custom attribute of type of “Two Options” on the source entity say new_isribbonbuttonclicked. (specified above in step 1).
This field helps us in plug-in to identify whether the ribbon button is clicked by a user or not.
When the user clicks on this newly added button, a new record gets created via plug-in and the same will be opened in a new window with CRM 2011 or in a same window in CRM 2013.
3. Create another attribute of type “Single line text” on the same entity say new_uniqueidentifierofentity. This attribute will hold the GUID value of a newly created record.
The value of this field will be used in JavaScript/web resource code to open the newly created
record.
Create a new web resource of type Script (JScript) and write the following JavaScript code in it. This code updates the value as “True” to the new_isribbonbuttonclicked attribute.
1: //Change the method and attribute name as per your need
2: function UpdateAttribute() {
3: var attribute = Xrm.Page.getAttribute("new_isribbonbuttonclicked"); //Specify the name of your attribute
4: var attributeValue = null;
5: if (attribute != null) {
6: attributeValue = attribute.getValue();7: if (attributeValue == null ||
8: attributeValue == false) {
9: attribute.setValue(true);
10: attribute.setSubmitMode("always");
11: Xrm.Page.data.entity.save(); 12: } 13: } 14: }5. Call the above JavaScript function from the ribbon button which we have created at very first step of this post.
6. Now, write a pre update plug-in on the source entity. In this plug-in just check whether the plug-in context contains the new_isribbonbuttonclicked attribute or not. If it exists in the context and the value of this attribute is “True” then create a record of another entity and get the unique identifier (GUID) of the newly created record from the response of the SDK call.
7. Then, add this GUID to the plug-in context for the new_uniqueidentifierofentity field.
Like,
entity.Attributes[new_uniqueidentifierofentity] = GUID; //Specify the name of your attribute
8. Also add the new_isribbonbuttonclicked field in the plug-in context as “False”. So that, the custom ribbon button will work for the next attempt.
9. At the end of plug-in execution the above attribute values get automatically updated.
10. Lastly, add another method in the web resource of the source entity and bind this method to “form load” event. Primarily, this method checks following two conditions.
· The form is loaded into the edit mode or not.
· The new_uniqueidentifierofentity attribute contains data or not.
If it satisfies both the conditions, meant if the record is opened in edit mode and the GUID attribute contains unique identifier of newly created record then just write a code to open this record, update the value of new_uniqueidentifierofentity to null, and save the form.
Following is the code that performs the things that we specified here in this step.
1: //Change the method and attribute name as per your need
2: function Form_Load() {
3: if (Xrm.Page.ui.getFormType() == 2) {
4: var attribute = Xrm.Page.getAttribute("AttributeName"); //Specify the name of your attribute
5: var attributeValue = null;
6: if (attribute != null) {
7: attributeValue = attribute.getValue();8: if (attributeValue != null &&
9: attributeValue != "") {
10: Xrm.Utility.openEntityForm("EntityName", attributeValue);
11: attribute.setValue(null);
12: attribute.setSubmitMode("always");
13: Xrm.Page.data.entity.save(); 14: } 15: } 16: } 17: }That’s it!
Hope, this helps. Thanks.
For one of our customers, we had created some custom stored procedures in a separate database with CRM plugins to replace their existing SQL triggers. We required these SPs “as is” because they were having very complex logic inside them and would have taken ample amount of time to re-write the complete logic in CRM plugins. Hence, We had just reused those objects and amended it to make them compliance with Dynamics CRM standards by fetching the data from filtered views instead of direct table hits. Like,
Select * from DBO. Account
was replaced with,
Select {required columns } from OrganisationName_MSCRM.dbo.FilteredAccount
Inside the Dynamics CRM plugins, we had written the code to connect to the custom database (using windows authentication connection string) and called the above stored procedures. However, surprisingly, the stored procedures did not return any data. Hence, one of our developers came to me with this problem. I knew that the problem is with Application Pool Identity. The CRM plugins are executing under the CRM Application Pool Identity user and that user does not have permission to access the CRM data.
The CRM filtered views run under the user security roles and do not return data if you don’t have configured the required privileges. Additionally, we must not configure the Dynamics CRM user as CRM application pool identity. Please refer below URL to know more about Security considerations for Microsoft Dynamics CRM 2011.
http://technet.microsoft.com/en-us/library/hh699825.aspx
Then, I suggested her to add the above application pool identity user to PrivUserGroup. (One of the auto-generated Active Directory groups.) But, in our case the identity pool user was already added in this group. To give complete CRM database access, it can also be added to SQLAccessGroup, however, the situation was same, and the identity was already added here too.
Eventually, we switched to user impersonation. There were two options; either we impersonate the user inside the plugin or at SQL server level. I had asked her to implement the latter one and she tried with “Execute AS” inside the stored procedure and it worked as per the expectation. Below is our complete solution.
1. Add a new user in SQL server security logins, the security logins area is displayed in below screen shot.
OR
If you wish then you can use one of the existing users. However, this user must require sysadmin sever role to execute “Execute AS” command. Below link will help you to get more details on “Execute AS” (transact-SQL).
http://msdn.microsoft.com/en-us/library/ms181362.aspx
2. Use the above SQL user in your connection string to connect with custom database inside CRM plugins, as described below.
Data Source=myServer;Initial Catalog=myDataBase;User Id=myUsername; Password=myPassword;Integrated Security=false
3. Retrieve the domain name of logged in CRM user.
In plugin context you will always get the UserID via Context.UserID property, which is the GUID of the logged in CRM User. Use this value to retrieve the domain name of logged in CRM user from “systemuser” table. Keep this web service call in a common class/method inside your plugin solution, so that, the same can be reused in other plugin classes as well.
4. Pass the above domain name to your custom stored procedure as parameter which can be further used in “Execute AS” command, as shown in below stored procedure.
USE [DBName]GOSET ANSI_NULLS ON
GOSET QUOTED_IDENTIFIER ON
GOALTER PROCEDURE [dbo].[TestProcedure]
@UserName NVARCHAR(100)
ASBEGIN BEGIN TRYEXECUTE AS LOGIN = @UserName
SELECT * FROM CRM_DB_Name.dbo.FilteredAccount
REVERT;
END TRY BEGIN CATCHREVERT;
END CATCHENDNote: Make sure you write the “REVERT” command to stop the user impersonation inside your stored procedure.
In this way we have impersonated the application pool identity user with the logged in CRM user. Thus, we can fetch the data from filtered views based on logged in user security roles.
I hope this would be helpful.
UPDATE: The External Connector License is obsoleted. The connector was removed from the pricelist in January 2014. From the quick reference guide:
"Access by external (third party) users is included with the Server License; you do not need CALs unless using Microsoft Dynamics CRM client applications. External users are users that are not either your or your affiliates’ employees, or your or your affiliates’ onsite contractors or onsite agents."
One of our customers, working on CRM 2011 on-premises, would like to provide the access of CRM data to external parties, like their service providers, customers and other contacts. At present, these people have been created as contacts in CRM. I was asked to prepare high level design, a work model that allows this group of people to access the Dynamics CRM data. I have prepared a design wherein we decided to give access to external parties via the existing web site of my customer. I have also explained that we require External Connector License for this implementation. However, as I never used it before, I would like to collect more details on External Connector License.
I thought once we purchase such uncommon license from Microsoft, they would allow us to assign it to one of the existing Dynamics CRM users and the credentials of that user can be consumed at web portal then to fetch/update CRM data. To validate my understanding, I put the same as question on different Dynamics CRM communities, forums and groups.
I found that my conception was wrong. The External Connector License is just a paper license, a trust license. It has nothing to do with the implementation. To validate the cost for this license, you can refer below link.
http://crmpublish.blob.core.windows.net/docs/Pricing_Licensing_Guide.pdf
You could also refer the below links that help me to confirm it.
http://social.microsoft.com/Forums/en-US/crmdevelopment/thread/6843ac17-4946-4ac4-8e88-22a5fae3e425
Note: The External Connector License is not applicable to Dynamics CRM 2011 online
Please feel free to update this post with your experience about External Connector License.
Yesterday one of my customers had discussed about the functionality of uncomforting orders, which was stopped working unexpectedly. She said that everything was working well a week ago.
This customer works on Dynamics CRM 2011 online. So, being a system administrator on the same instance, I immediately tried to login to the production server, but unfortunately she had deactivated me as she wanted to assign the same license to one of their new sales team member. So, I asked her to invite me again and provide the admin rights to validate the problem. For, this functionality I had configured a workflow (process) to activate the fulfilled order. So, on very first step I did validate the System Jobs in Settings area. Over there, I found that the some of the workflow records were sitting in listening (waiting) mode, while some had executed successfully.
Upon further inspection, I had discovered that the waiting mode workflows were still owned by me. As she deactivated me on the production server, all the workflow jobs were waiting for me to be activated again. So, we instantly changed the owner of those workflows and resume the workflow jobs. Voila! Everything started working well then.
Hence, the learning is, we should not own the workflows in production environment of our customers, so that they do not face the above problem.
I hope this would be helpful.
Hello everybody,
I would like to draw your attention to the Microsoft Dynamics Most Influential Top 100 List for 2013.
I am pleased to tell you that I have been nominated and that we are now in the voting process.
If you believe that I deserve it then please spare a few seconds time and take part in below voting poll by giving your invaluable vote to “Ankit Shah”.
Currently, I came across a scenario where we had to configure a workflow to send an e-mail on a specified date value on an opportunity entity. On opportunity entity I had a date field “Date 1” and what we were required to do was to send an email to opportunity owner on a date specified in the Date 1 field value. To achieve this, I can configure a workflow with timeout or wait condition set on the Date 1 value.
First, I tried to make it work using the Timeout criteria but it seemed to fail our requirements when the date value is null. So, I decided to work with wait condition.
Following are the steps configured in workflow to meet the requirements:-
Step 1: Start workflow on Record Created and Record Fields change. In Record fields change select the Date1 field.
Step 2: Check if Date1 field is null. If the field is null then no need to set any wait condition.
Step 3: Since we have fired this workflow on field change also, we had to make sure that there should not be more than one workflow with wait condition. When opportunity record is created and Date 1 field contains data, a workflow record would be created in wait mode. At the same time, if somebody modifies the date 1 value for the same opportunity record then another workflow record should not be crated in waiting mode to be executed on that particular updated date value. Instead, the previously created workflow should be updated with new value. To achieve this we have taken a custom attribute here DateValue which is a two option field. Default value of DateValue is false. Once a date is entered the value of datevalue gets updated to true. This way we ensure that on field change we don’t create a new wait condition if one already exists.
Step 4: If the attribute value is false means there is no previously existing system job with wait condition. So, Add step of wait condition and set process execution time on or after the Date1 value. If the value is true means the workflow record was already created and nothing to do in that scenario.
Step 5: Add a Send Email step and configure required values.
I hope this would be helpful.