Wrong Thread.CurrentPrincipal in async WCF end-method

后端 未结 3 1619
你的背包
你的背包 2021-02-08 15:25

I have a WCF service which has its Thread.CurrentPrincipal set in the ServiceConfiguration.ClaimsAuthorizationManager.

When I implement the ser

3条回答
  •  余生分开走
    2021-02-08 16:10

    The valid approach to this is to create an extension:

    public class SLOperationContext : IExtension
    {
        private readonly IDictionary items;
    
        private static ReaderWriterLockSlim _instanceLock = new ReaderWriterLockSlim();
    
        private SLOperationContext()
        {
            items = new Dictionary();
        }
    
        public IDictionary Items
        {
            get { return items; }
        }
    
        public static SLOperationContext Current
        {
            get
            {
                SLOperationContext context = OperationContext.Current.Extensions.Find();
                if (context == null)
                {
                    _instanceLock.EnterWriteLock();
                    context = new SLOperationContext();
                    OperationContext.Current.Extensions.Add(context);
                    _instanceLock.ExitWriteLock();
                }
                return context;
            }
        }
    
        public void Attach(OperationContext owner) { }
        public void Detach(OperationContext owner) { }
    }
    

    Now this extension is used as a container for objects that you want to persist between thread switching as OperationContext.Current will remain the same.

    Now you can use this in BeginMethod1 to save current user:

    SLOperationContext.Current.Items["Principal"] = OperationContext.Current.ClaimsPrincipal;
    

    And then in EndMethod1 you can get the user by typing:

    ClaimsPrincipal principal = SLOperationContext.Current.Items["Principal"];
    

    EDIT (Another approach):

    public IAsyncResult BeginMethod1(AsyncCallback callback, object state)
    {
        var task = Task.Factory.StartNew(this.WorkerFunction, state);
    
        var ec = ExecutionContext.Capture();
    
        return task.ContinueWith(res =>
            ExecutionContext.Run(ec, (_) => callback(task), null));
    }
    

提交回复
热议问题