/// <summary>
        /// Pass Extended OrganizationService to context
        /// </summary>
        /// <param name="cxInfo">IConnectionInfo</param>
        /// <returns>Constructor argument(s)</returns>
        public override object[] GetContextConstructorArguments(IConnectionInfo cxInfo)
        {
            // Instantiate CrmProperties.
            CrmProperties props = new CrmProperties(cxInfo);

            return(new object[]
            {
                new Uri(props.OrgUri + "/api/data/v" + props.Version + "/")
            });
        }
Example #2
0
        /// <summary>
        /// Pass Extended OrganizationService to context
        /// </summary>
        /// <param name="cxInfo">IConnectionInfo</param>
        /// <returns>Constructor argument(s)</returns>
        public override object[] GetContextConstructorArguments(IConnectionInfo cxInfo)
        {
            // Instantiate CrmProperties.
            CrmProperties props = new CrmProperties(cxInfo);
            // Create CrmConnection depending on connection type.
            CrmServiceClient crmConn = null;

            switch (props.AuthenticationProviderType)
            {
            case AuthenticationProviderType.OnlineFederation:
                crmConn = new CrmServiceClient(
                    $"AuthType=Office365; Username={props.UserName}; Password={props.Password}; Url={props.OrgUri}");
                break;

            case AuthenticationProviderType.ActiveDirectory:
                if (String.IsNullOrEmpty(props.DomainName))
                {
                    crmConn = new CrmServiceClient($"Url={props.OrgUri};");
                }
                else
                {
                    crmConn = new CrmServiceClient(
                        $"Url={props.OrgUri}; Domain={props.DomainName}; Username={props.UserName}; Password={props.Password};");
                }
                break;

            case AuthenticationProviderType.Federation:
                crmConn = new CrmServiceClient(
                    $"AuthType=IFD; Url={props.OrgUri}{props.ConnectedOrgUniqueName}; Domain={props.DomainName}; Username={props.UserName}; Password={props.Password};");
                break;
            }
            if (crmConn != null && crmConn.IsReady)
            {
                orgService = new OrganizationServiceEx(crmConn);
            }

            return(new object[]
            {
                orgService
            });
        }
        /// <summary>
        /// Additional work for Initialization. Hook PreExecute event to display QueryExpression and FetchXML to SQL tab.
        /// </summary>
        /// <param name="cxInfo">IConnectionInfo</param>
        /// <param name="context">Context generated via CSDL</param>
        /// <param name="executionManager">QueryExecutionManager</param>
        public override void InitializeContext(IConnectionInfo cxInfo, object context, QueryExecutionManager executionManager)
        {
            CrmProperties props = new CrmProperties(cxInfo);

            // Set AccessToken when calling REST Endpoint.
            (context as Microsoft.OData.Client.DataServiceContext).SendingRequest2 += (s, e) =>
            {
                switch (props.AuthenticationProviderType)
                {
                // If this is for CRM Online, then use OAuth 2.0
                case "OnlineFederation":
                case "Federation":
                    AuthenticationContext authContext = new AuthenticationContext(props.Authority, false);
                    string accessToken;
                    try
                    {
                        // Try to get token without prompt fist.
                        accessToken = authContext.AcquireTokenSilent(props.OrgUri, props.ClientId).AccessToken;
                    }
                    catch
                    {
                        // If AcquireTokenSilent fails, then use another way
                        if (props.AuthenticationProviderType == "OnlineFederation")
                        {
                            try
                            {
                                // Try to use embed credential
                                accessToken = authContext.AcquireToken(props.OrgUri, props.ClientId, new UserCredential(props.UserName, props.Password)).AccessToken;
                            }
                            catch (Exception ex)
                            {
                                // If failed, need to try using consent.
                                accessToken = authContext.AcquireToken(props.OrgUri, props.ClientId, new Uri(props.RedirectUri), PromptBehavior.Always, new UserIdentifier(props.UserName, UserIdentifierType.RequiredDisplayableId)).AccessToken;
                            }
                        }
                        else
                        {
                            accessToken = authContext.AcquireToken(props.OrgUri, props.ClientId, new Uri(props.RedirectUri), PromptBehavior.Always).AccessToken;
                        }
                    }
                    e.RequestMessage.SetHeader("Authorization", "Bearer " + accessToken);
                    break;

                // If this is ActiveDirectory, then use Windows Integrated Authentication.
                // Web API is only supported Online at the moment, so comment out the following for future use.
                case "ActiveDirectory":
                    if (String.IsNullOrEmpty(props.DomainName))
                    {
                        (e.RequestMessage as HttpWebRequestMessage).Credentials = CredentialCache.DefaultCredentials;
                    }
                    else
                    {
                        (e.RequestMessage as HttpWebRequestMessage).Credentials = new NetworkCredential(props.UserName, props.Password, props.DomainName);
                    }
                    break;
                }
                LINQPad.Util.ClearResults();
                executionManager.SqlTranslationWriter.WriteLine(e.RequestMessage.Url);
            };

            base.InitializeContext(cxInfo, context, executionManager);
        }
        // Display Name for connection.
        public override string GetConnectionDescription(IConnectionInfo cxInfo)
        {
            CrmProperties props = new CrmProperties(cxInfo);

            return(props.FriendlyName + "(Web API) " + props.OrgUri);
        }
        /// <summary>
        /// Generate Schema information.
        /// </summary>
        /// <param name="cxInfo">IConnectionInfo</param>
        /// <param name="customType">Context Type</param>
        /// <returns>Schema Information.</returns>
        public override List <ExplorerItem> GetSchema(IConnectionInfo cxInfo, Type customType)
        {
            // Instantiate CrmProperties.
            CrmProperties props = new CrmProperties(cxInfo);
            // Instantiate ExplorerItem list.
            List <ExplorerItem> schema = new List <ExplorerItem>();

            // Create Tables for Schema.
            foreach (PropertyInfo prop in customType.GetRuntimeProperties())
            {
                // If property is not Generic Type or IQueryable, then ignore.
                if (!prop.PropertyType.IsGenericType || prop.PropertyType.Name != "DataServiceQuery`1")
                {
                    continue;
                }

                // Create ExploreItem with Table icon as this is top level item.
                ExplorerItem item = new ExplorerItem(prop.Name, ExplorerItemKind.QueryableObject, ExplorerIcon.Table)
                {
                    // Store Entity Type to Tag.
                    Tag          = prop.PropertyType.GenericTypeArguments[0].Name,
                    IsEnumerable = true,
                    Children     = new List <ExplorerItem>()
                };

                schema.Add(item);
            }

            schema = schema.OrderBy(x => x.Text).ToList <ExplorerItem>();

            // Then create columns for each table. Loop through tables again.
            foreach (PropertyInfo prop in customType.GetRuntimeProperties())
            {
                // Obtain Table item from table lists.
                var item = schema.Where(x => x.Text == prop.Name).FirstOrDefault();

                if (item == null)
                {
                    continue;
                }

                // Get all property from Entity for the table. (i.e. Account for AccountSet)
                foreach (PropertyInfo childprop in customType.Module.GetTypes().Where(x => x.Name == prop.PropertyType.GenericTypeArguments[0].Name).First().GetRuntimeProperties())
                {
                    // If property is IEnumerable type, then it is 1:N or N:N relationship field.
                    // Need to find a way to figure out if this is 1:N or N:N. At the moment, I just make them as OneToMany type.
                    if (childprop.PropertyType.IsGenericType && childprop.PropertyType.Name == "IEnumerable`1")
                    {
                        // Try to get LinkTarget.
                        ExplorerItem linkTarget = schema.Where(x => x.Tag.ToString() == childprop.PropertyType.GetGenericArguments()[0].Name).FirstOrDefault();
                        if (linkTarget == null)
                        {
                            continue;
                        }

                        // Create ExplorerItem as Colleciton Link.
                        item.Children.Add(
                            new ExplorerItem(
                                childprop.Name,
                                ExplorerItemKind.CollectionLink,
                                ExplorerIcon.OneToMany)
                        {
                            HyperlinkTarget = linkTarget,
                            ToolTipText     = DataContextDriver.FormatTypeName(childprop.PropertyType, false)
                        });
                    }
                    else
                    {
                        // Try to get LinkTarget to check if this field is N:1.
                        ExplorerItem linkTarget = schema.Where(x => x.Tag.ToString() == childprop.PropertyType.Name).FirstOrDefault();

                        // If no linkTarget exists, then this is normal field.
                        if (linkTarget == null)
                        {
                            // Create ExplorerItem as Column.
                            item.Children.Add(
                                new ExplorerItem(
                                    childprop.Name + " (" + DataContextDriver.FormatTypeName(childprop.PropertyType, false) + ")",
                                    ExplorerItemKind.Property,
                                    ExplorerIcon.Column)
                            {
                                ToolTipText = DataContextDriver.FormatTypeName(childprop.PropertyType, false)
                            });
                        }
                        else
                        {
                            // Otherwise, create ExploreItem as N:1
                            item.Children.Add(
                                new ExplorerItem(
                                    childprop.Name + " (" + DataContextDriver.FormatTypeName(childprop.PropertyType, false) + ")",
                                    ExplorerItemKind.ReferenceLink,
                                    ExplorerIcon.ManyToOne)
                            {
                                HyperlinkTarget = linkTarget,
                                ToolTipText     = DataContextDriver.FormatTypeName(childprop.PropertyType, false)
                            });
                        }
                    }

                    // Order Fields
                    item.Children = item.Children.OrderBy(x => x.Text).ToList <ExplorerItem>();
                }
            }

            // Order Entities.
            schema = schema.OrderBy(x => x.Text).ToList <ExplorerItem>();

            return(schema);
        }