Dynamics 365 – Connecting your app using MFA

MFA is becoming a common thing, as joyous as it is to use 🙂

I have a C# app that connects to Dynamics CRM/365 and I had to update it to support Microsoft Azure MFA.

I couldn’t really find any definitive guide out there, i had to cobble all different things together to get a working solution.

I hope this guide helps out some other poor sucker like me.

 

1. I had to update my application to use the modern CRM Tooling method of connection.

I added the following in Nuget to my solution – the key being the CrmTooling which supports the new connection string method of connecting.

In my code, i changed the way i obtained an IOrganizationService to the below (simplified):

string conn = "my connection string";

IOrganizationService _crmService;

CrmServiceClient service = new CrmServiceClient(conn);

_crmService = (IOrganizationService)service.OrganizationWebProxyClient != null ? (IOrganizationService)service.OrganizationWebProxyClient : (IOrganizationService)service.OrganizationServiceProxy;

 

This gets me a connection using the new Tooling DLL and a CRM Connection string.

 

Next step, you need to create an application in Azure AD.  I followed this guide.

The trick is the Redirect URI – i wasn’t working with a web app – I ended up using http://localhost

https://docs.microsoft.com/en-us/dynamics365/customer-engagement/developer/walkthrough-register-dynamics-365-app-azure-active-directory

 

Finally, constructing a connection string that would work with the new registered Azure App.

AuthType=OAuth;Url=https://yourcrm.crm.dynamics.com;AppId=yournewappid;RedirectUri=http://localhost;

 

Now when you go to connect, the Microsoft Sign In assistant pops up and handles the authentication to the CRM Instance.

And, if you have MFA turned on, you are also prompted with MFA.

 

Happy Days!

 

Google Places API in C# .NET

I recently had a requirement to look in to using the Google Places API in some code i was writing.

I found this library here that made the whole thing a lot easier.

https://github.com/azizmb9494/Google-Places 

 

I ended up writing a quick C# application to test the different searches by lon/lat and by text.

Download Places –  a quick and dirty C# application that implements the API.. you’ll need to get a Google API Key to run it.

https://developers.google.com/places/web-service/get-api-key

 

Paste your key in to the app and then you can search by lon/lat, text or a combination of both

The basic guts of the code is below.  Having never had anything to do with Google API’s before, it was pretty simple to get some programmatic searching going on…

Example method using the API above:

 private async void TestGooglePlaces()
        {
            Response results;
            var placeList = new List<Place>();
            string apiKey = "your api key";

            if ((string.IsNullOrEmpty(txtLat.Text) || string.IsNullOrEmpty(txtLon.Text))) //if we dont have a lon/lat .. search txt
            {
                results = await Places.Api.TextSearch(txtQuery.Text, apiKey);
            }
            else
            {
                results = await Places.Api.SearchPlaces(Convert.ToDouble(txtLat.Text), Convert.ToDouble(txtLon.Text), txtQuery.Text, apiKey);
            }

            //add the results to placeList
            foreach (var place in results.Places)
            {
                placeList.Add(place);
            }

            //if there are more than one 'page' of results...
            while (results.Next != null)
            {
                //get the next lot of results
                results = await Places.Api.GetNext(results.Next, apiKey);

                foreach (var place in results.Places)
                {
                    placeList.Add(place);
                }
            }

            foreach (var place in placeList)
            {
                var placeDetails = await Places.Api.GetDetails(place.PlaceId, apiKey);

                //do stuff with your place and placeDetails                
                string name = place.Name;
                string address = placeDetails.Address;
                //......
            }

        }