Dynamic CRM Connection

Standard

A while ago I had to build a piece of software that connects to Dynamic CRM and retrieve values from an Entity to Export it to CSV file. Reading through existing code of other developers I noticed a lot of Impersonation taking place, or credentials being stored in the web.config/app.config file. I do not like this. I want my application to connect to CRM using my Active Directory credentials.

CRM is still a great big playpen to me where I feel and push the boundaries to see what it can do with it. Lacking experience with it allows me a lot of freedom to experiment.

After playing a bit and reading a lot on how to best avoid the whole credentials-in-the-config-file scenario, I came up with these classes.

This class build up an Organization Service Url for your favourite CRM Organization

using System;
using System.Configuration;

namespace MyApplication.CrmServices
{
    internal class OrganizationServiceUrl
    {
        const string XrmServiceLocation = @"/XRMServices/2011/Organization.svc";

        public OrganizationServiceUrl(string organizationUrl = null)
        {
            if (string.IsNullOrWhiteSpace(organizationUrl) && string.IsNullOrWhiteSpace(ConfigurationManager.AppSettings["CrmInstanceUrl"]))
                throw new InvalidOperationException("Organization URL is required.");

             organizationUrl = string.IsNullOrWhiteSpace(organizationUrl) ? ConfigurationManager.AppSettings["CrmInstanceUrl"] : organizationUrl ;
            if (string.IsNullOrWhiteSpace(organizationUrl))
                throw new InvalidOperationException(@"The [URL] setting was not found in the <appSettings> section of the configuration file.");

            Uri = new Uri(string.Format("{0}{1}",
                organizationUrl.EndsWith("/") ? organizationUrl.Substring(0, organizationUrl.LastIndexOf("/") - 1) : organizationUrl,
                XrmServiceLocation));
        }
        public Uri Uri { get; private set; }
    }
}

Next up I created a class that will give me ClientCredentials from the Default NeworkCredentials and accepts the OrganizationServiceUrl as a parameter.

using System.ServiceModel.Description;
using System.Net;

namespace MyApplication.CrmServices
{
    internal class CrmClientCredentials : ClientCredentials
    {
        private readonly OrganizationServiceUrl serviceUrl;
        public CrmClientCredentials(OrganizationServiceUrl serviceUrl)
            : base()
        {
            this.serviceUrl = serviceUrl;
            this.Windows.ClientCredential = CredentialCache.DefaultNetworkCredentials.GetCredential(serviceUrl.Uri, "Basic");
        }
    }
}

Finally, I can connect to the Organization service through the CRM SDK without having to store any credential in the config file.

using System;
using Microsoft.Xrm.Sdk;
using Microsoft.Xrm.Sdk.Client;

namespace MyApplication.CrmServices
{
    public class Connector : IDisposable
    {
        private OrganizationServiceUrl organizationServiceUrl;
        private CrmClientCredentials crmClientCredentials;
        public bool disposed;

        public Connector()
        {
            organizationServiceUrl = new OrganizationServiceUrl(string.Empty);
            crmClientCredentials = new CrmClientCredentials(organizationServiceUrl);
            disposed = false;
        }

        public Connector(string organizationUrl)
        {
            organizationServiceUrl = new OrganizationServiceUrl(organizationUrl);
            crmClientCredentials = new CrmClientCredentials(organizationServiceUrl);
            disposed = false;
        }

        public IOrganizationService Proxy
        {
            get { return new OrganizationServiceProxy(organizationServiceUrl.Uri, null, crmClientCredentials, null); }
        }

        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }

        protected virtual void Dispose(bool disposing)
        {
            if (!disposed)
            {
                if (disposing)
                {
                    if (organizationServiceUrl != null)
                        organizationServiceUrl = null;
                    if (crmClientCredentials != null)
                        crmClientCredentials = null;
                }
                disposed = true;
            }
        }
    }
}

Whether this is the correct, or even acceptable, way of connecting to CRM I do not know. What I do know, is that thus far, it works for me. It is simple and reusable.

Advertisements

Saving Window position

Standard

When I use an application and I move the window to a new location on my monitor, or even move it over to the second monitor I expect that it would start up where I left it last. Very few application, to my annoyance, does this.

To build this into you applications is such an easy thing to do.

Bind you Location property to in the property binding window.

In the properties toolbox of your solution set a name for Location property.

Property Binding Dialog

This property will be stored in your app.config file.

 <userSettings>
    <xxx.UI.Properties.Settings>
      <setting name="ExportFolder" serializeAs="String">
        <value>Choose a folder...</value>
      </setting>
      <setting name="StartupPosition" serializeAs="String">
        <value>0, 0</value>
      </setting>
    </xxx.UI.Properties.Settings>
  </userSettings>

Next add code to you Window’s ResizeEnd event. This event is called once you stop moving a window too.

        private void MainWindow_ResizeEnd(object sender, EventArgs e)
        {
            Properties.Settings.Default.StartupPosition = Location;
        }

Now, in the constructor add the following event subscription.

// Save settings
Properties.Settings.Default.PropertyChanged += (o, e) => Properties.Settings.Default.Save();

Next time your window start’s up it will be in the location the user left it, even on the second monitor if it was last left there.