Tuesday, August 25, 2020

Show Sitemap Sub areas based on Security Roles

 I came across a requirement where we had to show the Sitemap certain areas only to the Application Admins and hide it from the Users.

Yes it can be configured by removing entity privileges for the User Security role but there were dependencies on the entity as it was a lookup.

So removing the security privilege will also take away the permissions to append and view.

So to just show the entities on Sitemap only to Admins not for other Users we have used the functionality of Sitemap editor where without any code it can achieved using Privileges Feature.

Let us consider a scenario where User A is Sales Person and User B is Sales Admin.

I should Hide the Accounts  for User A i.e Sales Person but she should be able to select Account while creating a Contact and Read it too.





Step 1 : Go to Sitemap Editor and of Application and select that entity.


Step 2 : Click on Properties and scroll down towards Advanced > Privileges




Step 3 : Now Sales Admin has privileges on Account to Create, Write or Delete but Sales User does not has. He has only Read Permission. So select the ones which Admins have.




Step 4: Now this Account in Sitemap will be visible only to the Sales Admin not for Sales User as we have configured the Privileges. Publish the changes.


This will enable to hide entity on Sitemap without effecting functionality based on Security Roles.

Things to Remember :

1. If you add Account entity in any other group and do not configure this Privilege Setting, it will be visible due to Read permissions.

2. Even different entities and combinations can be configured to hide or show based on Organization needs.




Monday, August 24, 2020

Update Multi Select Option From Portal using MS Flows

Before Multiselect field option was introduced, we used to implement this using Javascript and HTML either in CRM or Portal.

Now to migrate this functionality to OOB MultiSelect Field you can use either Plugins or MS Flows.

MS Flows are very easy tool to help to migrate the values stored in text fields for a MultiSelect Option Field. This can be used to migrate already present values or from Portals.

So here I have used 2 steps to implement it.

Step 1 : Create a trigger using Common Data Service (current environment) in Flow as shown below.


Step 2 : Next Select Update a Record Action and give the Text field output as input to Multi select 
field.


Here Fav Colour is a MultiSelect Option Set. Sometimes these options will not be shown so select Enter Custom Value.


Give the Multi select text field as input to the Multi Select Option.

Things to Remember :

1. The values in the text field should be in format like 1,2,3  
2. Use only commas in text fields as separators and no ending commas too (as I faced error initially coz of that)
3. Values of multi select field are retrieved like in below image.



4. Create Flows in the Solution of your environment to get the CDS(current environment) connector.

Thursday, August 13, 2020

MultiSelect Field in Dynamics Portal - Easy Solution

In Dynamics 365 Version 9 we got a new Attribute Type i.e Multiselect Option.

But it is not yet supported in PowerApps Portal/Dynamics 365 Portal when they are added on the form.

Multiselect fields are not visible when we utilize them through Web forms or Entity forms in Portal.

So to solve it there are multiple solutions based on requirements.

1. Easy Solution


If you have a Multi select option with fixed Options or which are in less number then this will do good.

Step 1 :  

Create a text field which you will use to save the values of multi select Option from CRM.
Let us assume it as "new_multiselecttext" field.

Step 2 : 

Now we have to do some Custom JS coding to add our fixed Multi Select Option in Entity Form. So hide the text field for users on portal using below code.

$("#new_multiselecttext").hide();

Make sure this is added on the form in CRM to work.

Step 3 : 

Create a multiselect field now and append it to that field where you want to see.

var multiselect = $('<select multiple><option value="1">Red</option><option value="2">Blue</option><option value="3">Green</option><option value="4">Orange</option></select>');
    multiselect.insertAfter("#new_multiselecttext");

Step 4: 

Now to get the selected options to text field we need to add Change property.

multiselect.change(function () {
        ("#new_multiselecttext").val($(this).val());
    });

Step 5: 

It may look like below where Ctrl button is required to select multiple Options.


 

Whole Code:

$(document).ready(function () {
    var multiselect = $('<select multiple><option value="1">Red</option><option value="2">Blue</option><option value="3">Green</option><option value="4">Orange</option></select>');
    multiselect.insertAfter("#new_multiselecttext");
            $("#new_multiselecttext").hide();
    multiselect.change(function () {
    
      var values = $(this).val();
        $("#new_multiselecttext").val(values);
    });

});


Step 6: 

We are done with Portal side, now to save this values into our actual OOB Multiselect field, write a plugin code which gets triggered on Create or Update of that Text field.

public void Execute(IServiceProvider serviceProvider)
{
	var context = (IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext));

	var entity = context.InputParameters["Target"] as Entity;

	if (entity.Attributes.ContainsKey("new_multiselecttext"))
{ OptionSetValueCollection colours = new OptionSetValueCollection(); foreach (var option in entity.GetAttributeValue("new_multiselecttext").Split(','))
{ colours.Add(new OptionSetValue(int.Parse(option))); } entity["new_favcolour"] = colours; } }

If you have more options which can change or get added in future then you can go for Second Part.. 



Monday, November 11, 2019

Create CRM fields from Code

Below are the snippets for creating fields:

// Create a boolean attribute BooleanAttributeMetadata boolField = new BooleanAttributeMetadata { // Set base properties - language code = 1033 for english SchemaName = "new_boolean", DisplayName = new Label("Sample Boolean", _languageCode), RequiredLevel = new AttributeRequiredLevelManagedProperty(AttributeRequiredLevel.None), Description = new Label("Boolean Attribute", _languageCode), // Set extended properties OptionSet = new BooleanOptionSetMetadata( new OptionMetadata(new Label("True", _languageCode), 1), new OptionMetadata(new Label("False", _languageCode), 0) ) };

// Create a date time attribute DateTimeAttributeMetadata dtAttribute = new DateTimeAttributeMetadata { // Set base properties SchemaName = "new_datetime", DisplayName = new Label("Sample DateTime", _languageCode), RequiredLevel = new AttributeRequiredLevelManagedProperty(AttributeRequiredLevel.None), Description = new Label("DateTime Attribute", _languageCode), // Set extended properties Format = DateTimeFormat.DateOnly, ImeMode = ImeMode.Disabled };

// Create a decimal attribute DecimalAttributeMetadata decimalAttribute = new DecimalAttributeMetadata { // Set base properties SchemaName = "new_decimal", DisplayName = new Label("Sample Decimal", _languageCode), RequiredLevel = new AttributeRequiredLevelManagedProperty(AttributeRequiredLevel.None), Description = new Label("Decimal Attribute", _languageCode), // Set extended properties MaxValue = 100, MinValue = 0, Precision = 1 };

// Create a integer attribute IntegerAttributeMetadata integerAttribute = new IntegerAttributeMetadata { // Set base properties SchemaName = "new_integer", DisplayName = new Label("Sample Integer", _languageCode), RequiredLevel = new AttributeRequiredLevelManagedProperty(AttributeRequiredLevel.None), Description = new Label("Integer Attribute", _languageCode), // Set extended properties Format = IntegerFormat.None, MaxValue = 100, MinValue = 0 };

// Create a memo attribute MemoAttributeMetadata memoAttribute = new MemoAttributeMetadata { // Set base properties SchemaName = "new_memo", DisplayName = new Label("Sample Memo", _languageCode), RequiredLevel = new AttributeRequiredLevelManagedProperty(AttributeRequiredLevel.None), Description = new Label("Memo Attribute", _languageCode), // Set extended properties Format = StringFormat.TextArea, ImeMode = ImeMode.Disabled, MaxLength = 500 };


// Create a money attribute MoneyAttributeMetadata moneyAttribute = new MoneyAttributeMetadata { // Set base properties SchemaName = "new_money", DisplayName = new Label("Money Picklist", _languageCode), RequiredLevel = new AttributeRequiredLevelManagedProperty(AttributeRequiredLevel.None), Description = new Label("Money Attribue", _languageCode), // Set extended properties MaxValue = 1000.00, MinValue = 0.00, Precision = 1, PrecisionSource = 1, ImeMode = ImeMode.Disabled };

PicklistAttributeMetadata pickListAttribute = new PicklistAttributeMetadata { // Set base properties SchemaName = "new_picklist", DisplayName = new Label("Sample Picklist", _languageCode), RequiredLevel = new AttributeRequiredLevelManagedProperty(AttributeRequiredLevel.None), Description = new Label("Picklist Attribute", _languageCode), // Set extended properties // Build local picklist options OptionSet = new OptionSetMetadata { IsGlobal = false, OptionSetType = OptionSetType.Picklist, Options = { new OptionMetadata( new Label("Created", _languageCode), null), new OptionMetadata( new Label("Updated", _languageCode), null), new OptionMetadata( new Label("Deleted", _languageCode), null) } } };
CreateAttributeRequest createAttributeRequest = new CreateAttributeRequest
{ EntityName = Contact.EntityLogicalName, Attribute = anAttribute }; // Execute the request. _serviceProxy.Execute(createAttributeRequest);

For Lookup fields


                        CreateOneToManyRequest createOneToManyRelationshipRequest =
                            new CreateOneToManyRequest
                            {
                                OneToManyRelationship =
                            new OneToManyRelationshipMetadata
                            {
                                ReferencedEntity = "account",
                                ReferencingEntity = "new_customentity", //Entity to have lookup field
                                SchemaName = "new_account",
                                AssociatedMenuConfiguration = new AssociatedMenuConfiguration
                                {
                                    Behavior = AssociatedMenuBehavior.UseLabel,
                                    Group = AssociatedMenuGroup.Details,
                                    Label = new Label("Account", 1033),
                                    Order = 10000
                                },
                                CascadeConfiguration = new CascadeConfiguration
                                {
                                    Assign = CascadeType.Cascade,
                                    Delete = CascadeType.Cascade,
                                    Merge = CascadeType.Cascade,
                                    Reparent = CascadeType.Cascade,
                                    Share = CascadeType.Cascade,
                                    Unshare = CascadeType.Cascade
                                }
                            },
                                Lookup = new LookupAttributeMetadata
                                {
                                    SchemaName = "new_parent_accountid",
                                    DisplayName = new Label("Account Lookup", 1033),
                                    RequiredLevel = new AttributeRequiredLevelManagedProperty(AttributeRequiredLevel.None),
                                    Description = new Label("Sample Lookup", 1033)
                                }
                            };


                        CreateOneToManyResponse createOneToManyRelationshipResponse =
                            (CreateOneToManyResponse)appService.Execute(
                            createOneToManyRelationshipRequest);

                      Guid  _oneToManyRelationshipId = createOneToManyRelationshipResponse.RelationshipId;
                    string  _oneToManyRelationshipName =
                            createOneToManyRelationshipRequest.OneToManyRelationship.SchemaName;

                        Console.WriteLine(
                            "The one-to-many relationship has been created between {0} and {1}.",
                            "account", "campaign");
                   
                   


Monday, December 17, 2018

Adding Email Signatures with Image Hyperlink

Steps to include images hosted in Portal:
  1.   First Create a Image in a server which is accessible without any authentication.
  2.    If you have portal you can host it there with Admin role, go to the Home page of portal and  in Content Editor, select New à Child file.
  3. Give a Name to the image and browse the image which need to be included in the Email signature and save it. Note the Partial URL, as this will be used to navigate to the image.


4. To use this image as a hyper link in signature, go to home page of portal and select New à Child Page.


      5.  In the General Tab, give the name for Page, note down the Partial URL and select a blank template where image is visible.


            6. Next go to Language Content tab and select the Image icon in Copy section. This is to browse the image created in the previous steps.









7.  Then navigate to the Link tab and give the URL to which the image should link and click on OK.

  8. Image can be observed in Copy section, then save it.
9. Now navigate to the URL of the page created and copy the image.(This is Image with HyperLink)


10.  Now Navigate to Email Signatures in Settings > Templates and select Email Signatures.


11. Click on ‘New’ and give a title to the Email Signature.
12. Paste the image copied in previous steps in Email signature using Ctrl+V.
(Note:Use Internet explorer or Edge browser to copy and paste image in email signature body)

        13. Click on Save button and Set as Default button(optional). Insert Signature can be used on Email if it is not default.
14. After signature is saved and set as default, it will appear when a new email is created as below.


          15. The links can be tested after the email is sent.


NOTE: The images from other URL can be used like above if the image has referenced link without authentication.☺️




Show Sitemap Sub areas based on Security Roles

 I came across a requirement where we had to show the Sitemap certain areas only to the Application Admins and hide it from the Users. Yes i...