我正在尝试创建一个服务来将交换通知推送到asp.net应用程序,最终使用SignalR.
我的计划是创建一个通知中心,在每个用户登录到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 + "-------------"); } } }
解决方法
我解决这个问题的方法是:
>拥有一个有权冒充所有用户的帐户.
>我通过提供用户名和帐户为该帐户创建服务
密码.
>我冒充用户并将用户的订阅添加到
连接
>我创建了另一个服务,它是主服务的关闭
相同的用户名和密码,将冒充其他用户
然后将订阅添加到同一连接
这是我的代码的两个部分.忘记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; }