Azure Stream Analytics Error : Could not deserialize the input event(s) from IOT hub - json

I have created the Stream Analytics job to read data from IOT hub as input and and to store data to SQL DB.
Here are the some important input details configured for Steam Analytics job are
Event Serialization format: JSON
Encoding :utf-8
The message is sent to IOT Hub from Dotnet simulated code.
When I am running my job I am getting the following error:
Could not deserialize the input event as Json. Some possible reasons:
1) Malformed events
2) Input source configured with incorrect serialization format
And here is the my dotnet code.
private static async void ReceiveC2dAsync()
{
Console.WriteLine("\nReceiving cloud to device messages from service");
while (true)
{
Message receivedMessage = await deviceClient.ReceiveAsync();
if (receivedMessage == null) continue;
Console.ForegroundColor = ConsoleColor.Yellow;
Console.WriteLine("Received message: {0}", Encoding.ASCII.GetString(receivedMessage.GetBytes()));
Console.ResetColor();
await deviceClient.CompleteAsync(receivedMessage);
}
}
private static async void SendDeviceToCloudMessagesAsync()
{
double minTemperature = 20;
double minHumidity = 60;
int messageId = 1;
Random rand = new Random();
while (true)
{
double currentTemperature = minTemperature + rand.NextDouble() * 15;
double currentHumidity = minHumidity + rand.NextDouble() * 20;
var telemetryDataPoint = new
{
messageId = messageId++,
deviceId = "myFirstDevice",
temperature = currentTemperature,
humidity = currentHumidity
};
var messageString = JsonConvert.SerializeObject(telemetryDataPoint);
string levelValue;
string temperatureAlert = "false";
if (rand.NextDouble() > 0.7)
{
if (rand.NextDouble() > 0.5)
{
messageString = "This is a critical message";
levelValue = "critical";
}
else
{
messageString = "This is a storage message";
levelValue = "storage";
}
}
else
{
levelValue = "normal";
}
if(currentTemperature > 30)
{
temperatureAlert = "true";
}
var message = new Message(Encoding.UTF8.GetBytes(messageString));
message.Properties.Add("level", levelValue);
message.Properties.Add("temperatureAlert", temperatureAlert);
await deviceClient.SendEventAsync(message);
Console.WriteLine("{0} > Sending message: {1}", DateTime.Now, messageString);
await Task.Delay(1000);
}
}

it looks like your simulated device generated non-json formatted messages such as "This is a critical message" and "This is a storage message".
Basically, you have two choices to fix this issue:
1. comment this part in the simulated code or
2. add the filter in the Azure IoT Hub Routes for these messages

Related

Schema Extension Value is always NULL when updating through Microsoft Graph SDK

Step 1:
Created GraphServiceClient using Microsoft.Graph 4.9.0 and Microsoft.Graph.Core 2.0.5 SDK
var scopes = new[] { "https://graph.microsoft.com/.default" };
ClientSecretCredential clientSecretCredential = new ClientSecretCredential(tenantId, clientId, clientSecret, new ClientSecretCredentialOptions()
{
AuthorityHost = AzureAuthorityHosts.AzurePublicCloud
});`
GraphServiceClient graphServiceClient = new GraphServiceClient(clientSecretCredential, scopes);
Step 2:
And created a custom schema extension like below.
SchemaExtension schemaExtension = new SchemaExtension()
{
Id = "data1",
Description = "creating test schema extn",
TargetTypes = new List<string>()
{
"User"
},
Properties = new List<ExtensionSchemaProperty>()
{
new ExtensionSchemaProperty()
{
Name ="prop1",
Type ="String"
}
}
};
Step 3:
Updated the Schema extension status to "Available"
var updatedExtn = await graphServiceClient
.SchemaExtensions[schemaExtension.Id].Request()
.UpdateAsync(new SchemaExtension()
{
Status = "Available"
});
Step 4:
Create Class for extension data
public class data1
{
// You must serialize your property names to camelCase if your SchemaExtension describes as such.
[JsonProperty(NullValueHandling = NullValueHandling.Ignore, PropertyName = "prop1", Required = Newtonsoft.Json.Required.Default)]
public string Prop1 { get; set; }
}
Step 5:
Find the User and add the created schema extension to the user
IDictionary<string, object> extensionInstance = new Dictionary<string, object>();
// The below line is not working. but doesn't throw error
extensionInstance.Add(schemaExtension.Id, new data1 { prop1 = "testing" });
var usrCollection = await graphServiceClient.Users
.Request()
.Filter($"userPrincipalNames eq '{adelev_Mail}'")
.GetAsync();
var usr = usrCollection.FirstOrDefault();
if(usr != null)
{
usr.AdditionalData.Add(extensionInstance);
var updatedUser = await graphServiceClient.Users[usr.Id]
.Request()
.UpdateAsync(usr);
}
Step 6:
When you try to retrieve the extension the value is NULL.
User updatedUser = await graphServiceClient.Users[usr.Id].Request()
.Select($"id, {schemaExtension.Id}")
.GetAsync();
But it works with API using Graph Explorer.
PATCH https://graph.microsoft.com/v1.0/users/{userId}
{
"extXXXXXXXX_data1":
{
"prop1" : "testing"
}
}
Please let me know if I'm missing anything here. Any help here is much appreciated.
You should accessing the data on AdditionalData property. Try looking at user.AdditionalData in your result. Here is a screenshot with my example.
Getting User with Schema extension from Graph explorer.
While using the SDK, i access my custom data in user.AdditionalData
Check this thread - Graph SDK and SchemaExtensions for details.

Why the custom exception message from an exception is not shown in a Xamarin solution?

I have been understanding this example for Xamarin cross-platform mobile development:
https://msdn.microsoft.com/en-us/library/dn879698.aspx
I made an error by copying two times the the API key in the code:
using System;
using System.Threading.Tasks;
namespace XWeatherApp
{
public class Core
{
public static async Task<Weather> GetWeather(string zipCode)
{
//Sign up for a free API key at http://openweathermap.org/appid
string key = "40aabb59f41e9e88db7be4bab11f49f8";
string queryString = "http://api.openweathermap.org/data/2.5/weather?zip="
+ zipCode + ",us&appid=" + key + "&units=imperial";
//Make sure developers running this sample replaced the API key
if (key == "40aabb59f41e9e88db7be4bab11f49f8")
{
throw new ArgumentException("You must obtain an API key from openweathermap.org/appid and save it in the 'key' variable.");
}
dynamic results = await DataService.getDataFromService(queryString).ConfigureAwait(true);
if (results["weather"] != null)
{
Weather weather = new Weather();
weather.Title = (string)results["name"];
weather.Temperature = (string)results["main"]["temp"] + " F";
weather.Wind = (string)results["wind"]["speed"] + " mph";
weather.Humidity = (string)results["main"]["humidity"] + " %";
weather.Visibility = (string)results["weather"][0]["main"];
DateTime time = new System.DateTime(1970, 1, 1, 0, 0, 0, 0);
DateTime sunrise = time.AddSeconds((double)results["sys"]["sunrise"]);
DateTime sunset = time.AddSeconds((double)results["sys"]["sunset"]);
weather.Sunrise = sunrise.ToString() + " UTC";
weather.Sunset = sunset.ToString() + " UTC";
return weather;
}
else
{
return null;
}
}
}
}
Specifically, in the lines after the two comments.
I deployed the app to a physical Android phone. Obviously I got an exception (this was not so obvious after some minutes looking for the failing code).
That exception wasn't displayed in the Output window (in Visual Studio 2017). I just only got this message on screen:
Why don't the custom message for the exception (i.e., You must obtain an API key from openweathermap.org/appid and save it in the 'key' variable.).
Have you tried to use a try/catch?
something like
try{
await GetWeather(string zipCode);
}
catch(Exception ex) {
// here you should have your exception
}

WP8 - Scheduled Task Agent for push notifications

I'm trying to interface my app with push notifications and the backend developer choose Pusher as notifications provider.
.NET SDK is very messy, untidy and synchronous, which it does not work on WP8, so I rewrote its and it works fine now.
The question is: is a Scheduled Task required for fetch the push notifications and update the tile/toast? Or there are any best method?
I can't change push provider sadly.
You can simply send Tile and Toast push notifications to the phone and they will work even if your app is not running. You do not need background task for that.
Here is sample code that I use in a desktop application to send push notifications to a Windows Phone 8.0:
const String toastTemplate =
"<?xml version=\"1.0\" encoding=\"utf-8\"?>" +
"<wp:Notification xmlns:wp=\"WPNotification\">" +
"<wp:Toast>" +
"<wp:Text1>{0}</wp:Text1>" +
"<wp:Text2>{1}</wp:Text2>" +
"<wp:Param>{2}</wp:Param>" +
"</wp:Toast>" +
"</wp:Notification>";
String message = String.Format(toastTemplate, "Test", "updated: " + DateTime.Now.ToString(), "/Pages/SyncPage.xaml");
Status = await PushNotifiactionsManager.SendNotification(cfg.PushNotificationUri, message, 2);
public static async Task<string> SendNotification(string pushNotificationUri, string message, short notificationClass)
{
String responseText;
if (message.Length > 3072)
{
responseText = String.Format("The message must be <= 3072 bytes: {0}", message);
}
else
{
HttpClient request = new HttpClient();
// Add message headers.
request.DefaultRequestHeaders.Add("X-MessageID", Guid.NewGuid().ToString());
request.DefaultRequestHeaders.Add("X-NotificationClass", notificationClass.ToString());
if (notificationClass == 1)
{
request.DefaultRequestHeaders.Add("X-WindowsPhone-Target", "token");
}
else if (notificationClass == 2)
{
request.DefaultRequestHeaders.Add("X-WindowsPhone-Target", "toast");
}
try
{
// Send the message, and wait for the response.
HttpResponseMessage response = await request.PostAsync(pushNotificationUri, new StringContent(message));
IEnumerable<string> values;
String connectionStatus = String.Empty;
if (response.Headers.TryGetValues("X-DeviceConnectionStatus", out values))
{
connectionStatus = values.First();
}
String subscriptionStatus = String.Empty;
if (response.Headers.TryGetValues("X-SubscriptionStatus", out values))
{
subscriptionStatus = values.First();
}
String notificationStatus = String.Empty;
if (response.Headers.TryGetValues("X-NotificationStatus", out values))
{
notificationStatus = values.First();
}
responseText = String.Format("{0}: {1}, {2}, {3}, {4}",
notificationClass == 1 ? "Tile" :
notificationClass == 2 ? "Toast" : "Raw",
response.StatusCode,
connectionStatus, subscriptionStatus, notificationStatus);
}
catch (WebException ex)
{
responseText = ex.Message;
}
}
return "Notification response: " + responseText;
}

APEX, Unit Test, Callout No Response with Static Resource

Bit stuck on another one i'm afraid, i am trying to write a unit test for a bulk APEX class.
The class has a calllout to the google api, so i have created a static resource which i am feeding in via a mock, so i can complete testing of processing the JSON that is returned. However for some reason the response is always empty.
Now the very odd thing is that if i use exactly the same callout/JSON code, and the same mock code on a previous #future call, then it does return fine.
Here is the class:
global class mileage_bulk implements Database.Batchable<sObject>,
Database.AllowsCallouts
{
global Database.QueryLocator start(Database.BatchableContext BC)
{
String query = 'SELECT Id,Name,Amount,R2_Job_Ref__c,R2_Shipping_Post_Code__c,Shipping_Postcode_2__c FROM Opportunity WHERE R2_Shipping_Post_Code__c != null';
return Database.getQueryLocator(query);
//system.debug('Executing'+query);
}
global void execute(Database.BatchableContext BC, List<Opportunity> scope)
{
system.debug(scope);
for(Opportunity a : scope)
{
String startPostcode = null;
startPostcode = EncodingUtil.urlEncode('HP27DU', 'UTF-8');
String endPostcode = null;
String endPostcodeEncoded = null;
if (a.R2_Shipping_Post_Code__c != null){
endPostcode = a.R2_Shipping_Post_Code__c;
Pattern nonWordChar = Pattern.compile('[^\\w]');
endPostcode = nonWordChar.matcher(endPostcode).replaceAll('');
endPostcodeEncoded = EncodingUtil.urlEncode(endPostcode, 'UTF-8');
}
Double totalDistanceMeter = null;
Integer totalDistanceMile = null;
String responseBody = null;
Boolean firstRecord = false;
String ukPrefix = 'UKH';
if (a.R2_Job_Ref__c != null){
if ((a.R2_Job_Ref__c).toLowerCase().contains(ukPrefix.toLowerCase())){
system.debug('Is Hemel Job');
startPostcode = EncodingUtil.urlEncode('HP27DU', 'UTF-8');
} else {
system.debug('Is Bromsgrove Job');
startPostcode = EncodingUtil.urlEncode('B604AD', 'UTF-8');
}
}
// build callout
Http h = new Http();
HttpRequest req = new HttpRequest();
req.setEndpoint('http://maps.googleapis.com/maps/api/directions/json?origin='+startPostcode+'&destination='+endPostcodeEncoded+'&units=imperial&sensor=false');
req.setMethod('GET');
req.setTimeout(60000);
system.debug('request follows');
system.debug(req);
try{
// callout
HttpResponse res = h.send(req);
// parse coordinates from response
JSONParser parser = JSON.createParser(res.getBody());
responseBody = res.getBody();
system.debug(responseBody);
while (parser.nextToken() != null) {
if ((parser.getCurrentToken() == JSONToken.FIELD_NAME) &&
(parser.getText() == 'distance')){
parser.nextToken(); // object start
while (parser.nextToken() != JSONToken.END_OBJECT){
String txt = parser.getText();
parser.nextToken();
//system.debug(parser.nextToken());
//system.debug(txt);
if (firstRecord == false){
//if (txt == 'text'){
//totalDistanceMile = parser.getText();
system.debug(parser.getText());
//}
if (txt == 'value'){
totalDistanceMeter = parser.getDoubleValue();
double inches = totalDistanceMeter*39.3701;
totalDistanceMile = (integer)inches/63360;
system.debug(parser.getText());
firstRecord = true;
}
}
}
}
}
} catch (Exception e) {
}
//system.debug(accountId);
system.debug(a);
system.debug(endPostcodeEncoded);
system.debug(totalDistanceMeter);
system.debug(totalDistanceMile);
// update coordinates if we get back
if (totalDistanceMile != null){
system.debug('Entering Function to Update Object');
a.DistanceM__c = totalDistanceMile;
a.Shipping_Postcode_2__c = a.R2_Shipping_Post_Code__c;
//update a;
}
}
update scope;
}
global void finish(Database.BatchableContext BC)
{
}
}
and here is the test class;
#isTest
private class mileage_bulk_tests{
static testMethod void myUnitTest() {
Opportunity opp1 = new Opportunity(name = 'Google Test Opportunity',R2_Job_Ref__c = 'UKH12345',R2_Shipping_Post_Code__c = 'AL35QW',StageName = 'qualified',CloseDate = Date.today());
insert opp1;
Opportunity opp2 = new Opportunity(name = 'Google Test Opportunity 2',StageName = 'qualified',CloseDate = Date.today());
insert opp2;
Opportunity opp3 = new Opportunity(name = 'Google Test Opportunity 3',R2_Job_Ref__c = 'UKB56789',R2_Shipping_Post_Code__c = 'AL35QW',StageName = 'qualified',CloseDate = Date.today());
insert opp3;
StaticResourceCalloutMock mock = new StaticResourceCalloutMock();
mock.setStaticResource('googleMapsJSON');
mock.setStatusCode(200); // Or other appropriate HTTP status code
mock.setHeader('Content-Type', 'application/json'); // Or other appropriate MIME type like application/xml
//Set the mock callout mode
Test.setMock(HttpCalloutMock.class, mock);
system.debug(opp1);
system.debug(opp1.id);
//Call the method that performs the callout
Test.startTest();
mileage_bulk b = new mileage_bulk();
database.executeBatch((b), 10);
Test.stopTest();
}
}
Help greatly appreciated!
Thanks
Gareth
Not certain what 'googleMapsJSON' looks like, perhaps you could post for us.
Assuming your mock resource is well formatted, make sure the file extension is ".json" and was saved with UTF-8 encoding.
If #2 does not work, you should try saving your resource as .txt - I've run in to this before where it needed a plain text resource but expected application/json content type
Be certain that the resource name string you are providing has the same casing as the name of the resource. It is case sensitive.
Are you developing on a namespaced package environment? Try adding the namespace to the resource name if so.
Otherwise, your code looks pretty good at first glance.

Multiple PushNotification Subscriptions some work properly and some don't

I tried posting this on the Exchange Development forum and didnt get any replies, so I will try here. Link to forum
I have a windows services that fires every fifteen minutes to see if there is any subscriptions that need to be created or updated. I am using the Managed API v1.1 against Exchange 2007 SP1. I have a table that stores all the users that want there mailbox monitored. So that when a notifcation comes in to the "Listening Service" I am able to look up the user and access the message to log it into the application we are building. In the table I have the following columns that store the subscription information:
SubscriptionId - VARCHAR(MAX)
Watermark - VARCHAR(MAX)
LastStatusUpdate - DATETIME
My services calls a function that queries the data needed (based on which function it is doing). If the user doesn't have a subscription already the service will go and create one. I am using impersonation to access the mailboxes. Here is my "ActiveSubscription" method that is fired when a user needs the subscription either created or updated.
private void ActivateSubscription(User user)
{
if (user.ADGUID.HasValue)
{
PrincipalContext ctx = new PrincipalContext(ContextType.Domain, Settings.ActiveDirectoryServerName, Settings.ActiveDirectoryRootContainer);
using (UserPrincipal up = UserPrincipal.FindByIdentity(ctx, IdentityType.Guid, user.ADGUID.Value.ToString()))
{
ewService.ImpersonatedUserId = new ImpersonatedUserId(ConnectingIdType.SID, up.Sid.Value);
}
}
else
{
ewService.ImpersonatedUserId = new ImpersonatedUserId(ConnectingIdType.SmtpAddress, user.EmailAddress);
}
PushSubscription pushSubscription = ewService.SubscribeToPushNotifications(
new FolderId[] { WellKnownFolderName.Inbox, WellKnownFolderName.SentItems },
Settings.ListenerService, 30, user.Watermark,
EventType.NewMail, EventType.Created);
user.Watermark = pushSubscription.Watermark;
user.SubscriptionID = pushSubscription.Id;
user.SubscriptionStatusDateTime = DateTime.Now.ToLocalTime();
_users.Update(user);
}
We have also ran the following cmdlet to give the user we are accessing the EWS with the ability to impersonate on the Exchange Server.
Get-ExchangeServer | where {$_.IsClientAccessServer -eq $TRUE} | ForEach-Object {Add-ADPermission -Identity $_.distinguishedname -User (Get-User -Identity mailmonitor | select-object).identity -extendedRight ms-Exch-EPI-Impersonation}
The "ActivateSubscription" code above works as expected. Or so I thought. When I was testing it I had it monitoring my mailbox and it worked great. The only problem I had to work around was that the subscription was firing twice when the item was a new mail in the inbox, I got a notification for the NewMail event and Created event. I implemented a work around that checks to make sure the message hasn't already been logged on my Listening service. It all worked great.
Today, we started testing two mailboxes being monitor at the same time. The two mailboxes were mine and another developers mailbox. We found the strangest behavior. My subscription worked as expected. But his didn't, the incoming part of his subscription work properly but any email he sent out the listening service never was sent a notification. Looking at the mailbox properties on Exchange I don't see any difference between his mailbox and mine. We even compared options/settings in Outlook. I can see no reasons why it works on my mailbox and not on his.
Is there something that I am missing when creating the subscription. I didn't think there was since my subscription works as expected.
My listening service code works perfectly well. I have placed the code below incase someone wants to see it to make sure it is not the issue.
Thanks in advance, Terry
Listening Service Code:
/// <summary>
/// Summary description for PushNotificationClient
/// </summary>
[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
[System.ComponentModel.ToolboxItem(false)]
// To allow this Web Service to be called from script, using ASP.NET AJAX, uncomment the following line.
// [System.Web.Script.Services.ScriptService]
public class PushNotificationClient : System.Web.Services.WebService, INotificationServiceBinding
{
ExchangeService ewService = new ExchangeService(ExchangeVersion.Exchange2007_SP1);
public PushNotificationClient()
{
//todo: init the service.
SetupExchangeWebService();
}
private void SetupExchangeWebService()
{
ewService.Credentials = Settings.ServiceCreds;
try
{
ewService.AutodiscoverUrl(Settings.AutoDiscoverThisEmailAddress);
}
catch (AutodiscoverRemoteException e)
{
//log auto discovery failed
ewService.Url = Settings.ExchangeService;
}
}
public SendNotificationResultType SendNotification(SendNotificationResponseType SendNotification1)
{
using (var _users = new ExchangeUser(Settings.SqlConnectionString))
{
var result = new SendNotificationResultType();
var responseMessages = SendNotification1.ResponseMessages.Items;
foreach (var responseMessage in responseMessages)
{
if (responseMessage.ResponseCode != ResponseCodeType.NoError)
{
//log error and unsubscribe.
result.SubscriptionStatus = SubscriptionStatusType.Unsubscribe;
return result;
}
var sendNoficationResponse = responseMessage as SendNotificationResponseMessageType;
if (sendNoficationResponse == null)
{
result.SubscriptionStatus = SubscriptionStatusType.Unsubscribe;
return result;
}
var notificationType = sendNoficationResponse.Notification;
var subscriptionId = notificationType.SubscriptionId;
var previousWatermark = notificationType.PreviousWatermark;
User user = _users.GetById(subscriptionId);
if (user != null)
{
if (user.MonitorEmailYN == true)
{
BaseNotificationEventType[] baseNotifications = notificationType.Items;
for (int i = 0; i < notificationType.Items.Length; i++)
{
if (baseNotifications[i] is BaseObjectChangedEventType)
{
var bocet = baseNotifications[i] as BaseObjectChangedEventType;
AccessCreateDeleteNewMailEvent(bocet, ref user);
}
}
_PreviousItemId = null;
}
else
{
user.SubscriptionID = String.Empty;
user.SubscriptionStatusDateTime = null;
user.Watermark = String.Empty;
_users.Update(user);
result.SubscriptionStatus = SubscriptionStatusType.Unsubscribe;
return result;
}
user.SubscriptionStatusDateTime = DateTime.Now.ToLocalTime();
_users.Update(user);
}
else
{
result.SubscriptionStatus = SubscriptionStatusType.Unsubscribe;
return result;
}
}
result.SubscriptionStatus = SubscriptionStatusType.OK;
return result;
}
}
private string _PreviousItemId;
private void AccessCreateDeleteNewMailEvent(BaseObjectChangedEventType bocet, ref User user)
{
var watermark = bocet.Watermark;
var timestamp = bocet.TimeStamp.ToLocalTime();
var parentFolderId = bocet.ParentFolderId;
if (bocet.Item is ItemIdType)
{
var itemId = bocet.Item as ItemIdType;
if (itemId != null)
{
if (string.IsNullOrEmpty(_PreviousItemId) || (!string.IsNullOrEmpty(_PreviousItemId) && _PreviousItemId != itemId.Id))
{
ProcessItem(itemId, ref user);
_PreviousItemId = itemId.Id;
}
}
}
user.SubscriptionStatusDateTime = timestamp;
user.Watermark = watermark;
using (var _users = new ExchangeUser(Settings.SqlConnectionString))
{
_users.Update(user);
}
}
private void ProcessItem(ItemIdType itemId, ref User user)
{
try
{
ewService.ImpersonatedUserId = new ImpersonatedUserId(ConnectingIdType.SmtpAddress, user.EmailAddress);
EmailMessage email = EmailMessage.Bind(ewService, itemId.Id);
using (var _entity = new SalesAssistantEntityDataContext(Settings.SqlConnectionString))
{
var direction = EmailDirection.Incoming;
if (email.From.Address == user.EmailAddress)
{
direction = EmailDirection.Outgoing;
}
int? bodyType = (int)email.Body.BodyType;
var _HtmlToRtf = new HtmlToRtf();
var message = _HtmlToRtf.ConvertHtmlToText(email.Body.Text);
bool? IsIncoming = Convert.ToBoolean((int)direction);
if (IsIncoming.HasValue && IsIncoming.Value == false)
{
foreach (var emailTo in email.ToRecipients)
{
_entity.InsertMailMessage(email.From.Address, emailTo.Address, email.Subject, message, bodyType, IsIncoming);
}
}
else
{
if (email.ReceivedBy != null)
{
_entity.InsertMailMessage(email.From.Address, email.ReceivedBy.Address, email.Subject, message, bodyType, IsIncoming);
}
else
{
var emailToFind = user.EmailAddress;
if (email.ToRecipients.Any(x => x.Address == emailToFind))
{
_entity.InsertMailMessage(email.From.Address, emailToFind, email.Subject, message, bodyType, IsIncoming);
}
}
}
}
}
catch(Exception e)
{
//Log exception
using (var errorHandler = new ErrorHandler(Settings.SqlConnectionString))
{
errorHandler.LogException(e, user.UserID, user.SubscriptionID, user.Watermark, user.SubscriptionStatusDateTime);
}
throw e;
}
}
}
I have two answers for you.
At first you will have to create one instance of ExchangeService per user. Like I understand your Code you just create one instance and switch the impersonation, which is not supported. I developed a windowsservice which is pretty similar to yours. Mine is synchronising the mails between our CRM and Exchange. So at startup I create an instance per user and Cache it as long as the application runs.
Now about cache-mode. The diffrence between using cache-mode and not is just a timing gab. In cache-mode Outlook synchronizes from time to time. And non cached it's in time. When you use the cache-mode and want the Events immediatly on your Exchange-Server you can press the "send and receive"-button in Outlook to force the sync.
Hope that helps you...