/// <summary>
        /// Gets the sharing information for the specified ContentItem which includes the groups
        /// the item is shared with and overall access permission (public/non public).
        /// </summary>
        public void GetSharingInfo(ContentItem item, EventHandler <SharingInfoEventArgs> callback)
        {
            if (_agol.User.Current == null)
            {
                if (callback != null)
                {
                    callback(null, new SharingInfoEventArgs());
                }
                return;
            }

            //find out if the item is located in a folder
            //
            GetFolder(item, (object sender, RequestEventArgs e) =>
            {
                if (e.Error != null)
                {
                    if (callback != null)
                    {
                        callback(null, new SharingInfoEventArgs()
                        {
                            Error = e.Error
                        });
                    }
                    return;
                }

                string folderUrl = ContentFolder.IsSubfolder(item.Folder) ? "/" + item.Folder.Id : "";
                string url       = _agol.Url + "content/users/" + _agol.User.Current.Username + folderUrl + "/items/" + item.Id + "?f=json&token=" + _agol.User.Token;

                // add a bogus parameter to avoid the caching that happens with the WebClient
                //
                url += "&tickCount=" + Environment.TickCount.ToString();

                WebUtil.OpenReadAsync(url, null, (sender2, e2) =>
                {
                    if (e2.Error != null)
                    {
                        if (callback != null)
                        {
                            callback(null, new SharingInfoEventArgs()
                            {
                                Error = e2.Error
                            });
                        }
                        return;
                    }

                    UserItem userItem = WebUtil.ReadObject <UserItem>(e2.Result);

                    if (callback != null)
                    {
                        callback(null, new SharingInfoEventArgs()
                        {
                            SharingInfo = (item == null) ? null : userItem.Sharing, Item = (item == null) ? null : userItem.ContentItem
                        });
                    }
                });
            });
        }
        /// <summary>
        /// Gets the content of the current user.
        /// <remarks>
        /// If folderId is null gets the content from the root level, otherwise the content in the specified folder.
        /// </remarks>
        /// </summary>
        /// <param name="folderId">The id of the folder to retrive content from. If null the root level content is retrieved.</param>
        /// <param name="callback"></param>
        void GetUserContent(string folderId, EventHandler <UserContentEventArgs> callback)
        {
            string url = _agol.Url + "content/users/" + _agol.User.Current.Username + (string.IsNullOrEmpty(folderId) ? "" : "/" + folderId) + "?f=json&token=" + _agol.User.Token;

            // add a bogus parameter to avoid the caching that happens with the WebClient
            //
            url += "&tickCount=" + Environment.TickCount.ToString();

            WebUtil.OpenReadAsync(url, null, (sender, e) =>
            {
                if (e.Error != null)
                {
                    callback(null, new UserContentEventArgs()
                    {
                        Error = e.Error
                    });
                    return;
                }

                UserContent userContent = WebUtil.ReadObject <UserContent>(e.Result);
                callback(null, new UserContentEventArgs()
                {
                    Content = userContent
                });
            });
        }
Пример #3
0
        /// <summary>
        /// Retrieves a SubLayerDescription asynchronously for the specified url.
        /// </summary>
        public static void GetServiceInfoAsync(string url, EventHandler <SubLayerEventArgs> callback, string proxyUrl = null)
        {
            WebUtil.OpenReadAsync(new Uri(url + "?f=json"), null, (sender, e) =>
            {
                SubLayerDescription description = WebUtil.ReadObject <SubLayerDescription>(e.Result);
                description.RequiresProxy       = e.UsedProxy;

                // remove the geometry field
                //
                if (description.Fields != null)
                {
                    List <SubLayerField> fields = new List <SubLayerField>();
                    foreach (SubLayerField field in description.Fields)
                    {
                        if (field.Type != "esriFieldTypeGeometry" && field.Type != "Microsoft.SqlServer.Types.SqlGeometry")//exclude shape field from AGS and SDS v1.x
                        {
                            fields.Add(field);
                        }
                    }

                    description.Fields = fields.ToArray();
                }

                description.Url = url;

                callback(null, new SubLayerEventArgs()
                {
                    Description = description
                });
            });
        }
        /// <summary>
        /// Get all the related items of a certain relationship type for that item.
        /// An optional direction can be specified if the direction of the relationship is ambiguous. Otherwise the
        /// service will try to infer it.
        /// </summary>
        /// <param name="itemId"></param>
        /// <param name="relationshipType">The type of relationship between the two items.</param>
        /// <param name="direction">The direction of the relationship. Either 'forward' (from origin -> destination) or 'reverse' (from destination -> origin). </param>
        /// <param name="callback"></param>
        public void GetRelatedItems(string itemId, string relationshipType, string direction, EventHandler <ContentItemsEventArgs> callback)
        {
            string url = _agol.Url + "content/items/" + itemId + "/relatedItems?relationshipType=" + relationshipType + "&direction=" + direction + "&f=json";

            if (_agol.User.Current != null)
            {
                url += "&token=" + _agol.User.Token;
            }

            // add a bogus parameter to avoid the caching that happens with the WebClient
            //
            url += "&tickCount=" + Environment.TickCount.ToString();

            WebUtil.OpenReadAsync(url, null, (sender, e) =>
            {
                if (e.Error != null)
                {
                    if (callback != null)
                    {
                        callback(null, new ContentItemsEventArgs()
                        {
                            Error = e.Error
                        });
                    }
                    return;
                }

                RelatedItemsResult result = WebUtil.ReadObject <RelatedItemsResult>(e.Result);

                if (result != null && result.RelatedItems != null)
                {
                    // setup the thumbnails for each result
                    //
                    foreach (ContentItem item in result.RelatedItems)
                    {
                        if (item.ThumbnailPath != null)
                        {
                            string thumbnailUrl = _agol.Url + "content/items/" + item.Id + "/info/" + item.ThumbnailPath;
                            if (_agol.User.Current != null)
                            {
                                thumbnailUrl += "?token=" + _agol.User.Token;
                            }

                            item.Thumbnail = new BitmapImage(new Uri(thumbnailUrl));
                        }
                    }
                }

                if (callback != null)
                {
                    callback(null, new ContentItemsEventArgs()
                    {
                        Items = (result == null) ? null : result.RelatedItems
                    });
                }
            });
        }
Пример #5
0
        /// <summary>
        /// Gets information about the specified user.
        /// </summary>
        private void GetUser(string username, string token, EventHandler <GetUserEventArgs> callback)
        {
            string url = _agol.Url + "community/users/" + username + "?f=json";

            if (!string.IsNullOrEmpty(token))
            {
                url += "&token=" + token;
            }

            // add a bogus parameter to avoid the caching that happens with the WebClient
            //
            url += "&tickCount=" + Environment.TickCount.ToString();

            WebUtil.OpenReadAsync(url, null, (sender, e) =>
            {
                if (e.Error != null)
                {
                    if (callback != null)
                    {
                        callback(this, new GetUserEventArgs()
                        {
                            Error = e.Error
                        });
                    }
                    return;
                }

                User user = WebUtil.ReadObject <User>(e.Result);

                //setup the group thumbnails
                //
                if (user.Groups != null)
                {
                    foreach (Group group in user.Groups)
                    {
                        if (group.ThumbnailPath != null)
                        {
                            string thumbnailUrl = _agol.Url + "community/groups/" + group.Id + "/info/" + group.ThumbnailPath;
                            if (!string.IsNullOrEmpty(token))
                            {
                                thumbnailUrl += "?token=" + token;
                            }
                            group.Thumbnail = new BitmapImage(new Uri(thumbnailUrl));
                        }
                    }
                }

                if (callback != null)
                {
                    callback(null, new GetUserEventArgs()
                    {
                        User = user
                    });
                }
            });
        }
        public void Initialize(string url, string urlSecure, bool forceBrowserAuth = false, bool signOutCurrentUser = false)
        {
            _isInitialized      = false;
            InitializationError = null;

            if (User != null && signOutCurrentUser)
            {
                m_ignoreSignInOut = true;
                User.SignOut();
                removePortalCredentials(Url);
                m_ignoreSignInOut = false;
            }

            var oldUrl        = Url;
            var oldUrlSecure  = UrlSecure;
            var oldPortalInfo = PortalInfo;

            Url        = url;
            UrlSecure  = urlSecure;
            PortalInfo = null;

            // Initialize PortalInfo
            string portalInfoUrl = string.Format("{0}/{1}?f=json&culture={2}", url, "accounts/self",
                                                 System.Threading.Thread.CurrentThread.CurrentUICulture.ToString());

            if (!string.IsNullOrEmpty(User.Token))
            {
                portalInfoUrl += "&token=" + User.Token;
            }

            WebUtil.OpenReadAsync(portalInfoUrl + "&r=" + DateTime.Now.Ticks, null, (o, e) =>
            {
                if (e.Error == null && e.Result != null)
                {
                    PortalInfo = WebUtil.ReadObject <PortalInfo>(e.Result);
                    if (PortalInfo != null && PortalInfo.User != null &&
                        !string.IsNullOrEmpty(PortalInfo.User.UserName) &&
                        string.IsNullOrEmpty(User.Token))
                    {
                        initBrowserAuthenticatedUser(portalInfoUrl, PortalInfo.User.UserName);
                    }
                }
                else
                {
                    Url                 = oldUrl;
                    UrlSecure           = oldUrlSecure;
                    PortalInfo          = oldPortalInfo;
                    InitializationError = e.Error;
                }

                // Fire initialized event
                _isInitialized = true;
                OnInitialized();
            }, forceBrowserAuth);
        }
Пример #7
0
        /// <summary>
        /// Gets the tags for the current user.
        /// </summary>
        public void GetTags(EventHandler <UserTagEventArgs> callback)
        {
            if (Current == null)
            {
                if (callback != null)
                {
                    callback(null, new UserTagEventArgs()
                    {
                        Error = new Exception(ESRI.ArcGIS.Mapping.Controls.ArcGISOnline.Resources.Strings.ExceptionNoUserSignedIn)
                    });
                }
                return;
            }

            string userName = Current.Username;
            string url      = _agol.Url + "community/users/" + userName + "/tags?f=json&token=" + Token;

            // add a bogus parameter to avoid the caching that happens with the WebClient
            //
            url += "&tickCount=" + Environment.TickCount.ToString();

            WebUtil.OpenReadAsync(url, null, (sender, e) =>
            {
                if (e.Error != null)
                {
                    if (callback != null)
                    {
                        callback(this, new UserTagEventArgs()
                        {
                            Error = e.Error
                        });
                    }
                    return;
                }

                Tags result = WebUtil.ReadObject <Tags>(e.Result);

                if (callback != null && result != null && result.UserTags != null)
                {
                    callback(null, new UserTagEventArgs()
                    {
                        UserTags = result.UserTags
                    });
                }
                else if (callback != null)
                {
                    callback(null, new UserTagEventArgs()
                    {
                        Error = new Exception(string.Format(ESRI.ArcGIS.Mapping.Controls.ArcGISOnline.Resources.Strings.ExceptionFailedToRetrieveTagForUser, userName))
                    });
                }
            });
        }
        /// <summary>
        /// Gets the join applications for the specified group.
        /// </summary>
        public void GetApplications(string groupId, EventHandler <GroupApplicationEventArgs> callback)
        {
            if (_agol.User.Current == null)
            {
                if (callback != null)
                {
                    callback(null, new GroupApplicationEventArgs()
                    {
                        Error = new Exception(ESRI.ArcGIS.Mapping.Controls.ArcGISOnline.Resources.Strings.ExceptionNoUserSignedIn)
                    });
                }
                return;
            }

            string url = _agol.Url + "community/groups/" + groupId + "/applications?f=json&token=" + _agol.User.Token;

            // add a bogus parameter to avoid the caching that happens with the WebClient
            //
            url += "&tickCount=" + Environment.TickCount.ToString();

            WebUtil.OpenReadAsync(url, null, (sender, e) =>
            {
                if (e.Error != null)
                {
                    if (callback != null)
                    {
                        callback(null, new GroupApplicationEventArgs()
                        {
                            Error = e.Error
                        });
                    }
                    return;
                }

                GroupApplications result = WebUtil.ReadObject <GroupApplications>(e.Result);

                if (callback != null && result != null && result.Applications != null)
                {
                    callback(null, new GroupApplicationEventArgs()
                    {
                        Applications = result.Applications
                    });
                }
                else if (callback != null)
                {
                    callback(null, new GroupApplicationEventArgs()
                    {
                        Error = new Exception(string.Format(ESRI.ArcGIS.Mapping.Controls.ArcGISOnline.Resources.Strings.ExceptionFailedToGetGroupApplicationsForGroup, groupId))
                    });
                }
            });
        }
Пример #9
0
 public static void LoadConfig(Uri uri, EventHandler callback)
 {
     WebUtil.OpenReadAsync(uri, null, (sender2, e2) =>
     {
         if (e2.Error != null)
         {
             return;
         }
         XDocument xml = XDocument.Load(e2.Result);
         XElement el   = xml.Element("Configuration");
         LoadConfig(el, callback);
     });
 }
        /// <summary>
        /// Retrieves the group specified by its Id.
        /// </summary>
        public void GetGroup(string groupId, EventHandler <GroupEventArgs> callback)
        {
            string url = _agol.Url + "community/groups/" + groupId + "?f=json";

            if (_agol.User.Current != null)
            {
                url += "&token=" + _agol.User.Token;
            }

            // add a bogus parameter to avoid the caching that happens with the WebClient
            //
            url += "&tickCount=" + Environment.TickCount.ToString();

            WebUtil.OpenReadAsync(url, null, (sender, e) =>
            {
                if (e.Error != null)
                {
                    if (callback != null)
                    {
                        callback(null, new GroupEventArgs()
                        {
                            Error = e.Error
                        });
                    }
                    return;
                }

                Group group = WebUtil.ReadObject <Group>(e.Result);

                // setup the thumbnails for the group
                //
                if (group.ThumbnailPath != null)
                {
                    string thumbnailUrl = _agol.Url + "community/groups/" + group.Id + "/info/" + group.ThumbnailPath + "?tickCount=" + Environment.TickCount.ToString();;
                    if (_agol.User.Current != null)
                    {
                        thumbnailUrl += "&token=" + _agol.User.Token;
                    }

                    group.Thumbnail = new BitmapImage(new Uri(thumbnailUrl));
                }

                if (callback != null)
                {
                    callback(null, new GroupEventArgs()
                    {
                        Group = group
                    });
                }
            });
        }
        /// <summary>
        /// Retrieves the comments for the specified content item.
        /// </summary>
        public void GetComments(string itemId, EventHandler <CommentEventArgs> callback)
        {
            string url = _agol.Url + "content/items/" + itemId + "/comments?f=json";

            if (_agol.User.Current != null)
            {
                url += "&token=" + _agol.User.Token;
            }

            // add a bogus parameter to avoid the caching that happens with the WebClient
            //
            url += "&tickCount=" + Environment.TickCount.ToString();

            WebUtil.OpenReadAsync(url, null, (sender, e) =>
            {
                if (e.Error != null)
                {
                    if (callback != null)
                    {
                        callback(this, new CommentEventArgs()
                        {
                            Error = e.Error
                        });
                    }
                    return;
                }

                ItemComments result = WebUtil.ReadObject <ItemComments>(e.Result);

                if (callback != null)
                {
                    if (result != null)
                    {
                        callback(null, new CommentEventArgs()
                        {
                            Comments = result.Comments
                        });
                    }
                    else
                    {
                        callback(null, new CommentEventArgs()
                        {
                            Error = new Exception(ESRI.ArcGIS.Mapping.Controls.ArcGISOnline.Resources.Strings.ExceptionGetCommentsFailed)
                        });
                    }
                }
            });
        }
Пример #12
0
        /// <summary>
        /// Performs a search for users using the specified query and startIndex.
        /// </summary>
        /// <param name="query"></param>
        /// <param name="startIndex">The index of the starting result for paging.</param>
        /// <param name="maxCount"></param>
        /// <param name="callback"></param>
        public void Search(string query, int startIndex, int maxCount, EventHandler <UserSearchEventArgs> callback)
        {
            string url = _agol.Url + "community/users?start=startIndex&num=maxCount&q=" + query + "&f=json";

            if (_agol.User.Current != null)
            {
                url += "&token=" + _agol.User.Token;
            }

            // add a bogus parameter to avoid the caching that happens with the WebClient
            //
            url += "&tickCount=" + Environment.TickCount.ToString();

            WebUtil.OpenReadAsync(url, callback, (sender, e) =>
            {
                SearchCompleted(e, callback);
            });
        }
        /// <summary>
        /// Performs a search for content using the specified query and startIndex.
        /// </summary>
        /// <param name="query"></param>
        /// <param name="startIndex">The index of the starting result for paging.</param>
        /// <param name="maxCount"></param>
        /// <param name="callback"></param>
        public void Search(string query, string sort, int startIndex, int maxCount, EventHandler <ContentSearchEventArgs> callback)
        {
            string url = _agol.Url + "search?q=" + query + sort + "&f=json&start=" + startIndex.ToString() + "&num=" + maxCount.ToString();

            if (_agol.User.Current != null)
            {
                url += "&token=" + _agol.User.Token;
            }

            // add a bogus parameter to avoid the caching that happens with the WebClient
            //
            url += "&tickCount=" + Environment.TickCount.ToString();

            WebUtil.OpenReadAsync(url, callback, (sender, e) =>
            {
                SearchCompleted(e, sort, callback);
            });
        }
        /// <summary>
        /// Performs a search for groups using the specified query.
        /// </summary>
        public void Search(string query, EventHandler <GroupSearchEventArgs> callback)
        {
            string url = _agol.Url + "community/groups?q=" + query + "&sortField=title&f=json&num=12";

            if (_agol.User.Current != null)
            {
                url += "&token=" + _agol.User.Token;
            }

            // add a bogus parameter to avoid the caching that happens with the WebClient
            //
            url += "&tickCount=" + Environment.TickCount.ToString();

            WebUtil.OpenReadAsync(url, null, (sender, e) =>
            {
                SearchCompleted(e, callback);
            });
        }
        /// <summary>
        /// Gets the members of the specified group.
        /// </summary>
        public void GetMembers(string groupId, EventHandler <GroupMembersEventArgs> callback)
        {
            string url = _agol.Url + "community/groups/" + groupId + "/users?f=json";

            if (_agol.User.Current != null)
            {
                url += "&token=" + _agol.User.Token;
            }

            // add a bogus parameter to avoid the caching that happens with the WebClient
            //
            url += "&tickCount=" + Environment.TickCount.ToString();

            WebUtil.OpenReadAsync(url, null, (sender, e) =>
            {
                if (e.Error != null)
                {
                    if (callback != null)
                    {
                        callback(this, new GroupMembersEventArgs()
                        {
                            Error = e.Error
                        });
                    }
                    return;
                }

                GroupMembers result = WebUtil.ReadObject <GroupMembers>(e.Result);

                if (callback != null)
                {
                    callback(null, new GroupMembersEventArgs()
                    {
                        GroupMembers = result
                    });
                }
            });
        }
        /// <summary>
        /// Gets the service information for a MapService asynchronously.
        /// </summary>
        public static void GetServiceInfoAsync(string url, object userState, EventHandler <ServiceEventArgs> callback)
        {
            WebUtil.OpenReadAsync(new Uri(url + "?f=json"), null, (sender, e) =>
            {
                if (e.Error != null)
                {
                    callback(null, new ServiceEventArgs());
                    return;
                }

                MapService mapService = WebUtil.ReadObject <MapService>(e.Result);
                if (mapService != null && mapService.Name != null && mapService.Units != null)
                {
                    mapService.Url           = url;
                    mapService.RequiresProxy = e.UsedProxy;
                    mapService.InitTitle();
                    callback(null, new ServiceEventArgs()
                    {
                        Service = mapService, UserState = userState
                    });
                    return;
                }

                FeatureService featureService = WebUtil.ReadObject <FeatureService>(e.Result);
                if (featureService != null && featureService.Layers != null && featureService.Layers.Length > 0)
                {
                    featureService.Url           = url;
                    featureService.RequiresProxy = e.UsedProxy;
                    featureService.InitTitle();
                    callback(null, new ServiceEventArgs()
                    {
                        Service = featureService, UserState = userState
                    });
                    return;
                }

                ImageService imageService = WebUtil.ReadObject <ImageService>(e.Result);
                if (imageService != null && imageService.PixelType != null)
                {
                    imageService.Url           = url;
                    imageService.RequiresProxy = e.UsedProxy;
                    imageService.InitTitle();
                    callback(null, new ServiceEventArgs()
                    {
                        Service = imageService, UserState = userState
                    });
                    return;
                }

                FeatureLayerService featureLayerService = WebUtil.ReadObject <FeatureLayerService>(e.Result);
                if (featureLayerService != null && featureLayerService.Type == "Feature Layer")
                {
                    featureLayerService.Url           = url;
                    featureLayerService.RequiresProxy = e.UsedProxy;
                    featureLayerService.Title         = featureLayerService.Name;
                    callback(null, new ServiceEventArgs()
                    {
                        Service = featureLayerService, UserState = userState
                    });
                    return;
                }

                callback(null, new ServiceEventArgs());
            });
        }
Пример #17
0
        /// <summary>
        /// Initiates sign-in based on the username and token stored in user settings.
        /// </summary>
        public void SignInFromLocalStorage(EventHandler <RequestEventArgs> callback)
        {
            string username = null;
            string token    = null;

            // see if the browser cookie is present
            //
            string cookie = WebUtil.GetCookie("esri_auth");

            if (cookie != null)
            {
                cookie = HttpUtility.UrlDecode(cookie);
                CachedSignIn signIn = WebUtil.ReadObject <CachedSignIn>(new MemoryStream(Encoding.UTF8.GetBytes(cookie)));
                username = signIn.Email;
                token    = signIn.Token;
            }

            if (username != null && token != null)
            {
                string url = _agol.Url + "community/users/" + username + "?token=" + token + "&f=json";
                WebUtil.OpenReadAsync(url, null, (sender, e) =>
                {
                    if (e.Error != null) // bail on error
                    {
                        if (callback != null)
                        {
                            callback(null, new RequestEventArgs()
                            {
                                Error = e.Error
                            });
                        }
                        return;
                    }

                    User cachedUser = WebUtil.ReadObject <User>(e.Result);

                    if (cachedUser != null && !string.IsNullOrEmpty(cachedUser.Username))
                    {
                        // Add credential to IdentityManager
                        if (!string.IsNullOrEmpty(token) && !string.IsNullOrEmpty(username) &&
                            IdentityManager.Current != null &&
                            IdentityManager.Current.FindCredential(_agol.Url, username) == null)
                        {
                            IdentityManager.Credential cred = new IdentityManager.Credential()
                            {
                                UserName = username,
                                Url      = _agol.Url,
                                Token    = token
                            };
                            IdentityManager.Current.AddCredential(cred);
                        }

                        Current = cachedUser;
                        Token   = token;
                    }
                    else
                    {
                        Current = null;
                        Token   = null;
                    }

                    if (callback != null) // notify caller of success
                    {
                        callback(null, new RequestEventArgs());
                    }

                    if (SignedInOut != null)
                    {
                        SignedInOut(null, EventArgs.Empty);
                    }
                });
            }
            else if (callback != null)
            {
                callback(null, new RequestEventArgs()); // call the client back in any case
            }
        }
Пример #18
0
        private void getGroups(EventHandler <GroupsEventArgs> callback, bool publicOnly)
        {
            if (Current == null)
            {
                if (callback != null)
                {
                    callback(null, new GroupsEventArgs()
                    {
                        Error = new Exception(ESRI.ArcGIS.Mapping.Controls.ArcGISOnline.Resources.Strings.ExceptionNoUserSignedIn)
                    });
                }
                return;
            }

            string accountId = Current.AccountId;

            string url = null;

            if (publicOnly)
            {
                url = _agol.Url + "community/groups?q=(accountid:" + accountId + "%20AND%20(access:public))&sortField=title&sortOrder=asc&start=1&num=100&f=json&token=" + Token;
            }
            else
            {
                url = _agol.Url + "community/groups?q=(accountid:" + accountId + "%20AND%20(access:account%20||%20access:public))&sortField=title&sortOrder=asc&start=1&num=100&f=json&token=" + Token;
            }

            // add a bogus parameter to avoid the caching that happens with the WebClient
            //
            url += "&tickCount=" + Environment.TickCount.ToString();

            WebUtil.OpenReadAsync(url, null, (sender, e) =>
            {
                if (e.Error != null)
                {
                    if (callback != null)
                    {
                        callback(this, new GroupsEventArgs()
                        {
                            Error = e.Error
                        });
                    }
                    return;
                }

                GroupResults result = WebUtil.ReadObject <GroupResults>(e.Result);

                if (callback != null && result != null && result.Groups != null)
                {
                    callback(null, new GroupsEventArgs()
                    {
                        Groups = result.Groups
                    });
                }
                else if (callback != null)
                {
                    callback(null, new GroupsEventArgs()
                    {
                        Error = new Exception(ESRI.ArcGIS.Mapping.Controls.ArcGISOnline.Resources.Strings.ExceptionFailedToRetrieveOrgGroups)
                    });
                }
            });
        }
        /// <summary>
        /// Retrieves the ContentItem specified by its Id.
        /// </summary>
        /// <param name="itemId"></param>
        /// <param name="useCachedThumbnail">
        /// Specifies if the thumbnail from the cache can be
        /// reused if the thumbnail is already cached.
        /// </param>
        /// <param name="callback"></param>
        public void GetItem(string itemId, EventHandler <ContentItemEventArgs> callback)
        {
            string url = _agol.Url + "content/items/" + itemId + "?f=json";

            if (_agol.User.Current != null)
            {
                url += "&token=" + _agol.User.Token;
            }

            // add a bogus parameter to avoid the caching that happens with the WebClient
            //
            url += "&tickCount=" + Environment.TickCount.ToString();

            WebUtil.OpenReadAsync(url, null, (sender, e) =>
            {
                if (e.Error != null)
                {
                    if (callback != null)
                    {
                        callback(this, new ContentItemEventArgs()
                        {
                            Error = e.Error, Id = itemId
                        });
                    }
                    return;
                }

                ContentItem item = WebUtil.ReadObject <ContentItem>(e.Result);

                // did the request succeed with a valid item?
                //
                if (item.Id == null)
                {
                    if (callback != null)
                    {
                        callback(this, new ContentItemEventArgs()
                        {
                            Error = new Exception("Invalid identifier or access denied."), Id = itemId
                        });
                    }
                    return;
                }

                // setup the thumbnail
                if (item.ThumbnailPath != null)
                {
                    string thumbnailUrl = _agol.Url + "content/items/" + item.Id + "/info/" + item.ThumbnailPath + "?tickCount=" + Environment.TickCount.ToString();
                    if (_agol.User.Current != null)
                    {
                        thumbnailUrl += "&token=" + _agol.User.Token;
                    }

                    item.Thumbnail = new BitmapImage(new Uri(thumbnailUrl));
                }

                if (callback != null)
                {
                    callback(this, new ContentItemEventArgs()
                    {
                        Item = item
                    });
                }
            });
        }