Advertisements

Archive

Posts Tagged ‘CRM’

(401) Unauthorized Error – CRM integration with SharePoint

December 12, 2017 Leave a comment

We encountered below exception when we were integrating CRM with SharePoint.

Exception: System.Net.WebException: The remote server returned an error: (401) Unauthorized.

Environment details:

  • CRM 2016 on-premise with Claims authentication enabled.
  • SharePoint Server On-premise with Claims authentication enabled.
  • User Account using to set up is Admin on both the CRM and Sharepoint servers.

Reason & Fix:

Fix suggested in this MSDN Forum worked for us.

It seems there is a known issue/bug with CRM 2016 that doesn’t allow this to work if you try using https in the MetadataEndPoint.

To get this working, you will have to temporarily do the following items before running the SharePoint Power Shell command.

Note : Make sure you note all the existing settings before executing below steps which helps you to roll back, if something goes wrong.

Steps:

  1. Open the CRM Deployment Manager tool
    • Disable CRM IFD
    • Disable CRM Claims Configuration
  2. Open the IIS and remove the https binding on the CRM Web site and add back the http binding for the CRM Web site.
  3. Run CRM Deployment Manager and change the properties of the deployment for the Web Address to use http instead of https.
  4. Run an IISReset on the CRM Server to ensure this is now accessible via http.
  5. Run the SharePoint PowerShell commands (you should be able to access the MetadataEndpoint using http vs. https now if you put it in the browser (and it should prompt to download a .json file).
  6. Once the SharePoint commands are finished running, you need to reverse the changes above in CRM to re-enable IFD.
  7. Change the CRM Web Address to use https in the CRM Deployment Properties.
  8. Remove the http binding on the CRM Web site and add back the https binding, selecting the correct SSL Certificate.
  9. Run the Configure CRM Claims in the CRM Deployment Manager.  (keep the existing settings)
  10. Run the Configure IFD in the CRM Deployment Manager (keep existing settings).
  11. Run an IISReset on the CRM Server.

Refer MSDN article  which details integrating SharePoint on-premise with CRM on-premise.

🙂

Advertisements

Set “Created On”,” Created By”, “Modified On”, “Modified By” fields using SDK/Data Import/Plug-in – Dynamics 365

November 18, 2017 Leave a comment

I got an ask from one of my blog followers on how to set “Created On” field of a record, as it defaults to current date.

In this article I am going to explain various ways to set these values.

Override ‘Created On’ using Data Import:

  • Using ‘Data Import’, setting the “Created On” is straight forward and all you need is to add a column “Created On” in your .csv file and import.

Override Created On - Data Import

  • For non-system admin users who import, make sure “Override Created on or Created by…” Privilege is checked in their Security Role.

Override Created On - Privilege

Points to Ponder:

  • Even though the privilege “Override Created on or Created by for records during data import” name suggests overriding “Created by” field but we cannot override “Created by” via Data Import.

Override ‘Created On’ using SDK:

  • Set the “overriddencreatedon” field to the date, which you want your “Created On” date as.
  • Post the execution of code, “Created On” value will be overridden with the Date set in “overriddencreatedon” field and “overriddencreatedon” field will default to todays date.
  • For example, today is “01-01-2017” and you want the “Created On” as “01-01-2016”
    • Set “overriddencreatedon” to “01-01-2016”
    • After code execution, “Created On” will set to “01-01-2016” and “overriddencreatedon” will be today (i.e., 01-01-2017)

Sample code:

Entity contact = new Entity(“contact”);
contact[“firstname”] = “Contact Migrated”;
contact[“overriddencreatedon“] = new DateTime(2016, 01, 01);
_service.Create(contact);

Override “Created On”,” Created By”,” Modified On”,” Modified By” using Plug-in:

  • To Override the fields, we need to go for plug-in approach.
  • Register a “PreOperationCreate” plug-in and set the fields.

Override Created On - Plug-in step

Plug-in Code:

public void Execute(IServiceProvider serviceProvider){
// Obtain the execution context from the service provider.
IPluginExecutionContext context = (IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext));

// The InputParameters collection contains all the data passed in the message request.
if (context.InputParameters.Contains(“Target”) && context.InputParameters[“Target”] is Entity)
{
// Obtain the target entity from the input parameters.
Entity TargetEntity = (Entity)context.InputParameters[“Target”];

// Set date in Past
TargetEntity[“createdon”] = new DateTime(2016, 01, 01);
TargetEntity[“modifiedon”] = new DateTime(2016, 01, 01);
// Set the GUID of non-calling user
TargetEntity[“createdby”] = new EntityReference(“systemuser”, new Guid(“5BB6EF5F-6BCC-E711-A831-000D3A1BE051”));
TargetEntity[“modifiedby”] = new EntityReference(“systemuser”, new Guid(“5BB6EF5F-6BCC-E711-A831-000D3A1BE051”));
}
}

  • Once this plug-in executes, values will get overridden with the passed values.

Override Created On - Plug-in

Points to Ponder:

  • As you would have noticed, it requires a plug-in to set the ”Created By”,” Modified On”,” Modified By” fields which is an overhead.
  • But this approach is extremely useful in “Data Migration” as this is common ask while migrating historical client data.
  • Have the plug-in step enabled during “Data Migration” and deactivate post migration.

 

CRM Record “Email a Link” feature not working

February 8, 2017 Leave a comment

Recently few of our CRM users complained OOB “Email a Link” not working.

email-link

Reason:

  • Machines default “Email” App was set to “Chrome”

email-settings

Fix:

  • Change default “Email” App to “Mail” or “Outlook” client

 

email-settings-set-to-mail-client

🙂

Categories: CRM, Uncategorized Tags: , ,

Retrieve Global Option set details – CRM SDK

January 28, 2017 Leave a comment

Below is the sample code to retrieve existing Global Option sets along with Option text & values using RetrieveAllOptionSetsRequest :

var retrieveAllOptionSetsRequest = new RetrieveAllOptionSetsRequest();

RetrieveAllOptionSetsResponse retrieveAllOptionSetsResponse = (RetrieveAllOptionSetsResponse)orgService.Execute(retrieveAllOptionSetsRequest);

if (retrieveAllOptionSetsResponse.OptionSetMetadata.Count() > 0){
StringBuilder sb = new StringBuilder();
foreach (OptionSetMetadataBase optionSetMetadataBase in retrieveAllOptionSetsResponse.OptionSetMetadata){
if (optionSetMetadataBase.OptionSetType != null){
if ((OptionSetType)optionSetMetadataBase.OptionSetType == OptionSetType.Picklist){
OptionSetMetadata optionSetMetadata = (OptionSetMetadata)optionSetMetadataBase;
sb.AppendLine(“OptionSetDisplayName – ” + ((optionSetMetadata.DisplayName.LocalizedLabels.Count > 0) ? optionSetMetadata.DisplayName.LocalizedLabels[0].Label : String.Empty));
sb.AppendLine(“***************************************************”);

foreach (OptionMetadata option in optionSetMetadata.Options){
sb.AppendLine(“Option”);
sb.AppendLine(“OptionValue – ” + option.Value.ToString());
sb.AppendLine(“OptionDescription – ” + option.Label.UserLocalizedLabel.Label.ToString());
}
}
else if ((OptionSetType)optionSetMetadataBase.OptionSetType == OptionSetType.Boolean){
BooleanOptionSetMetadata optionSetMetadata = (BooleanOptionSetMetadata)optionSetMetadataBase;
// Start OptionSet Node
//metadataWriter.WriteAttributeString(“OptionSetType”, OptionSetType.Boolean.ToString());
if (optionSetMetadata.DisplayName.LocalizedLabels.Count != 0)
sb.AppendLine(“OptionSetDisplayName – ” + optionSetMetadata.DisplayName.LocalizedLabels[0].Label);
else
sb.AppendLine(“OptionSetDisplayName – ” + “UNDEFINED”);

sb.AppendLine(“**************************************************”);

// Writes the TrueOption
sb.AppendLine(“TrueOption”);
sb.AppendLine(“OptionValue – ” + optionSetMetadata.TrueOption.Value.ToString());
sb.AppendLine(“OptionDescription – ” + optionSetMetadata.TrueOption.Label.UserLocalizedLabel.Label.ToString());
sb.AppendLine(“FalseOption”);
sb.AppendLine(“OptionValue – ” + optionSetMetadata.FalseOption.Value.ToString());
sb.AppendLine(“OptionDescription – ” + optionSetMetadata.FalseOption.Label.UserLocalizedLabel.Label.ToString());
}
}
sb.AppendLine(string.Empty);
}

Console.WriteLine(sb.ToString());

Output would be

global-options-1

global-options-2

🙂

Categories: CRM, Uncategorized Tags: ,

CRM Date and Time field – Behaviors

December 18, 2016 2 comments

Recently, I was asked a question in my blog on what is the significance of the different ‘Behaviors’ of ‘Date and Time’ field.

There are 3 different behaviors available for ‘Date and Time’ field.

Date and Time field behavior

Date and Time field behavior

User Local:

  • Time zone would be applied on this behavior. Field’s Date and time would be shown based on current user’s time zone.
  • ‘User Local’ behavior of a Field can be changed to other behaviors after field creation.
  • If the field behavior changed,
    • Behavior change takes affect only to the newly added/updated field values.
    • The existing field values remain in the database in the UTC time zone format.
  • To change the behavior of the existing field values from UTC to Date Only we would need SDK call (ConvertDateAndTimeBehaviorRequest)
  • Below is the sample code

var request = new ConvertDateAndTimeBehaviorRequest(){
Attributes = new EntityAttributeCollection() {
new KeyValuePair<string, StringCollection>(“account”, new StringCollection()
{ “new_sampledatetimeattribute” })
},
ConversionRule = DateTimeBehaviorConversionRule.SpecificTimeZone.Value,
TimeZoneCode = 190, // Time zone code for India Standard Time (IST) in CRM
AutoConvert = false // Conversion must be done using ConversionRule
};

// Execute the request
var response = (ConvertDateAndTimeBehaviorResponse)_serviceProxy.Execute(request);

 

    • Conversion rules:
      • SpecificTimeZone: Converts UTC value to a DateOnly value as per the specified time zone code.
      • CreatedByTimeZone: Converts UTC value to a DateOnly value that the user who created the record.
      • OwnerTimeZone: Converts UTC value to a DateOnly value that the user who owns the record.
      • LastUpdatedByTimeZone: Converts UTC value to a DateOnly value that the user who last updated the record
  • When you execute the ConvertDateAndTimeBehaviorRequest message, a system job (asynchronous operation) is created to run the conversion request.

Date Only:

  • Time zone isn’t applicable to this behavior. Field values are displayed without the time zone conversion.
  • The time portion of the value is always 12:00AM
  • This Behavior can’t be changed to other behavior types, once it’s set.
  • The Date Only behavior is good for cases when information about the time of the day and the time zone isn’t required, such as such as birthdays or anniversaries.

Time-Zone Independent:

  • Time zone isn’t applicable to this behavior. The field values are displayed without the time zone conversion.
  • This Behavior can’t be changed to other behavior types, once it’s set.
  • You can use this behavior when time zone information isn’t required, such as the hotel check-in time.

Refer MSDN article for more details.

🙂

Categories: CRM Tags: , ,

Complete a transaction and throw exception in CRM Plug-in

July 31, 2016 3 comments

Recently I was asked a question in my blog on how to achieve below scenario in plug-in.

  • User try to save Account record by providing data in multiple fields.
  • Create Plug-in should check whether any other Account already exists in CRM with provided data.
  • If match found, update the existing record and display “Cannot save the Account as Account with data already exists”
  • If no match found, create an Account.

Challenge:

  • If ‘Account’ match found, system should update matched Account and at the same time throw message “Cannot save the Account as Account with data already exists”.
  • To display message Plugin must throw Execution with message which would roll back the update operation.

Proposed Design:

  • Register a Plug-in on “PreCreateAccount” with following logic, if matching ‘Account’ already exists with input data.
  • To complete update operation,
    • Use “ExecuteMultipleRequest” with option “ContinueOnError = true” which completes transaction.
    • Instantiate ‘UpdateRequest’ and execute using “ExecuteMultipleRequest”
  • In next line, throw exception with message

Plug-in Code:

// Get the matched Account
Entity matchedAccount = new Entity(“account”);
UpdateRequest reqUpdate = new UpdateRequest();
reqUpdate.Target = matchedAccount;

// Use this to complete the update operation even on an exception
ExecuteMultipleRequest reqMultiple = new ExecuteMultipleRequest(){
Requests = new OrganizationRequestCollection(),
Settings = new ExecuteMultipleSettings(){
ContinueOnError = true,
ReturnResponses = false
}
};

// Add Update Request to Multiple Request.
reqMultiple.Requests.Add(reqUpdate);

// Trigger the Execute Multiple.
crmOrgService.Execute(reqMultiple);

// Use this to display message to user
throw InvalidPluginExecutionException(“Cannot save the Account as Account with data already exists”);

🙂

Categories: CRM Tags: , ,

System.Web.HttpUnhandledException – While opening a CRM record

Other day we were getting “Unexpected” exception while opening a ‘Contact’ record.

There were no error details to check at application level.

When I verified my CRM application server’s Event viewer, there was below error log

Exception of type ‘System.Web.HttpUnhandledException’ was thrown.

at System.Web.UI.Page.HandleError(Exception e)

at System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint)

at System.Web.UI.Page.ProcessRequest(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint)

Index was outside the bounds of the array.

Fix:

  • By resetting the IIS on CRM application servers solved the issue.

Reason:

  • Not sure what caused this exception, as nothing had been customized on Contact entity.

🙂