When creating an IServiceManagement for Dynamics 365, why does the authentication endpoint respond with an HTML sign in page? - dynamics-crm

I have some integration code that intends to use the Organization Service via the CRM SDK.
On one environment, creating an IServiceManagement<IOrganizationService>:
IServiceManagement<IOrganizationService> orgServiceManagement = ServiceConfigurationFactory.CreateManagement<IOrganizationService>(new Uri("dynamics uri")));
and then authenticating with service account credentials:
AuthenticationCredentials authCredentials = new AuthenticationCredentials();
authCredentials.ClientCredentials.UserName.UserName = _config.GetValue<string>("Dynamics:Username");
authCredentials.ClientCredentials.UserName.Password = _config.GetValue<string>("Dynamics:Password");
AuthenticationCredentials tokenCredentials = orgServiceManagement.Authenticate(authCredentials);
works fine.
On another Dynamics environment, the call to GetServiceManagement fails with the following error message:
System.InvalidOperationException
HResult=0x80131509
Message=Metadata contains a reference that cannot be resolved: 'https://login.microsoftonline.com/[guid]/oauth2/authorize?client_id=[some client id]&response_mode=form_post&response_type=code+id_token&scope=openid+profile&state=OpenIdConnect.AuthenticationProperties%[some base-64]RedirectTo%3dhttps%253a%252f%252ftst-success.crm4.dynamics.com%252f&nonce=[some nonce]&redirect_uri=https:%2f%2fcloudredirector.crm4.dynamics.com%2fG%2fAuthRedirect%2fIndex.aspx&max_age=86400'.
Source=System.ServiceModel
StackTrace:
at System.ServiceModel.Description.MetadataExchangeClient.MetadataRetriever.Retrieve(TimeoutHelper timeoutHelper)
at System.ServiceModel.Description.MetadataExchangeClient.ResolveNext(ResolveCallState resolveCallState)
at System.ServiceModel.Description.MetadataExchangeClient.GetMetadata(MetadataRetriever retriever)
at System.ServiceModel.Description.MetadataExchangeClient.GetMetadata(Uri address, MetadataExchangeClientMode mode)
at Microsoft.Xrm.Sdk.Client.ServiceMetadataUtility.RetrieveServiceEndpointMetadata(Type contractType, Uri serviceUri, Boolean checkForSecondary)
at Microsoft.Xrm.Sdk.Client.ServiceConfiguration`1..ctor(Uri serviceUri, Boolean checkForSecondary)
at Microsoft.Xrm.Sdk.Client.ServiceConfigurationFactory.CreateConfiguration[TService](Uri serviceUri, Boolean enableProxyTypes, Assembly assembly)
at Microsoft.Xrm.Sdk.Client.ServiceConfigurationFactory.CreateConfiguration[TService](Uri serviceUri)
at CrmAuthTest.Program.Main(String[] args) in c:\users\t.wolverson\Source\Repos\CrmAuthTest\CrmAuthTest\Program.cs:line 18
Inner Exception 1:
XmlException: CData elements not valid at top level of an XML document. Line 1, position 3.
(I have masked the bits which look identifying or cryptographic)
POSTing to this URL in PostMan yields the HTML for a browser login page, which explains the failure; this isn't what the ServiceConfigurationFactory expects. The scenario is not user-interactive, so this would never make sense, there is no browser and no user able to interact with it.
What do I have to change in Dynamics CRM Online to stop it doing this, and make it just work normally?

Do you instantiate your OrganizationServiceProxy depending on the AuthenticationProviderType right after the lines of code you have posted? Like this
var orgServiceManagement = ServiceConfigurationFactory.CreateManagement<IOrganizationService>(new Uri(ConfigurationManager.AppSettings["CrmUrlService"]));
var authCredentials = new AuthenticationCredentials();
authCredentials.ClientCredentials.UserName.UserName = ConfigurationManager.AppSettings["CrmUserName"];
authCredentials.ClientCredentials.UserName.Password = ConfigurationManager.AppSettings["CrmPassword"];
var tokenCredentials = orgServiceManagement.Authenticate(authCredentials);
IOrganizationService _service;
switch (orgServiceManagement.AuthenticationType)
{
case AuthenticationProviderType.ActiveDirectory:
_service = new OrganizationServiceProxy(orgServiceManagement, tokenCredentials.ClientCredentials);
break;
default:
_service = new OrganizationServiceProxy(orgServiceManagement, tokenCredentials.SecurityTokenResponse);
break;
}
Even if this solves your problem, I recommend that you use CrmServiceClient instead. This class can be found in Microsoft.Xrm.Tooling.Connector dll. It is the go to authentication class when building Windows client applications that connect to Microsoft Dynamics 365. More information on this can be found here
Here is an example on how to initialize CrmServiceClient when connecting to Dynamics 365 online using Office 365:
var myConnectionString = "Url=https://[YourOrganization].crm4.dynamics.com;Username=[YourUser];Password=[YourPassword];AuthType=Office365;";
var crmClient = new CrmServiceClient(myConnectionString);
//Do your stuff
var response = crmClient.Execute(new WhoAmIRequest());
If you need other authentication methods in Dynamics Online check how to build your connection string here.
For on-premises check how to build your connection string here.

Related

Microsoft.Office.Interop.Outlook does not work on web server but works on local machine

I am using below code in the button event, so that user can send mail through self machine outlook directly (nuget Microsoft. Office. Interop.Outlook). Code is working when I am debugging below code in my localhost and send mail from outlook. But problem is when I deployed the code into web server and browse through IE from my work station, mail not send through outlook.
This error message show in log:
Retrieving the COM class factory for component with CLSID {0006F03A-0000-0000-C000-000000000046} failed due to the following error: 80070005 Access is denied. (Exception from HRESULT: 0x80070005 (E_ACCESSDENIED)).
How can I resolve this issue?
Web application reside into web server and users will access the application from IE and then they will send mail through self machine outlook.
public void SendEmailOutlook(string mailToRecipients, string mailCCRecipients, string subjectLine, [Optional] string attachments, string HTMLBody)
{
try
{
Microsoft.Office.Interop.Outlook.Application oApp = new Microsoft.Office.Interop.Outlook.Application();
Microsoft.Office.Interop.Outlook.MailItem oMsg = oApp.CreateItem(Microsoft.Office.Interop.Outlook.OlItemType.olMailItem);
Outlook.Recipients oRecips = oMsg.Recipients;
List<string> oTORecip = new List<string>();
List<string> oCCRecip = new List<string>();
var ToRecip = mailToRecipients.Split(',');
var CCRecip = mailCCRecipients.Split(',');
foreach (string ToRecipient in ToRecip)
{
oTORecip.Add(ToRecipient);
}
foreach (string CCRecipient in CCRecip)
{
oCCRecip.Add(CCRecipient);
}
foreach (string to in oTORecip)
{
Outlook.Recipient oTORecipt = oRecips.Add(to);
oTORecipt.Type = (int)Outlook.OlMailRecipientType.olTo;
oTORecipt.Resolve();
}
foreach (string cc in oCCRecip)
{
Outlook.Recipient oCCRecipt = oRecips.Add(cc);
oCCRecipt.Type = (int)Outlook.OlMailRecipientType.olCC;
oCCRecipt.Resolve();
}
oMsg.Subject = subjectLine;
if (attachments.Length > 0)
{
string sDisplayName = "MyAttachment";
int iPosition = 1;
int iAttachType = (int)Outlook.OlAttachmentType.olByValue;
var Sendattachments = attachments.Split(',');
foreach (var attachment in Sendattachments)
{
Outlook.Attachment oAttach = oMsg.Attachments.Add(attachment, iAttachType, iPosition, sDisplayName);
}
}
if (HTMLBody.Length > 0)
{
oMsg.HTMLBody = HTMLBody;
}
oMsg.Save();
oMsg.Send();
oTORecip = null;
oCCRecip = null;
oMsg = null;
oApp = null;
}
catch (Exception e)
{
//print(e.Message);
}
}
Outlook, just like every other Office app, cannot be used from a service (such as IIS).
The Considerations for server-side Automation of Office article states the following:
Microsoft does not currently recommend, and does not support, Automation of Microsoft Office applications from any unattended, non-interactive client application or component (including ASP, ASP.NET, DCOM, and NT Services), because Office may exhibit unstable behavior and/or deadlock when Office is run in this environment.
If you are building a solution that runs in a server-side context, you should try to use components that have been made safe for unattended execution. Or, you should try to find alternatives that allow at least part of the code to run client-side. If you use an Office application from a server-side solution, the application will lack many of the necessary capabilities to run successfully. Additionally, you will be taking risks with the stability of your overall solution.
As a possible workaround you may consider using EWS or any other REST API (for example, Graph API) if you deal with Exchange server profiles only. See Explore the EWS Managed API, EWS, and web services in Exchange for more information.
I've had this issue too."Retrieving the COM class factory for component with CLSID {0006F03A-0000-0000-C000-000000000046} failed due to the following error: 80070005 Access is denied. (Exception from HRESULT: 0x80070005 (E_ACCESSDENIED))."
Server environment:Windows server 2019&iis
Local machine:Windows 10&iis
Tip:The Microsoft office doesn't support that use OutWork IIS or Asp.net
So,I give you right answer(It's worked):
1、Run "win+R" ,then inuput 'Dcomcnfg'
2、As this pic:
enter image description here

ChatBot did not work in Web Emulator but work well in Local Bot Framework emulator

I developed the ChatBot that integrates with SharePoint On Premise. When I debug the ChatBot in emulator, it work. But When I debug on Web Emulator in Azure and Website Hosted in Company Website by using DirectLine, it did not work.
Does anyone know how to solve it?
Herewith my screenshot.
Left hand side is from Web Emulator, Right hand side is from local Bot Framework Emulator
Update with Source Code (09 December 2019)
XmlNamespaceManager xmlnspm = new XmlNamespaceManager(new NameTable());
Uri sharepointUrl = new Uri("https://mvponduty.sharepoint.com/sites/sg/daw/");
xmlnspm.AddNamespace("atom", "http://www.w3.org/2005/Atom");
xmlnspm.AddNamespace("d", "http://schemas.microsoft.com/ado/2007/08/dataservices");
xmlnspm.AddNamespace("m", "http://schemas.microsoft.com/ado/2007/08/dataservices/metadata");
NetworkCredential cred = new System.Net.NetworkCredential("engsooncheah#mvponduty.onmicrosoft.com", "Pa$$w0rd", "mvponduty.onmicrosoft.com");
HttpWebRequest listRequest = (HttpWebRequest)HttpWebRequest.Create(sharepointUrl.ToString() + "_api/lists/getByTitle('" + "data#work" + "')/items?$filter=Keywords%20eq%20%27bloomberg%27");
listRequest.Method = "GET";
listRequest.Accept = "application/atom+xml";
listRequest.ContentType = "application/atom+xml;type=entry";
listRequest.Credentials = cred;
//LINE 136 start from below
HttpWebResponse listResponse = (HttpWebResponse)listRequest.GetResponse();
StreamReader listReader = new StreamReader(listResponse.GetResponseStream());
XmlDocument listXml = new XmlDocument();
listXml.LoadXml(listReader.ReadToEnd());
if (listResponse.StatusCode == HttpStatusCode.OK)
{
Console.WriteLine("Connected");
await turnContext.SendActivityAsync("Connected");
}
// Get and display all the document titles.
XmlElement root = listXml.DocumentElement;
XmlNodeList elemList = root.GetElementsByTagName("content");
XmlNodeList elemList_title = root.GetElementsByTagName("d:Title");
XmlNodeList elemList_desc = root.GetElementsByTagName("d:Description");
//for LINK
XmlNodeList elemList_Id = root.GetElementsByTagName("d:Id");
XmlNodeList elemList_Source = root.GetElementsByTagName("d:Sources");
XmlNodeList elemList_ContentTypeId = root.GetElementsByTagName("d:ContentTypeId");
var attachments = new List<Attachment>();
for (int i = 0; i < elemList.Count; i++)
{
string title = elemList_title[i].InnerText;
string desc = elemList_desc[i].InnerText;
string baseurllink = "https://mvponduty.sharepoint.com/sites/sg/daw/Lists/data/DispForm.aspx?ID=";
string LINK = baseurllink + elemList_Id[i].InnerText + "&Source=" + elemList_Source[i].InnerText + "&ContentTypeId=" + elemList_ContentTypeId[i].InnerText;
//// Hero Card
var heroCard = new HeroCard(
title: title.ToString(),
text: desc.ToString(),
buttons: new CardAction[]
{
new CardAction(ActionTypes.OpenUrl,"LINK",value:LINK)
}
).ToAttachment();
attachments.Add(heroCard);
}
var reply = MessageFactory.Carousel(attachments);
await turnContext.SendActivityAsync(reply);
Update 17 December 2019
I had try using Embedded and Direct Line. But the Error still same.
The Bot is not hosted in SharePoint.
Update 06 January 2020
Its did not work in Azure Bot Services
Based on your description, you can fetch data from it locally. This means your code and logic are all right.
I noticed that your sharePoint URL is : https://mvponduty.sharepoint.com/sites/sg/daw/ and I tried to access it, and also tried to access your whole request URL : https://mvponduty.sharepoint.com/sites/sg/daw/_api/lists/getByTitle('data#work')/items?$filter=Keywords eq 'bloomberg' the response of the two are all 404.
And you said this is an on-prem site , so could you pls have a check that if this site can be reached from a public network?
I assume when you test your code locally, you can access this site as you are in your internal network which will be able to access the on-prem site. However, when you publish your code to Azure, it is not in your internal work anymore: it is in public network so that can't access your on-prem sharePoint site which caused this error.
As we know, bot code is hosted on Azure app service, if this error is caused by the above reason, maybe Azure App Service Hybrid Connections feature will be helpful in this scenario.
ChatBot seems to be working fine? it's sending and receiving messages. There's some code you have that is behaving differently when run locally versus hosted. There's Xml, is it a file or generated? You need check that it's following the same logic and using same data as when it is run locally. Maybe if you paste some of the (non confidential) code where it crashes, we can have more ideas how to help
When you publish your bot, there will be an option as below :
Select Edit App Service Settings. Add only the following details, nothing else :
MicrosoftAppId : <xxxxx>
MicrosoftAppPassword : <xxxxx>
Click Apply, Ok.
Make sure you remove the Microsoft App Id and Microsoft App Password from appsettings.json, so that it works in bot emulator as well.
Now Publish the bot. It will work at both places.
Hope this is helpful.

CrmServiceClient is always returning null Organization Service

I've got the following code to connect to Dynamics 365 Online organization. It throws a null reference exception on orgService.Execute(new WhoAmIRequest()); and error log is below the code. I've tried this on two machines with different console apps. I've tried both the 8.2 and 8.0 SDK DLLs. If I rewrite this using CrmConnection with the 7.x SDK DLLs everything works fine. I can browse to the organization using the same credentials (cut & pasted to be sure there is not a typo.)
The connection string format is taken from the example at https://msdn.microsoft.com/en-us/library/mt608573.aspx:
Named account using Office 365
<add name="MyCRMServer"
-connectionString="AuthType=Office365;Username=jsmith#contoso.onmicrosoft.com;
Password=passcode;Url=https://contoso.crm.dynamics.com"/>
The basic code.
var connectionString = #"Url=https://ORGNAME.crm.dynamics.com; Username=username#ORGNAME.onmicrosoft.com; Password=43JF##$j##Ha; Authype=Office365;";
var client = new CrmServiceClient(connectionString);
var orgService = (IOrganizationService)client.OrganizationWebProxyClient ?? client.OrganizationServiceProxy;
orgService.Execute(new WhoAmIRequest());
Error log output:
Microsoft.Xrm.Tooling.Connector.CrmServiceClient Information: 8 : Discovery URI is = https://ORGNAME.crm.dynamics.com:443/XRMServices/2011/Discovery.svc
Microsoft.Xrm.Tooling.Connector.CrmServiceClient Information: 8 : DiscoverOrganizations - Initializing Discovery Server Object with https://ORGNAME.crm.dynamics.com/XRMServices/2011/Discovery.svc
Microsoft.Xrm.Tooling.Connector.CrmServiceClient Verbose: 16 : DiscoverOrganizations - attempting to connect to CRM server # https://ORGNAME.crm.dynamics.com/XRMServices/2011/Discovery.svc
Microsoft.Xrm.Tooling.Connector.CrmServiceClient Error: 2 : Source : System.ServiceModel
Method : Retrieve
Date : 2/13/2017
Time : 5:42:37 PM
Error : Metadata contains a reference that cannot be resolved: 'https://ORGNAME.crm.dynamics.com/_common/error/errorhandler.aspx?BackUri=&ErrorCode=&Parm0=%0d%0a%0d%0aتفاصيل الخطأ: The service '%2fXRMServices%2f2011%2fDiscovery.svc' cannot be activated due to an exception during compilation. The exception message is: Could not load file or assembly 'Microsoft.Crm.Site.Services%2c Version%3d8.0.0.0%2c Culture%3dneutral%2c PublicKeyToken%3d31bf3856ad364e35' or one of its dependencies. The system cannot find the file specified..&RequestUri=%2fXRMServices%2f2011%2fDiscovery.svc%3fwsdl%26sdkversion%3d8.1&user_lcid=1025'.
Stack Trace : at System.ServiceModel.Description.MetadataExchangeClient.MetadataRetriever.Retrieve(TimeoutHelper timeoutHelper)
at System.ServiceModel.Description.MetadataExchangeClient.ResolveNext(ResolveCallState resolveCallState)
at System.ServiceModel.Description.MetadataExchangeClient.GetMetadata(MetadataRetriever retriever)
at System.ServiceModel.Description.MetadataExchangeClient.GetMetadata(Uri address, MetadataExchangeClientMode mode)
at Microsoft.Xrm.Sdk.Client.ServiceMetadataUtility.RetrieveServiceEndpointMetadata(Type contractType, Uri serviceUri, Boolean checkForSecondary)
at Microsoft.Xrm.Sdk.Client.ServiceConfiguration`1..ctor(Uri serviceUri, Boolean checkForSecondary)
at Microsoft.Xrm.Sdk.Client.ServiceConfigurationFactory.CreateManagement[TService](Uri serviceUri, Boolean enableProxyTypes, Assembly assembly)
at Microsoft.Xrm.Sdk.Client.ServiceConfigurationFactory.CreateManagement[TService](Uri serviceUri)
at Microsoft.Xrm.Tooling.Connector.CrmWebSvc.CreateAndAuthenticateProxy[T](IServiceManagement`1 servicecfg, Uri ServiceUri, Uri homeRealm, ClientCredentials userCredentials, ClientCredentials deviceCredentials, String LogString)
at Microsoft.Xrm.Tooling.Connector.CrmWebSvc.DiscoverOrganizations(Uri discoveryServiceUri, Uri homeRealmUri, ClientCredentials clientCredentials, ClientCredentials deviceCredentials)
at Microsoft.Xrm.Tooling.Connector.CrmWebSvc.DiscoverOrganizations(Uri discoveryServiceUri, Uri homeRealmUri, NetworkCredential networkCredential)
at Microsoft.Xrm.Tooling.Connector.CrmWebSvc.InitCRM2011Service()
======================================================================================================================
Inner Exception Level 1 :
Source : System.Runtime.Serialization
Method : ThrowXmlException
Date : 2/13/2017
Time : 5:42:37 PM
Error : CData elements not valid at top level of an XML document. Line 1, position 3.
Stack Trace : at System.Xml.XmlExceptionHelper.ThrowXmlException(XmlDictionaryReader reader, XmlException exception)
at System.Xml.XmlUTF8TextReader.Read()
at System.ServiceModel.Description.MetadataExchangeClient.MetadataLocationRetriever.GetXmlReader(HttpWebResponse response, Int64 maxMessageSize, XmlDictionaryReaderQuotas readerQuotas)
at System.ServiceModel.Description.MetadataExchangeClient.MetadataLocationRetriever.DownloadMetadata(TimeoutHelper timeoutHelper)
at System.ServiceModel.Description.MetadataExchangeClient.MetadataRetriever.Retrieve(TimeoutHelper timeoutHelper)
======================================================================================================================
Microsoft.Xrm.Tooling.Connector.CrmServiceClient Error: 2 : Unable to Login to Dynamics CRM
Microsoft.Xrm.Tooling.Connector.CrmServiceClient Error: 2 : OrganizationWebProxyClient is null
Microsoft.Xrm.Tooling.Connector.CrmServiceClient Error: 2 : OrganizationServiceProxy is null
As per latest Microsoft recommendation we are not supposed to use “AuthType=Office365”.
https://learn.microsoft.com/en-us/powerapps/developer/common-data-service/authenticate-office365-deprecation
We can use Application Account (Client ID & Secret Key) to generate Token & access Dynamics CRM Organization Service. But if you want to use User ID & PWD then Use (AuthType = OAuth)
Sample Code :
string connectionString = "AuthType = OAuth; Url = 'https://*****.crm.dynamics.com'; Username = '*******'; Password = '*******'; AppId = 51f81489-12ee-4a9e-aaae-a2591f45987d; RedirectUri = app://58145B91-0C36-4500-8554-080854F2AC97;LoginPrompt=Never";
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
CrmServiceClient crmServiceClient = new CrmServiceClient(connectionString);
WhoAmIResponse whoAmIResponse = crmServiceClient.Execute(new WhoAmIRequest()) as WhoAmIResponse;
Note : While trying to use this from Azure Function I got below errors :
ERROR REQUESTING Token FROM THE Authentication contextNeed a non-empty authority
One or more errors occurred. => An error occurred while sending the request. => The underlying connection was closed: An unexpected error occurred on a send. => Unable to read data from the transport connection: An existing connection was forcibly closed by the remote host. => An existing connection was forcibly closed by the remote hostERROR REQUESTING Token FROM THE Authentication context
CurrentAccessToken = 'crmServiceClient.CurrentAccessToken' threw an exception of type 'System.NullReferenceException'
Easily you can resolve these using just one additional line : ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
Ref URL : https://support.microsoft.com/en-us/help/4051700
Microsoft Dynamics 365 Customer Engagement (online) to require TLS 1.2 for connectivity
Pls let me know if you are facing any other issues.
Thanks,
Sumit
Have you tried passing the parameters directly to the CrmServiceClient instead of the connection string?
I can connect successfully to Dynamics365 by using this following method
public CrmServiceClient(string crmUserId, SecureString crmPassword, string crmRegion, string orgName, bool useUniqueInstance = false, bool useSsl = false, OrganizationDetail orgDetail = null, bool isOffice365 = false);
And here's how I applied
var pwd = ConvertToSecureString("userpassword");
CrmServiceClient client = new CrmServiceClient("user#mail.com", pwd, "NorthAmerica", "orgname", isOffice365: true);
And here's the method to convert the password to secure string
private System.Security.SecureString ConvertToSecureString(string password)
{
if (password == null)
throw new ArgumentNullException("missing pwd");
var securePassword = new System.Security.SecureString();
foreach (char c in password)
securePassword.AppendChar(c);
securePassword.MakeReadOnly();
return securePassword;
}
I was getting error
Unable to login to Dynamics CRM, Error was :
Data[0] = "The provided uri did not return any Service Endpoints!
I received this error when attempting to connect to Dynamics using a connection string with AuthType=ClientSecret. Previously I was connecting successfully using username and password with a connection string of the form
"Url={dynamicsConnectionString};Username={username};Password={password};AuthType=Office365;"
The connection string was changed to have the form
"AuthType=ClientSecret;RequireNewInstance=false;Url={CrmDynamicsPrivatePrimaryConnection};ClientId={CrmDynamicsPrivateClientId};ClientSecret={CrmDynamicsPrivateClientSecret};LoginPrompt=Never;"
The error occurred because I was using an outdated version of Microsoft.CrmSdk.XrmTooling.CoreAssembly. I was using version 9.0.2.27, and according to a web report, version 9.1.0.13 is needed for connecting with ClientSecret. I updated to version 9.1.0.68 using NuGet, and the Dynamics connection worked.
I was struggling on fixing this issue because everything I did except installing higher version (On MS docs also They didn't mentioned this) of Microsoft.CrmSdk.XrmTooling.CoreAssembly since lower version of this dll doesn't support ClientSecret authentiation.

How to authenticate against Sharepoint Online with user credentials?

I am trying to customize some lists for SharePoint Online and since I am new to the subject I do not know how to connect to the service.
When I use NAPA and from the cloud use the option "Edit in Visual Studio", I am prompted for credentials automatically when the project opens.
However, when I start from bottom-up, i.e. open a new project in Visual Studio, add all necessary dlls, this part of code throws an error (it is an authentication issue):
ClientContext context = new ClientContext("https://MYURL.sharepoint.com/n/");
context.ExecuteQuery();
I am using Microsoft.SharePoint.Client;
The error message:
An unhandled exception of type 'System.Net.WebException' occurred in Microsoft.SharePoint.Client.dll
Additional information: The remote server returned an error: (403) Forbidden.
I think I am missing part of the code which is responsible for authentication and which in case of NAPA app is hard-coded.
How can I authenticate to SharePoint Online? (it is enough if my code runs just once, it's not an app, I don't want to package it and publish)
I am guessing it has something to do with http://msdn.microsoft.com/en-us/library/microsoft.visualstudio.sharepoint.remote.authentication.aspx, but that's as far as I got.
How to authenticate against SharePoint Online using the managed CSOM
The CSOM for SharePoint 2013 introduces the SharePointOnlineCredentials class that allows to perform an active authentication to SharePoint Online.
Example
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Enter the URL of the SharePoint Online site:");
string webUrl = Console.ReadLine();
Console.WriteLine("Enter your user name (format: username#tenant.onmicrosoft.com)");
string userName = Console.ReadLine();
Console.WriteLine("Enter your password.");
SecureString password = GetPasswordFromConsoleInput();
using (var context = new ClientContext(webUrl))
{
context.Credentials = new SharePointOnlineCredentials(userName,password);
context.Load(context.Web, w => w.Title);
context.ExecuteQuery();
Console.WriteLine("Your site title is: " + context.Web.Title);
}
}
private static SecureString GetPasswordFromConsoleInput()
{
ConsoleKeyInfo info;
//Get the user's password as a SecureString
SecureString securePassword = new SecureString();
do
{
info = Console.ReadKey(true);
if (info.Key != ConsoleKey.Enter)
{
securePassword.AppendChar(info.KeyChar);
}
}
while (info.Key != ConsoleKey.Enter);
return securePassword;
}
}

Can I use the Dynamics CRM 4.0 SDK against a hosted IFD system?

I am running this code (with names and security details obscured). When I do, I get 401 unauthorised. The credentials are that of the user on the hosted server. Is this possible against an IFD system?
var token = new CrmAuthenticationToken();
token.AuthenticationType = 0;
token.OrganizationName = "myorganisation";
CrmService service = new CrmService();
service.Url = "https://myorganisation.dynamicsgateway.com/mscrmservices/2007/crmservice.asmx";
service.CrmAuthenticationTokenValue = token;
service.Credentials = new NetworkCredential("bob.smith", "Password", "HOSTEDCRM");
var request = new RetrieveMultipleRequest();
request.Query = new QueryExpression
{
ColumnSet = new ColumnSet(new string[] { "name" }),
EntityName = "account"
};
var response = service.Execute(request);
I assume this code is outside of the CRM Website? In that case you'll want to add a reference to the discovery service as Mercure points out above. You'll want to execute a RetrieveCrmTicketRequest against the discovery service to get a ticket good for connecting to the Crm Services.
In your CRM Authentication Token you'll want to set the authentication type to 2 (IFD). Then set the CrmTicket property on the token to the ticket you got from your RetrieveCrmTicketResponse.
I also set the URL based on that response, but you could continue to hard code it.
You will want to continue to set the Credentials on the service.
I use a single user to connect to CRM and cache that ticket (an expiration date is in the response from the discovery service). That way I can bypass the discovery service on future requests. There is an error code to look for to go after the ticket again, but I don't have it off hand.
Yes, it's possible, you are only missing a little pieces, the CrmAuthenticationToken.ExtractCrmAuthenticationToken.
Check out this great explaination on Dynamics Forum http://social.microsoft.com/Forums/en-US/crmdevelopment/thread/81f8ba82-981d-40dd-893d-3add67436478

Resources