0
votes

I'm trying to create a web app which does many things but the one that I'm currently focused in is the inbox count. I want to use EWS StreamSubscription so that I can get notification for each event and returns the total count of items in the inbox. How can I use this in terms of MVC? I did find some code from Microsoft tutorial that I was gonna test, but I just couldn't figure how I could use it in MVC world i.e. What's the model going to be, if model is the count then how does it get notified every time an event occurs in Exchange Server, etc.

Here's the code I downloaded from Microsoft, but just couldn't understand how I can convert the count to json and push it to client as soon as a new change event occurs. NOTE: This code is unchanged, so it doesn't return count, yet.

using System;
using System.Linq;
using System.Net;
using System.Threading;
using Microsoft.Exchange.WebServices.Data;

namespace StreamingNotificationsSample
{
    internal class Program
    {
        private static AutoResetEvent _Signal;
        private static ExchangeService _ExchangeService;
        private static string _SynchronizationState;
        private static Thread _BackroundSyncThread;

        private static StreamingSubscriptionConnection CreateStreamingSubscription(ExchangeService service,
                                                                                   StreamingSubscription subscription)
        {
            var connection = new StreamingSubscriptionConnection(service, 30);
            connection.AddSubscription(subscription);
            connection.OnNotificationEvent += OnNotificationEvent;
            connection.OnSubscriptionError += OnSubscriptionError;
            connection.OnDisconnect += OnDisconnect;
            connection.Open();

            return connection;
        }

        private static void SynchronizeChangesPeriodically()
        {
            while (true)
            {
                try
                {
                    // Get all changes from the server and process them according to the business
                    // rules.
                    SynchronizeChanges(new FolderId(WellKnownFolderName.Inbox));
                }
                catch (Exception ex)
                {
                    Console.WriteLine("Failed to synchronize items. Error: {0}", ex);
                }
                // Since the SyncFolderItems operation is a 
                // rather expensive operation, only do this every 10 minutes
                Thread.Sleep(TimeSpan.FromMinutes(10));
            }
        }

        public static void SynchronizeChanges(FolderId folderId)
        {
            bool moreChangesAvailable;
            do
            {
                Console.WriteLine("Synchronizing changes...");
                // Get all changes since the last call. The synchronization cookie is stored in the _SynchronizationState field.
                // Only the the ids are requested. Additional properties should be fetched via GetItem calls.
                var changes = _ExchangeService.SyncFolderItems(folderId, PropertySet.IdOnly, null, 512,
                                                               SyncFolderItemsScope.NormalItems, _SynchronizationState);
                // Update the synchronization cookie
                _SynchronizationState = changes.SyncState;

                // Process all changes
                foreach (var itemChange in changes)
                {
                    // This example just prints the ChangeType and ItemId to the console
                    // LOB application would apply business rules to each item.
                    Console.Out.WriteLine("ChangeType = {0}", itemChange.ChangeType);
                    Console.Out.WriteLine("ChangeType = {0}", itemChange.ItemId);
                }
                // If more changes are available, issue additional SyncFolderItems requests.
                moreChangesAvailable = changes.MoreChangesAvailable;
            } while (moreChangesAvailable);
        }


        public static void Main(string[] args)
        {
            // Create new exchange service binding
            // Important point: Specify Exchange 2010 with SP1 as the requested version.
            _ExchangeService = new ExchangeService(ExchangeVersion.Exchange2010_SP1)
                               {
                                Credentials = new NetworkCredential("user", "password"),
                                Url = new Uri("URL to the Exchange Web Services")
                               };

            // Process all items in the folder on a background-thread.
            // A real-world LOB application would retrieve the last synchronization state first 
            // and write it to the _SynchronizationState field.
            _BackroundSyncThread = new Thread(SynchronizeChangesPeriodically);
            _BackroundSyncThread.Start();

            // Create a new subscription
            var subscription = _ExchangeService.SubscribeToStreamingNotifications(new FolderId[] {WellKnownFolderName.Inbox},
                                                                                  EventType.NewMail);
            // Create new streaming notification conection
            var connection = CreateStreamingSubscription(_ExchangeService, subscription);

            Console.Out.WriteLine("Subscription created.");
            _Signal = new AutoResetEvent(false);

            // Wait for the application to exit
            _Signal.WaitOne();

            // Finally, unsubscribe from the Exchange server
            subscription.Unsubscribe();
            // Close the connection
            connection.Close();
        }

        private static void OnDisconnect(object sender, SubscriptionErrorEventArgs args)
        {
            // Cast the sender as a StreamingSubscriptionConnection object.           
            var connection = (StreamingSubscriptionConnection) sender;
            // Ask the user if they want to reconnect or close the subscription. 
            Console.WriteLine("The connection has been aborted; probably because it timed out.");
            Console.WriteLine("Do you want to reconnect to the subscription? Y/N");
            while (true)
            {
                var keyInfo = Console.ReadKey(true);
                {
                    switch (keyInfo.Key)
                    {
                        case ConsoleKey.Y:
                            // Reconnect the connection
                            connection.Open();
                            Console.WriteLine("Connection has been reopened.");
                            break;
                        case ConsoleKey.N:
                            // Signal the main thread to exit.
                            Console.WriteLine("Terminating.");
                            _Signal.Set();
                            break;
                    }
                }
            }
        }

        private static void OnNotificationEvent(object sender, NotificationEventArgs args)
        {
            // Extract the item ids for all NewMail Events in the list.
            var newMails = from e in args.Events.OfType<ItemEvent>()
                           where e.EventType == EventType.NewMail
                           select e.ItemId;

            // Note: For the sake of simplicity, error handling is ommited here. 
            // Just assume everything went fine
            var response = _ExchangeService.BindToItems(newMails,
                                                        new PropertySet(BasePropertySet.IdOnly, ItemSchema.DateTimeReceived,
                                                                        ItemSchema.Subject));
            var items = response.Select(itemResponse => itemResponse.Item);

            foreach (var item in items)
            {
                Console.Out.WriteLine("A new mail has been created. Received on {0}", item.DateTimeReceived);
                Console.Out.WriteLine("Subject: {0}", item.Subject);
            }
        }

        private static void OnSubscriptionError(object sender, SubscriptionErrorEventArgs args)
        {
            // Handle error conditions. 
            var e = args.Exception;
            Console.Out.WriteLine("The following error occured:");
            Console.Out.WriteLine(e.ToString());
            Console.Out.WriteLine();
        }
    }
}

I just want to understand the basic concept as in what can be model, and where can I use other functions.

2
Unlike forum sites, we don't use "Thanks", or "Any help appreciated", or signatures on Stack Overflow. See "Should 'Hi', 'thanks,' taglines, and salutations be removed from posts?.John Saunders
Ok, thank. Will keep that in mind. Creature of habit.user1828605

2 Answers

1
votes

Your problem is that you are confusing a service (EWS) with your applications model. They are two different things. Your model is entirely in your control, and you can do whatever you want with it. EWS is outside of your control, and is merely a service you call to get data.

In your controller, you call the EWS service and get the count. Then you populate your model with that count, then in your view, you render that model property. It's really that simple.

A web page has no state. It doesn't get notified when things change. You just reload the page and get whatever the current state is (ie, whatever the current count is).

In more advanced applications, like Single Page Apps, with Ajax, you might periodically query the service in the background. Or, you might have a special notification service that uses something like SignalR to notify your SPA of a change, but these concepts are far more advanced than you currently are. You should probably develop your app as a simple stateless app first, then improve it to add ajax functionality or what not once you have a better grasp of things.

0
votes

That's a very broad question without a clear-cut answer. Your model could certainly have a "Count" property that you could update. The sample code you found would likely be used by your controller.