I am creating a workflow activity to download the annotation attachment from a custom entity. Running the workflow throws
System.NullReferenceException: Object reference not set to an instance of an object.
Here is my code:
private static string SaveFile(string fileName, string noteBody)
{
string outputFileName = #"C:\temp\" + fileName;
if (!string.IsNullOrEmpty(noteBody))
{
// Download the attachment in the current execution folder.
byte[] fileContent = Convert.FromBase64String(noteBody);
System.IO.File.WriteAllBytes(outputFileName, fileContent);
}
else
{
throw new InvalidPluginExecutionException("File content is empty or cannot be retrieved");
}
return outputFileName;
}
Debugging it shows that the error is thrown by:
System.IO.File.WriteAllBytes(outputFileName, fileContent);
From Visual Studio I get this exception
Request for permission of type System.Security.Permissions.FileIOPermission
CRM online plugins & workflows must be registered & run in sandbox isolation mode, which is secured & partially trusted in cloud (not Full trust).
Hence you cannot access C:\temp\ in Server from Plugin/workflow code. You will get FileIOPermission exception.
Developers have the option of registering their plug-ins in the sandbox, known as partial trust, or outside the sandbox, known as full trust. Full trust is supported for on-premises and Internet-facing Microsoft Dynamics 365 deployments. For a Microsoft Dynamics 365 (online) deployment, plug-ins or custom workflow activities must be registered in the sandbox (partial trust)
Access to the file system, system event log, certain network protocols, registry, and more is prevented in the sandbox.
Read more
Related
Getting error while creating Azure Batch Pool with private network configuration.
BatchClient bClient = BatchClient.Open(new BatchSharedKeyCredentials(batchUri, accountName, accountKey));
PoolSpecification poolSp = new PoolSpecification();
poolSp.NetworkConfiguration = new NetworkConfiguration
{
SubnetId = "/subscriptions/{0}/resourceGroups/{1}/providers/{2}/virtualNetworks/{3}/subnets/{4}"
};
Getting errors when creating job
await job.CommitAsync();
Exception: Microsoft.Azure.Batch.Protocol.Models.ErrorMessage - AuthenticationFailed
AuthenticationErrorDetail: The specified type of authentication SharedKey is not allowed when external resources of type Network are linked.
After research, I found that it is mandatory to use AAD authentication when using VNET. The reason is when using a shared key, the key doesn't have permission to access Network resources.
You can read the article mentioned in Authenticate Batch service solutions with Active Directory.
Has anything changed recently with the Google Drive APIs and specifically the Export function, which would cause it to fail while using API Key access after 27-Mar-2018?
I have a Windows Service that creates and sends daily course emails for an educational group. The source content for each email is stored in a Google Drive, as a Google Doc, so that the faculty can update the course content easily.
This has been working flawlessly for the past year, but suddenly stopped working about 27-Mar-2018. Since then, I can retrieve the file details;
_googleDriveHtmlContent.LoadFile(
fileId
);
But not the contents. When I Export the file as HTML, I immediately get a DownloadStatus.Failed from the ProgressChanged handler;
var request = _driveService.Files.Export(
fileId,
"text/html"
);
I'm using API keys for security, rather than OAuth, since it's a UI-less service. To do this I need to mark the file folders as publicly accessible - specifically I'm using "Accessible to everyone, with link." This has been working great.
I've updated to the latest API v3 libraries through NuGet, with no change in behavior.
Using Google's API Explorer, I'm seeing a similar behavior.
I can retrieve my file successfully using the API Explorer with the get endpoint.
https://developers.google.com/drive/v3/reference/files/get
fileId 1AIuGhzXsNuhhi0PMA1pblh0l5CCDaa1nPj8t_dasi_c
Authentication: API key (uses a "demo API key")
But with the export endpoint, I get an Internal Error (500)-
https://developers.google.com/drive/v3/reference/files/export
fileId 1AIuGhzXsNuhhi0PMA1pblh0l5CCDaa1nPj8t_dasi_c
mimeType: text/html
Authentication: API key (uses a "demo API key")
Changing the Authentication in the API Explorer to OAuth 2.0, and approving access, then returns a successful 200 result with the file HTML. However I'm unable to do that since I'm accessing the API via a UI-less service.
Has anything changed recently with the Google Drive APIs and specifically the Export function, which would cause it to fail while using API Key access after 27-Mar-2018?
Its possible but its most likely a stealth change that you will not get any official word on. Not that long ago i saw someone posting a similar question they were using an API key to update a Google sheet and it suddenly stopped working.
IMO if google has changed this its probably a good thing. API keys are meant for accessing public data. Setting a document to public is a really bad idea if anyone did manage to find the file ID of your document they would then be able to update your document.
Suggestion:
What you should be using is a Service account. Service accounts are dummy users by creating service account credentials on Google developer console and then taking the service account email address you can share the file on Google Drive with the service account granting it access to said file without the need of making the file public.
You havent specified what language you are using but you said you were making a windows service so i am going to assume you are using .net. Here is an example of service account authencation with the Google .net client library.
public static DriveService AuthenticateServiceAccount(string serviceAccountEmail, string serviceAccountCredentialFilePath, string[] scopes)
{
try
{
if (string.IsNullOrEmpty(serviceAccountCredentialFilePath))
throw new Exception("Path to the service account credentials file is required.");
if (!File.Exists(serviceAccountCredentialFilePath))
throw new Exception("The service account credentials file does not exist at: " + serviceAccountCredentialFilePath);
if (string.IsNullOrEmpty(serviceAccountEmail))
throw new Exception("ServiceAccountEmail is required.");
// For Json file
if (Path.GetExtension(serviceAccountCredentialFilePath).ToLower() == ".json")
{
GoogleCredential credential;
using (var stream = new FileStream(serviceAccountCredentialFilePath, FileMode.Open, FileAccess.Read))
{
credential = GoogleCredential.FromStream(stream)
.CreateScoped(scopes);
}
// Create the Analytics service.
return new DriveService(new BaseClientService.Initializer()
{
HttpClientInitializer = credential,
ApplicationName = "Drive Service account Authentication Sample",
});
}
else if (Path.GetExtension(serviceAccountCredentialFilePath).ToLower() == ".p12")
{ // If its a P12 file
var certificate = new X509Certificate2(serviceAccountCredentialFilePath, "notasecret", X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.Exportable);
var credential = new ServiceAccountCredential(new ServiceAccountCredential.Initializer(serviceAccountEmail)
{
Scopes = scopes
}.FromCertificate(certificate));
// Create the Drive service.
return new DriveService(new BaseClientService.Initializer()
{
HttpClientInitializer = credential,
ApplicationName = "Drive Authentication Sample",
});
}
else
{
throw new Exception("Unsupported Service accounts credentials.");
}
}
catch (Exception ex)
{
throw new Exception("CreateServiceAccountDriveFailed", ex);
}
}
}
code ripped from serviceaccount.cs. Assuming that you were already using the Google .net client library the service this method returns will be the same drive service you were using with an api key.
Once you have granted your service account access to the file it will be able to access the file when ever it needs there is no authentication needed as you have preauthorized it by sharing the file with it.
In my Android project, I am trying to connect to the Worklight server (CLI) but after the client.Connect() method call, when I look at the task result, it has an error message saying Error retrieving device data and HTTP status 500. However, I can see the activity count increasing in the Analytics portal.
I am following the sample that comes along with the Xamarin Worklight SDK. All I did was changing the Realm to another one and stripped out irrelevant methods and kept the ConnectAsync & Connect methods alone.
If I run the Worklight sample application that comes along with the SDK, I don't see this error in the task. It gets back a HTTP 200 and everything looks good.
Here is the code, for clarity sake.
private async Task<WorklightResponse> Connect()
{
//lets send a message to the server
client.Analytics.Log("Trying to connect to server", metadata);
ChallengeHandler customCH = new CustomChallengeHandler(appRealm);
client.RegisterChallengeHandler(customCH);
WorklightResponse task = await client.Connect();
//lets log to the local client (not server)
client.Logger("Xamarin").Trace("connection");
//write to the server the connection status
client.Analytics.Log("Connect response : " + task.Success);
return task;
}
This probably has to do with you Android app permissions. Edit your Android project options. In the Android Application->Required Permissions list, select the appropriate permissions. For example, one of my apps requires:
AccessNetworkState
AccessWiFiState
GetAccounts
Internet
UseCredentials
WakeLock
WriteExternalStorage
I have received the same error message without the appropriate permissions. Your list may vary depending on requirements.
By default, the SubscribeServlet is tied to a rejectAll login module which rejects all login requests. If you have not changed the login module, then this is probably why you're seeing your login rejected.
Try changing the login module to a different one if you're using the rejectAll login module
I'm trying to send a push notification to my Windows Store App developed in my laptop using VS 2013 Express. It's been few days now but I cannot figure out why I get "The Token obtained from the Token Provider is wrong" error. I use Windows Azure Notification Bus for this purpose. I use VS Server Explorer to send test notifications. I can see my laptop is being registered as a device in the Device Registration tab too. I tried the Azure portal as well, but the same error. However, when I try to connect to Service Bus Explorer 2.4.3.0 providing the connection string it throws below error.
<21:47:14> Exception: The remote server returned an error: (401) Unauthorized. Manage claim is required for this operation..TrackingId:c0c4fea2-08bc-4def-964c-ec6e690b7551_G45,TimeStamp:10/12/2014 4:17:11 PM. Method b__7e: retry 2 of 10.
FYI: I'm following below article step by step.
http://azure.microsoft.com/en-us/documentation/articles/notification-hubs-windows-store-dotnet-get-started/
Please help me. Thank you.
Mahesh
Looks like token is just expired. Make sure you obtain token each time application starts. In terms of the article you refer it means you should call method InitNotificationsAsync() to do it. Here is that method:
private async void InitNotificationsAsync()
{
var channel = await PushNotificationChannelManager.CreatePushNotificationChannelForApplicationAsync();
var hub = new NotificationHub("<hub name>", "<connection string with listen access>");
var result = await hub.RegisterNativeAsync(channel.Uri);
// Displays the registration ID so you know it was successful
if (result.RegistrationId != null)
{
var dialog = new MessageDialog("Registration successful: " + result.RegistrationId);
dialog.Commands.Add(new UICommand("OK"));
await dialog.ShowAsync();
}
}
I am currently implementing access to Google Contacts via OAuth 2.0 and a so called Service Account. The service account is generated for an ordinary user like "My.Name#gmail.com".
The code to generate the OAuth 2.0 credentials is:
public static GoogleCredential getCredentials() throws GeneralSecurityException, IOException {
GoogleCredential credential = new GoogleCredential.Builder().setTransport(HTTP_TRANSPORT)
.setJsonFactory(JSON_FACTORY)
.setServiceAccountId(SingleUserCredentials.SERVICE_ACCOUNT_EMAIL)
.setServiceAccountScopes("https://www.google.com/m8/feeds")
.setServiceAccountPrivateKeyFromP12File(new File(SingleUserCredentials.SERVICE_ACCOUNT_PKCS12_FILE_PATH))
.build();
credential.refreshToken();
return credential;
}
I am then trying to retrieve the contacts via:
ContactsService myService = new ContactsService(
"myApp");
myService.setOAuth2Credentials(getCredentials());
URL feedUrl = new URL("https://www.google.com/m8/feeds/contacts/default/full");
Query myQuery = new Query(feedUrl);
ContactFeed resultFeed = myService.query(myQuery, ContactFeed.class);
// Print the results
for (ContactEntry entry : resultFeed.getEntries()) {
System.out.println(entry.getName().getFullName().getValue());
System.out.println("Updated on: " + entry.getUpdated().toStringRfc822());
}
The problem is that I do not get any a single contact from my account. The feed is always empty. There is no error. Nothing.
When accessing a Google Apps managed domain via the same approach it works nicely.
I am wondering if the Contacts Api supports OAuth 2.0 for ordinary (aka #gmail.com) accounts when using a p12 key file and a service account.
I ran into that same problem myself.
I tried both the email address that I received when I setup the key and the email address of a domain administrator.
When I use the email from the key setup, I don't receive anything at all -- no warnings, no exceptions, and no data.
When I use the email address of a domain administrator, I receive an exception:
com.google.api.client.auth.oauth2.TokenResponseException: 400 OK
[java] {
[java] "error" : "invalid_grant"
[java] }
[java] Feb 5, 2013 5:16:48 PM com.google.appengine.repackaged.org.apache.http.impl.client.DefaultRequestDirector handleResponse
[java] WARNING: Authentication error: Unable to respond to any of these challenges: {}
[java] Feb 5, 2013 5:16:48 PM com.google.apphosting.utils.jetty.JettyLogger warn
[java] WARNING: /
[java] java.lang.NullPointerException: No authentication header information
...
So, I figured that the domain administrator's email address wasn't what I needed.
Next, I Googled around for a while before finding this page:
http://javadoc.google-api-java-client.googlecode.com/hg/1.13.2-beta/com/google/api/client/googleapis/auth/oauth2/GoogleCredential.html
I saw in there getServiceAccountUser (). The description of the field was:
Returns the email address of the user the application is trying to impersonate in the service account flow or null for none or if not using the service account flow.
Sure enough, there's a corresponding setServiceAccountUser (String) which accepts the username (email address) of the user you're using the service account to impersonate.
I set that field to an appropriate value and I was able to proceed.
In retrospect, it all makes sense -- if I don't supply an account that I'm trying to work from, I can't pull down the contacts for that account.
It is currently not possible to access Contacts using a service account as it is not supported in the Google APIs Console at Google APIs Console.
See also: Service Accounts
Second, it would only work with a Google managed domain because the Admin of the domain must grant access to the service account via the process below:
Delegate domain-wide authority to your service account
The service account that you created now needs to be granted access to the Google Apps domain’s user data that you want to access. The following tasks have to be performed by an administrator of the Google Apps domain:
Go to your Google Apps domain’s control panel. The URL should look like: "www.google.com/a/cpanel/mydomain.com"
Go to Advanced tools... > Manage third party OAuth Client access.
In the Client name field enter the service account's Client ID.
In the One or More API Scopes field enter the list of scopes that your application should be granted access to.
Click the Authorize button.
I've run across this very same error today but have given up on using Service Accounts for now, which I assume is not currently supported in the Contacts API. And so I am using Contacts API v3 with OAuth 1.0 and am getting the expected results.
ContactsService contactsService = new ContactsService(APPLICATION_NAME);
contactsService.setUserCredentials(CLIENT_USERNAME, CLIENT_SECRET);
URL contactFeedURL = new URL("https://www.google.com/m8/feeds/contacts/default/full");
Query contactFeedQuery = new Query(contactFeedURL);
ContactFeed contactFeed = contactsService.getFeed(contactFeedQuery, ContactFeed.class);