Sam's Microsoft Dynamics 365 Blog

Wednesday, 26 September 2018

Create Ads in Dynamics Portal


Create Ads in Dynamics Portal

Here is an OOB feature to Display Ads on Portal in Dynamics Portals. Here we can create text or image-based ads and have they run in multiple placements In Portal. We can choose release and expiration dates for time-sensitive, scheduled content. Ads can be hyperlinked to any destination and open in the current window or a new window. Advertisements are displayed in the portal via two Dynamics 365 entities: The Ad Placement entity and associated Ad entity.

1.      Create an Ad

Portal ==> Ads ==> New

a.       Put a Name of Ad e.g. Product Advertisment
b.      Select Website e.g. Partner Portal
c.       Publishing State as Published
d.      Also can select Release Date and Expiration Date
e.       Redirect URL to redirect after click on Ad
f.        Put your Content in Content Tab or put image in Image Detail Tab or we can put both.
g.      Save it.





2.      Create an Ad Placement

Portal ==> Ad Placement ==> New

a.       Put a Name of Ad e.g. Product Advertisment
b.      Select Website e.g. Partner Portal
c.       Select Ad inside Ads Subgrid e.g. Product Advertisment
d.      Save it.




                3.   Include created Ad in Web Page

Portal ==> Web Pages ==> Select a Web Page

a.       Inside Content Tab of Web Page (e.g. Product New) Include  an Ad


{% include 'ad' ad_name:'Product Advertisment' %}




Now we can see Ad on the Portal, as I have added on Product entity List



Monday, 17 September 2018

Send Email on birthday in MS Dynamics CRM Using Azure Function App


Create an Azure Function App as explained in below steps:-

Open Visual Studio 2017, Create a new Project then Select Cloud tab and then select Azure Functions.
New Project => Cloud => Azure Functions
Name it and then click Ok.



Now select:-

a.       .Net Framework
b.      Http trigger
c.       Storage Account(AzureWebJobsStorage) :  Storage Emulator
d.      Schedule: 0 */5 * * * *


After click on Ok it will create a code. In this code it will execute every day at 8:30 AM, and print a log.  Code will look like as shown in below screenshot:


Now Run it locally. Then a Console window will open Also opens a Windows security Alert then Allow Access , looks like as shown in below screenshot:-



It will execute. Also we can debug it.


Now we can check log inside console, As shown in below screenshot.



Now we are going to put below code of sending emails, also putting TimerTrigger as 0 30 8 * * * (it will execute every day at 8: 30 AM)

Main Run method:-
var connectionString = ConfigurationManager.ConnectionStrings["CRMConnectionString"].ConnectionString; ;
            // Connect to the CRM web service using a connection string.
            ServicePointManager.SecurityProtocol = (SecurityProtocolType)3072; //need to add ref System.Net
            CrmServiceClient conn = new Microsoft.Xrm.Tooling.Connector.CrmServiceClient(connectionString);
            // Cast the proxy client to the IOrganizationService interface.
            IOrganizationService _orgService = (IOrganizationService)conn.OrganizationWebProxyClient != null ? (IOrganizationService)conn.OrganizationWebProxyClient : (IOrganizationService)conn.OrganizationServiceProxy;

            var query = new QueryExpression("contact");

            ConditionExpression condition1 = new ConditionExpression();
            condition1.AttributeName = "birthdate";
            condition1.Operator = ConditionOperator.Equal;
            condition1.Values.Add(DateTime.Now);

            FilterExpression contactfilter = new FilterExpression();
            contactfilter.Conditions.Add(condition1);

           query.ColumnSet = new ColumnSet(true);
            query.Criteria.AddFilter(contactfilter);

            EntityCollection TodayBirthdayReq = _orgService.RetrieveMultiple(query);
            foreach (Entity contact in TodayBirthdayReq.Entities)
            {
                if (contact.Attributes.Contains("emailaddress1") && contact.Attributes.Contains("fullname"))
                {
                    fnsendBirthdayEmail(contact.Attributes["fullname"].ToString(), contact.Attributes["emailaddress1"].ToString());
                }
            }



fnsendBirthdayEmail:-

        public static void fnsendBirthdayEmail(string fullname, string ContactEmail)
        {
            string myEmail = "sam@gmail.com";
            string myPassword = "password";
            string subject = "Birthday Wish!";
            string body = "Dear " + fullname + " wish you a very happy birthday.!!!";
            SmtpClient client = new SmtpClient();
            client.Port = 587;
            client.Host = "smtp.gmail.com";
            client.EnableSsl = true;
            client.Timeout = 10000;
            client.DeliveryMethod = SmtpDeliveryMethod.Network;
            client.UseDefaultCredentials = false;
            client.Credentials = new System.Net.NetworkCredential(myEmail, myPassword);
            MailMessage _MailMessage = new MailMessage(myEmail, ContactEmail, subject, body);
            _MailMessage.BodyEncoding = UTF8Encoding.UTF8;
            _MailMessage.DeliveryNotificationOptions = DeliveryNotificationOptions.OnFailure;

            client.Send(_MailMessage);
        }


Now Publish it:-

1.       Click on Publish.


2.       Select Create New and then OK


3.       Put App Name and other field values as shown in below screenshot and then click on Create.


4.       Now we can check the function app URL in Site URL.


5.       After completion we can check in Azure.



Let check its working:-



Now let’s check email.




Friday, 7 September 2018

Trigger a Plugin while Record Open of any entity.


Sometimes we need to trigger a Plugins while a record is open, but we face a lots of issue. So here I am explaining how we can trigger our Plugin on event of any record open.
There are major three things which help us:-


             Plugin
          Action    
          JavaScript web resource

Let us discuss with an real world example:- I want to create an activity at the time of contact record is open with the help of a Plugin.
So first I will create an Action in MS Dynamics
Setting => Customization=> Customize the System => Processes





Add new Process



Put a name and select Category as Action and Entity as None (global).
Click ok. Now we can add Argument if we need to pass on Plugin. Here I am adding to Arguments- ActivityName and ActivityDescription. (I will pass value from my JavaScript code).





Now Save it, Publish it and Activate it.

Note: - Here Unique Name of my action will be displayed on Plugin Registration Tool as a message.

Now  I will write a Plugin Like:-





Code:-
using Microsoft.Xrm.Sdk;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace PluginCreateActivity
{
    public class CreateActivity : IPlugin
    {
        public void Execute(IServiceProvider serviceProvider)
        {
            IPluginExecutionContext context = (IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext));
            IOrganizationServiceFactory factory = (IOrganizationServiceFactory)serviceProvider.GetService(typeof(IOrganizationServiceFactory));
            IOrganizationService service = factory.CreateOrganizationService(context.UserId);
            IOrganizationService service1 = (IOrganizationService)serviceProvider.GetService(typeof(IOrganizationService));
            if (context.InputParameters != null)
            {
                string ActivityName = context.InputParameters.Contains("ActivityName") ? (string)context.InputParameters["ActivityName"] : "";
                string ActivityDescription = context.InputParameters.Contains("ActivityDescription") ? (string)context.InputParameters["ActivityDescription"] : "";

                Entity task = new Entity("task");
                task["subject"] = ActivityName;
                task["description"] = ActivityDescription;
                task["regardingobjectid"] = new EntityReference("contact",new Guid("336B5DF8-DDA9-E811-A965-000D3AF06236"));
                service.Create(task);
            }
        }
    }
}


Now register the Plugin and the add step like:-
Message = Unique Name of Action.
Primary Entity= none.
Secondary Entity= none.



Now the Third Step is Add a javascript code as Web resource like:-
Setting => Customization=> Customize the System => Web Resources




Add new. Put a Name, Type as Script (JScript). And paste below JavaScript code in Text Editor.
Code:-

//Main Function
//fn Proceed To Call Action and Plugin
function fnProceedToCallActionPlugin() {
    ActivityName = "sam test Activity";
    ActivityDescription = "This is a test of an Action activity, while opening a record."
    fnRequestToCallaPlugin(ActivityName, ActivityDescription);
}

///fn Request To Call a Plugin
function fnRequestToCallaPlugin(ActivityName, ActivityDescription) {

    try{
        // Creating the request XML for calling the Action
        var requestXML = ""
        requestXML += "<s:Envelope xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\">";
        requestXML += "  <s:Body>";
        requestXML += "    <Execute xmlns=\"http://schemas.microsoft.com/xrm/2011/Contracts/Services\" xmlns:i=\"http://www.w3.org/2001/XMLSchema-instance\">";
        requestXML += "      <request xmlns:a=\"http://schemas.microsoft.com/xrm/2011/Contracts\">";
        requestXML += "        <a:Parameters xmlns:b=\"http://schemas.datacontract.org/2004/07/System.Collections.Generic\">";
        requestXML += "          <a:KeyValuePairOfstringanyType>";
        requestXML += "            <b:key>ActivityName</b:key>";
        requestXML += "            <b:value i:type=\"c:string\" xmlns:c=\"http://www.w3.org/2001/XMLSchema\">" + ActivityName + "</b:value>";
        requestXML += "          </a:KeyValuePairOfstringanyType>";
        requestXML += "          <a:KeyValuePairOfstringanyType>";
        requestXML += "            <b:key>ActivityDescription</b:key>";
        requestXML += "            <b:value i:type=\"c:string\" xmlns:c=\"http://www.w3.org/2001/XMLSchema\">" + ActivityDescription + "</b:value>";
        requestXML += "          </a:KeyValuePairOfstringanyType>";
        requestXML += "        </a:Parameters>";
        requestXML += "        <a:RequestId i:nil=\"true\" />";
        requestXML += "        <a:RequestName>" + "new_My_Record_Open_Action" + "</a:RequestName>";
        requestXML += "      </request>";
        requestXML += "    </Execute>";
        requestXML += "  </s:Body>";
        requestXML += "</s:Envelope>";

        var req = new XMLHttpRequest();
        req.open("POST", fnGetClientUrl(), false);
        req.setRequestHeader("Accept", "application/xml, text/xml, */*");
        req.setRequestHeader("Content-Type", "text/xml; charset=utf-8");
        req.setRequestHeader("SOAPAction", "http://schemas.microsoft.com/xrm/2011/Contracts/Services/IOrganizationService/Execute");

        req.send(requestXML);
        //Get the Resonse from the CRM Execute method
        var response = req.responseXML.xml;
        if (req.status === 200) {
            fnRetriiveAfterSuccess();
        } else {
            alert("Problem in plugin call");
        }
    }
    catch (err) {
        alert(err);
    }
  
}

//fn Retriive After Success
function fnRetriiveAfterSuccess() {
    alert("Plugin called successfully");
}

//fn Get Client Url
function fnGetClientUrl() {
    return Xrm.Page.context.getClientUrl() + "/XRMServices/2011/Organization.svc/web"
}



Now Save it and Publish it.
After that we need to add this on Form. So I am adding on Contact Form.
Setting => Customization=> Customize the System => Entities => Contacts => Forms => Select Information Form (a default main form).
In Form Properties add this Web Resource(As shown in below Screenshot).







Now Save the Form and Publish it.
Now go to Contact and open any Contact. Hope Plugin will trigger.
Now I am going to check in activity.



Plugin triggered successfully.
Hope this Article will helpful for you.


Web Resource vs PCF vs Canvas App - which of the one is used?

While started working on specific Business Requirements related to custom layout, there is a always common question that "where to star...