5

Я пытаюсь создать службу для обмена уведомлениями об обмене в приложениях asp.net, в конечном итоге используя SignalR.EWS Notification Hub для нескольких пользователей

Мой план заключается в создании центра уведомлений, который подписывается на каждого пользователя при входе в приложение asp и прослушивания уведомлений для них. По мере получения уведомления вторая часть проекта должна затем использовать signalR для отправки правильных уведомлений каждому пользователю. Как только они выйдут из системы или тайм-аут, центр уведомлений отменит их подписку.

До сих пор я провел небольшое базовое тестирование и могу получать уведомления в небольшом консольном приложении для себя с моими учетными данными, жестко закодированными. То, с чем я борюсь, - это как сделать это для нескольких людей одновременно. Например, мне придется создавать отдельные потоки для каждого пользователя или есть лучший способ?

Я предполагаю, что независимо от того, что мне нужно использовать олицетворение, а не держать права каждого пользователя правильно? Мне также придется разработать способ автоматического обновления тайм-аута для каждого пользователя, если у них активная сессия.

Ниже приводится небольшой код, который я нашел и играл с ним, я был бы благодарен за любые идеи или примеры, которые могли бы рассказать о том, как я мог бы достичь этого.

Большое спасибо

Энди

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Net; 
using System.Threading.Tasks; 
using Microsoft.Exchange.WebServices.Data; 

namespace ConsoleApplication1 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 

       ExchangeService service = new ExchangeService(ExchangeVersion.Exchange2010_SP2); 
       service.Url = new Uri("https://server/EWS/Exchange.asmx"); 
       service.Credentials = new NetworkCredential("user", "pass", "domain"); 
       SetStreamingNotifications(service); 
       while (true) 
       { } 


     } 

     static void SetStreamingNotifications(ExchangeService service) 
     { 
      // Subscribe to streaming notifications on the Inbox folder, and listen 
      // for "NewMail", "Created", and "Deleted" events. 
      StreamingSubscription streamingsubscription = service.SubscribeToStreamingNotifications(
       new FolderId[] { WellKnownFolderName.Calendar, WellKnownFolderName.Inbox }, 
       EventType.Created, 
       EventType.Modified); 

      StreamingSubscriptionConnection connection = new StreamingSubscriptionConnection(service, 9); 

      connection.AddSubscription(streamingsubscription); 
      // Delegate event handlers. 
      connection.OnNotificationEvent += 
       new StreamingSubscriptionConnection.NotificationEventDelegate(OnEvent); 
      connection.OnSubscriptionError += 
       new StreamingSubscriptionConnection.SubscriptionErrorDelegate(OnError); 
      connection.OnDisconnect += 
       new StreamingSubscriptionConnection.SubscriptionErrorDelegate(OnDisconnect); 
      connection.Open(); 

      Console.WriteLine("--------- StreamSubscription event -------"); 
     } 

     static private void OnDisconnect(object sender, SubscriptionErrorEventArgs args) 
     { 
      // Cast the sender as a StreamingSubscriptionConnection object.   
      StreamingSubscriptionConnection connection = (StreamingSubscriptionConnection)sender; 
      // Ask the user if they want to reconnect or close the subscription. 
      ConsoleKeyInfo cki; 
      Console.WriteLine("The connection to the subscription is disconnected."); 
      Console.WriteLine("Do you want to reconnect to the subscription? Y/N"); 
      while (true) 
      { 
       cki = Console.ReadKey(true); 
       { 
        if (cki.Key == ConsoleKey.Y) 
        { 
         connection.Open(); 
         Console.WriteLine("Connection open."); 
         break; 
        } 
        else if (cki.Key == ConsoleKey.N) 
        { 
         // The ReadKey in the Main() consumes the E. 
         Console.WriteLine("\n\nPress E to exit"); 
         break; 
        } 
       } 
      } 
     } 

     static void OnEvent(object sender, NotificationEventArgs args) 
     { 
      StreamingSubscription subscription = args.Subscription; 

      // Loop through all item-related events. 
      foreach (NotificationEvent notification in args.Events) 
      { 

       switch (notification.EventType) 
       { 
        case EventType.NewMail: 
         Console.WriteLine("\n-------------Mail created:-------------"); 
         break; 
        case EventType.Created: 
         Console.WriteLine("\n-------------Item or folder created:-------------"); 
         break; 
        case EventType.Deleted: 
         Console.WriteLine("\n-------------Item or folder deleted:-------------"); 
         break; 
       } 
       // Display the notification identifier. 
       if (notification is ItemEvent) 
       { 
        // The NotificationEvent for an e-mail message is an ItemEvent. 
        ItemEvent itemEvent = (ItemEvent)notification; 
        Console.WriteLine("\nItemId: " + itemEvent.ItemId.UniqueId); 

       } 
       else 
       { 
        // The NotificationEvent for a folder is an FolderEvent. 
        //FolderEvent folderEvent = (FolderEvent)notification; 
        //Console.WriteLine("\nFolderId: " + folderEvent.FolderId.UniqueId); 
       } 
      } 
     } 
     static void OnError(object sender, SubscriptionErrorEventArgs args) 
     { 
      // Handle error conditions. 
      Exception e = args.Exception; 
      Console.WriteLine("\n-------------Error ---" + e.Message + "-------------"); 
     } 
    } 
} 

ответ

3

Как я решил эту проблему с помощью:

  1. Имея счет, который имеет право выдавать себя всех пользователей.
  2. Я создаю службу для этой учетной записи с указанием имени пользователя и пароля .
  3. Я олицетворения пользователя и добавить подписки пользователя на связи
  4. создать другой сервис, который является близким для основного сервиса с то же имя пользователя и пароль, который будет выдавать себя за другого пользователя , а затем добавить подписка на то же соединение до

Вот две части моего кода. Забудьте о LogDevice, это просто что-то внутренне. Первая часть - это подробное олицетворение и добавление услуги в список услуг. . Список услуг в моем случае - это словарь с userSMTP, это ключ, ключ UserSMTP - это олицетворяемая учетная запись.

/// <summary> 
    /// Impersonate one user at a time and without using the autodiscovery method to find the proper url for the userSmtp, 
    /// and copy the provided url to the usersmtp. 
    /// </summary> 
    /// <param name="url"> </param> 
    /// <param name="userSmtp">user smtp</param> 
    /// <param name="enableTrace">to enable logging from the XML tracing </param> 
    /// <param name="exchangeVersion">Exchange server version used</param> 
    private Uri ImpersonateUser(Uri url, string userSmtp, bool enableTrace, ExchangeVersion exchangeVersion) 
    { 
     Uri result = url; 
     var log = "ImpersonateUser \n"; 
     try 
     { 
      log += "0/8 Checking services redundancy\n"; 
      if (Services.ContainsKey(userSmtp)) 
      { 
       Services.Remove(userSmtp); 
      } 
      log += "1/8 Create a new service for " + userSmtp + "\n"; 
      var service = new ExchangeService(exchangeVersion); 

      log += "2/8 Get credentials for the service\n"; 
      var serviceCred = ((System.Net.NetworkCredential)(((WebCredentials)(Services.First().Value.Credentials)).Credentials)); 

      log += "3/8 Assign credentials to the new service\n"; 
      service.Credentials = new WebCredentials(serviceCred.UserName, serviceCred.Password); 

      log += "4/8 TraceEnabled is" + enableTrace.ToString() + "\n"; 
      service.TraceEnabled = enableTrace; 

      log += "5/8 Get the Url for the service with AutodiscoverUrl \n"; 
      service.Url = url; 

      log += "6/8 Assign a new ImpersonatedUserId to the new service for" + userSmtp + "\n"; 
      service.ImpersonatedUserId = new ImpersonatedUserId(ConnectingIdType.SmtpAddress, userSmtp); 

      try 
      { 
       log += "7/8 Validating the impersonation\n"; 
       RuleCollection rulecoll = service.GetInboxRules(); 
      } 
      catch (Exception ex) 
      { 
       _logDevice.LogSrvMessage(1, "ExchangeLiteService: ImpersonateUser: failed to validate the impersonation for {0}\n Exception: {1}\n", userSmtp, ex.Message); 
       int hr = System.Runtime.InteropServices.Marshal.GetHRForException(ex); 

       if (hr == -2146233088) // We do not have right to impersonate this user. 
       { 
        result = null; 
        return result; 
       } 
       else 
       { 
        _logDevice.LogSrvMessage(1, "ExchangeLiteService: ImpersonateUser(2): trying to resolve {0} with Autodiscover instead...", userSmtp); 
        result = ImpersonateUser(userSmtp, enableTrace, exchangeVersion); 
       } 

      } 

      log += "8/8 Adding the service \n"; 
      if (!Services.ContainsKey(userSmtp)) 
      { 
       Services.Add(userSmtp, service); 
       _logDevice.LogSrvMessage(1, "ExchangeLiteService: ImpersonateUser(2): {0} has been impersonated\n", service.ImpersonatedUserId.Id); 
      } 
     } 
     catch (Exception ex) 
     { 
      _logDevice.LogSrvMessage(1, "ExchangeLiteService: ImpersonateUser(2): exception {0}\n The exception occured after the following steps: \n{1}", ex.Message, log); 
     } 
     return result; 
    } 

А вот код, который вызывает предыдущую функцию (т.е. для всех пользователей) положить в виду, что вы должны каким-то образом хранящих адреса электронной почты для каждого счета вы хотите выдать себя.

/// <summary> 
     /// To Impersonate users in order to get the info from them. 
     /// </summary> 
     /// <param name="userSmtps">List of users to be impersonated</param> 
     /// <param name="enableTrace"> To enable logging from the XML tracing</param> 
     /// <param name="exchangeVersion">Exchange server version used </param> 
     public void ImpersonateUsers(ICollection<string> userSmtps) 
     { 
      var log = "ImpersonateUsers\n"; 
      var firstUserSmtp = ""; 
      if (userSmtps != null) 

       if (userSmtps.Count > 0) 
       { 

        //the url for the first smtp 
        try 
        { 
         log += "1/2 Impersonating the first userSmtp\n"; 
         _logDevice.LogSrvMessage(1, "ExchangeLiteService: ImpersonateUsers: Getting the Url from the autodiscovery for the first smtp {0} ", userSmtps.First()); 
         bool enableTrace = Services.First().Value.TraceEnabled; 

         ExchangeVersion exchangeVersion = Services.First().Value.RequestedServerVersion; 
         firstUserSmtp = userSmtps.First(); 
         var commonSmtpUrl = ImpersonateUser(userSmtps.First(), enableTrace, exchangeVersion); 
         if (commonSmtpUrl == null) userSmtps.Remove(firstUserSmtp); 
         // If the list contains other than the first one 
         log += "2/2 Impersonating " + (userSmtps.Count - 1) + " userSmtps\n"; 

         if (userSmtps.Count >= 1) 
         { 
          foreach (var userSmtp in userSmtps) 
          { 
           try 
           { //skip ther first one because it is already impersonated. 
            if (userSmtp == firstUserSmtp) 
            { 
             continue; 
            } 
            // Impersonate the users 
            _logDevice.LogSrvMessage(1, "ExchangeLiteService: ImpersonateUsers: Impersonating {0} ...", userSmtp); 

             commonSmtpUrl = ImpersonateUser(userSmtp, enableTrace, exchangeVersion); 

           } 
           catch (Exception ex) 
           { 
            _logDevice.LogSrvMessage(1, "ExchangeLiteService: ImpersonateUsers: Impersonating {1}\n exception {0}\n", ex.Message, userSmtp); 
           } 
          } 
         } 
        } 
        catch (Exception ex) 
        { 
         _logDevice.LogSrvMessage(1, "ExchangeLiteService: ImpersonateUsers: exception {0}\n The exception occured after the following steps: \n{1}", ex.Message, log); 
        } 
       } 
     } 

Я бы поставил подписную часть и добавление к соединению, но это немного уродливые и трудно получить. но идея заключается просто в том, что у вас должно быть соединение, а затем вы переходите к каждой созданной вами службе, а затем к `connection.AddSubscription (streamingSubscription); Где потоковая подписка извлекается из службы.

+0

Спасибо, что здорово! Можете ли вы немного разобраться ...Поэтому я получаю план олицетворения таким образом, что вы жестко скопируете учетные данные учетной записи приложения и передаете учетную запись электронной почты, которую вы выдаете. Как вы занимаетесь созданием второго, третьего, 100-го соединения? Сделайте все подписки каким-то образом, как часть 1 соединения? Большое спасибо, Andy – mcinnes01

+0

да, вы поняли, все подписки идут в одно и то же соединение, я изменил ответ и поместил части своего кода. Я не установил код соединений, потому что он уродлив: D в любом случае я описал, как я думал об этом. ПРЕДУПРЕЖДЕНИЕ. Я не знаю, является ли это рекомендуемым способом или насколько он безопасен, но, по крайней мере, он работает и выполняет свою работу. – BraveHeart

+0

Спасибо BraveHeart, это здорово, мне нужно настроить учетную запись олицетворения, поэтому я пойду и дам вам знать, как только у меня получится. – mcinnes01

Смежные вопросы