public SortUserViewModel(SortUserState sortOrder)
        {
            UserNameSort           = sortOrder == SortUserState.UserNameAsc ? SortUserState.UserNameDesc : SortUserState.UserNameAsc;
            EmailSort              = sortOrder == SortUserState.EmailAsc ? SortUserState.EmailDesc : SortUserState.EmailAsc;
            ConfirmEmailSort       = sortOrder == SortUserState.ConfirmEmailAsc ? SortUserState.ConfirmEmailDesc : SortUserState.ConfirmEmailAsc;
            PhoneNumberSort        = sortOrder == SortUserState.PhoneNumberAsc ? SortUserState.PhoneNumberDesc : SortUserState.PhoneNumberAsc;
            ConfirmPhoneNumberSort = sortOrder == SortUserState.ConfirmPhoneNumberAsc ? SortUserState.ConfirmPhoneNumberDesc : SortUserState.ConfirmPhoneNumberAsc;
            TwoFaSort              = sortOrder == SortUserState.TwoFaAsc ? SortUserState.TwoFaDesc : SortUserState.TwoFaAsc;
            LockoutEndSort         = sortOrder == SortUserState.LockoutEndAsc ? SortUserState.LockoutEndDesc : SortUserState.LockoutEndAsc;
            LockoutEnabledSort     = sortOrder == SortUserState.LockoutEnabledAsc ? SortUserState.LockoutEnabledDesc : SortUserState.LockoutEnabledAsc;
            AccessFailedCountSort  = sortOrder == SortUserState.AccessFailedCountAsc ? SortUserState.AccessFailedCountDesc : SortUserState.AccessFailedCountAsc;

            Current = sortOrder;
        }
        public async Task <IActionResult> Users(string email, int page  = 1,
                                                SortUserState sortOrder = SortUserState.UserNameAsc)
        {
            // NOTE: сначала надо выполнить фильтрацию, потом сортировку и в конце пагинацию
            const int pageSize = 3;

            // Фильтрация, он же поиск
            IEnumerable <User> users = await _userManager.Users.ToListAsync();

            if (!string.IsNullOrWhiteSpace(email))
            {
                users = users
                        .AsParallel()
                        .WithDegreeOfParallelism(System.Environment.ProcessorCount)
                        .Where(u => u.Email.Contains(email));
            } // if

            // Сортировка
            switch (sortOrder)
            {
            case SortUserState.UserNameDesc:
                users = users
                        .AsParallel()
                        .WithDegreeOfParallelism(System.Environment.ProcessorCount)
                        .OrderByDescending(s => s.UserName);
                break;

            case SortUserState.EmailAsc:
                users = users
                        .AsParallel()
                        .WithDegreeOfParallelism(System.Environment.ProcessorCount)
                        .OrderBy(s => s.Email);
                break;

            case SortUserState.EmailDesc:
                users = users
                        .AsParallel()
                        .WithDegreeOfParallelism(System.Environment.ProcessorCount)
                        .OrderByDescending(s => s.Email);
                break;

            case SortUserState.ConfirmEmailAsc:
                users = users
                        .AsParallel()
                        .WithDegreeOfParallelism(System.Environment.ProcessorCount)
                        .OrderBy(s => s.EmailConfirmed);
                break;

            case SortUserState.ConfirmEmailDesc:
                users = users
                        .AsParallel()
                        .WithDegreeOfParallelism(System.Environment.ProcessorCount)
                        .OrderByDescending(s => s.EmailConfirmed);
                break;

            case SortUserState.PhoneNumberAsc:
                users = users
                        .AsParallel()
                        .WithDegreeOfParallelism(System.Environment.ProcessorCount)
                        .OrderBy(s => s.PhoneNumber);
                break;

            case SortUserState.PhoneNumberDesc:
                users = users
                        .AsParallel()
                        .WithDegreeOfParallelism(System.Environment.ProcessorCount)
                        .OrderByDescending(s => s.PhoneNumber);
                break;

            case SortUserState.ConfirmPhoneNumberAsc:
                users = users
                        .AsParallel()
                        .WithDegreeOfParallelism(System.Environment.ProcessorCount)
                        .OrderBy(s => s.PhoneNumberConfirmed);
                break;

            case SortUserState.ConfirmPhoneNumberDesc:
                users = users
                        .AsParallel()
                        .WithDegreeOfParallelism(System.Environment.ProcessorCount)
                        .OrderByDescending(s => s.PhoneNumberConfirmed);
                break;

            case SortUserState.TwoFaAsc:
                users = users
                        .AsParallel()
                        .WithDegreeOfParallelism(System.Environment.ProcessorCount)
                        .OrderBy(s => s.TwoFactorEnabled);
                break;

            case SortUserState.TwoFaDesc:
                users = users
                        .AsParallel()
                        .WithDegreeOfParallelism(System.Environment.ProcessorCount)
                        .OrderByDescending(s => s.TwoFactorEnabled);
                break;

            case SortUserState.LockoutEndAsc:
                users = users
                        .AsParallel()
                        .WithDegreeOfParallelism(System.Environment.ProcessorCount)
                        .OrderBy(s => s.LockoutEnd);
                break;

            case SortUserState.LockoutEndDesc:
                users = users
                        .AsParallel()
                        .WithDegreeOfParallelism(System.Environment.ProcessorCount)
                        .OrderByDescending(s => s.LockoutEnd);
                break;

            case SortUserState.LockoutEnabledAsc:
                users = users
                        .AsParallel()
                        .WithDegreeOfParallelism(System.Environment.ProcessorCount)
                        .OrderBy(s => s.LockoutEnabled);
                break;

            case SortUserState.LockoutEnabledDesc:
                users = users
                        .AsParallel()
                        .WithDegreeOfParallelism(System.Environment.ProcessorCount)
                        .OrderByDescending(s => s.LockoutEnabled);
                break;

            case SortUserState.AccessFailedCountAsc:
                users = users
                        .AsParallel()
                        .WithDegreeOfParallelism(System.Environment.ProcessorCount)
                        .OrderBy(s => s.AccessFailedCount);
                break;

            case SortUserState.AccessFailedCountDesc:
                users = users
                        .AsParallel()
                        .WithDegreeOfParallelism(System.Environment.ProcessorCount)
                        .OrderByDescending(s => s.AccessFailedCount);
                break;

            default:
                users = users
                        .AsParallel()
                        .WithDegreeOfParallelism(System.Environment.ProcessorCount)
                        .OrderBy(s => s.UserName);
                break;
            } // switch

            // Пагинация
            var count = users.Count();
            var items = users
                        .Skip((page - 1) * pageSize)
                        .Take(pageSize)
                        .ToList();

            var viewModel = new UsersListViewModel {
                PageViewModel       = new PageViewModel(count, page, pageSize),
                SortViewModel       = new SortUserViewModel(sortOrder),
                FilterUserViewModel = new FilterUserViewModel(email),
                Users = items
            };

            return(View(viewModel));
        }