WorkContext currentuser is null under certain circumstance

Topics: Core
Aug 7, 2014 at 9:52 AM
Hi!
I wanted to log changes of certain entities (marked with attribute) so, I created AbstractSessionInterceptor 's descendant
to get access to entity changes. Also I want to know who did this changes, so I need to access current user, so through IWorkContextAccessor I'm creating IWorkContextScope, getting WorkContext and trying to get user, but in some cases It returns null...could this be a bug?

Here's the code:
public class ProtocolInterceptor : AbstractSessionInterceptor
    {
        private IProtocolLogger _logger;
        private readonly Type _mainAttrType = typeof(ProtocolAttribute);
        private readonly Type _fieldAttrType = typeof(ProtocolFieldAttribute);
        private readonly IWorkContextAccessor _contextAccessor;

        public ProtocolInterceptor(IWorkContextAccessor contextAccessor)
        {
            _contextAccessor = contextAccessor;
        }

        public override bool OnFlushDirty(object entity, object id, object[] currentState, object[] previousState, string[] propertyNames, NHibernate.Type.IType[] types)
        {
            var t = entity.GetType();
            var attributes = t.GetCustomAttributes(_mainAttrType, true);

            if (attributes.Length != 0)
            {
                IWorkContextScope scope = _contextAccessor.CreateWorkContextScope();
                {
                    WorkContext context = scope.WorkContext;
                    if (context != null)
                    {
                        var attr = (ProtocolAttribute)attributes.FirstOrDefault();
                        var currentDic = currentState.Select((s, i) => new { S = s, Index = i }).ToDictionary(x => x.Index, x => x.S);

                        var prvDic = previousState.Select((s, i) => new { S = s, Index = i }).ToDictionary(x => x.Index, x => x.S);

                        var diff = compare(currentDic, prvDic);

                        if (!attr.LogAllData)
                        {
                            List<string> properties = new List<string>();
                            foreach (var propety in t.GetProperties())
                            {
                                var propertyAttributes = propety.GetCustomAttributes(_fieldAttrType, true);
                                if (propertyAttributes.Length != 0)
                                    properties.Add(propety.Name);
                            }
                            if (properties.Count != 0)
                            {
                                var necesseryProps = propertyNames.Select((s, i) => new { S = s, Index = i }).Where(p => properties.Contains(p.S)).ToDictionary(x => x.Index, x => x.S);
                                TupleList<int, object, object> ToRemove = new TupleList<int, object, object>();
                                foreach (var tuple in diff)
                                {
                                    if (!necesseryProps.Keys.Contains(tuple.Item1))
                                    {
                                        ToRemove.Add(tuple);
                                    }
                                }
                                ToRemove.ForEach(d => diff.Remove(d));
                            }
                        }

                        if (diff.Count != 0)
                        {
                            _logger = ProtocolLogger.GetInstance();

                            IUser user = context.CurrentUser;
                            string propertiesFormat = GetPropertiesStringFormat(diff, propertyNames);
                            object[] param = new object[] { DateTime.Now, entity, propertyNames };

                            string entityId = string.Empty;
                            try
                            {
                                if (entity is IAuditable)
                                {
                                    entityId = ((IAuditable)entity).Id.ToString();
                                }
                            }
                            catch (Exception)
                            {
                                entityId = entity.ToString();
                            }
                            foreach (var pair in diff)
                            {
                                ProtocolPropertyInfo info = new ProtocolPropertyInfo(propertyNames[pair.Item1], Convert.ToString(pair.Item2), Convert.ToString(pair.Item3));

                                _logger.Log(user, entity, entityId, context, Operation.Write, info);
                            }
                        }
                    }
                }
            }

            return base.OnFlushDirty(entity, id, currentState, previousState, propertyNames, types);
        }

        private string GetPropertiesStringFormat(TupleList<int, object, object> diffDic, string[] propertyNames)
        {
            StringBuilder result = new StringBuilder();

            foreach (var pair in diffDic)
            {
                result.AppendFormat("Property name {0}, New value {1}, Old value {2}", propertyNames[pair.Item1], pair.Item2, pair.Item3);
            }

            return result.ToString();
        }

        private TupleList<int, object, object> compare(Dictionary<int, object> dic1, Dictionary<int, object> dic2)
        {
            var diff = new TupleList<int, object, object>();

            foreach (KeyValuePair<int, object> pair in dic1)
            {
                if (!Equals(pair.Value, dic2[pair.Key]))
                {
                    diff.Add(pair.Key, pair.Value, dic2[pair.Key]);
                }
            }

            return diff;
        }
    }
Thanks.
Aug 7, 2014 at 10:13 AM
Edited Aug 7, 2014 at 10:13 AM
CurrentUser = null if the user isn't logged in
Aug 7, 2014 at 10:17 AM
sanderg wrote:
CurrentUser = null if the user isn't logged in
But there is user logged in
Aug 7, 2014 at 10:28 AM
What do you mean by 'some cases'. What is the difference with the 'normal cases'?
Aug 7, 2014 at 11:02 AM
sanderg wrote:
What do you mean by 'some cases'. What is the difference with the 'normal cases'?
when existing entity is being edited - I'm able to access current user, when new entity is created with contentmanager current user is null.
Aug 7, 2014 at 1:04 PM
Also I find out one more problem: logger creating record instances in database, records are creating via IRepository, which i'm getting through WorkContext, repository lock's table while IWorkContextScope is not disposed, but if I dispose it orchard will not able to use WorkContext instance (in WebViewPage for example).
Aug 8, 2014 at 3:27 PM
I think I figured it out.
Current user is null only in debug mode, but real problem is that I'm getting timeout exception...
So i tryed to get user and create new record in database by openning new Nhibernate session, it worked but I'm still getting timeout exception after.
Any ideas?