コード例 #1
0
        /// <summary>
        /// Executes this request asynchronously.
        /// </summary>
        /// <returns> The async task with the type of the response. </returns>
        public virtual async Task <T> ExecuteAsync()
        {
            var response = await ExecuteUnparsedAsync().ConfigureAwait(false);

            if (OverrideRedirect)
            {
                string newLoc = string.Empty;
                foreach (var header in response.Headers)
                {
                    if (header.Key.ToLower().Equals("location"))
                    {
                        newLoc = header.Value.FirstOrDefault();
                        break;
                    }
                }
                //string newlocation = response.Headers.FirstOrDefault(stringToCheck => stringToCheck.ToString().Equals("Location")).ToString();
                return(await onRedirectAsync(newLoc).ConfigureAwait(false));
            }
            // special case to handle void or empty responses
            if (response.Content == null)
            {
                return(default(T));
            }

            string path = response.RequestMessage.RequestUri.AbsolutePath;

            if (path != null &&
                path.Contains(Constants.STR_PATH_CUSTOM_ENDPOINT) &&
                (((int)response.StatusCode) < 200 || ((int)response.StatusCode) > 302))
            {
                // Seems like only Custom Endpoint/BL would result in having a successful response
                // without having a successful status code.  The BL executed successfully, but did
                // produce a successsful outcome.
                try
                {
                    response.EnsureSuccessStatusCode();
                }
                catch (Exception ex)
                {
                    var ke = new KinveyException(
                        EnumErrorCategory.ERROR_CUSTOM_ENDPOINT,
                        EnumErrorCode.ERROR_CUSTOM_ENDPOINT_ERROR,
                        response,
                        ex
                        );
                    throw ke;
                }
            }

            if (path != null &&
                path.Contains(Constants.STR_PATH_REALTIME_STREAM) &&
                (((int)response.StatusCode) < 200 || ((int)response.StatusCode) > 302))
            {
                // Appears as though there is a stream error.  A stream error could result in having a successful response
                // without having a successful status code, such as a 401.  The request was successful, but the response
                // indicates that there is an issue with what was being requested
                try
                {
                    response.EnsureSuccessStatusCode();
                }
                catch (Exception ex)
                {
                    var ke = new KinveyException(
                        EnumErrorCategory.ERROR_REALTIME,
                        EnumErrorCode.ERROR_REALTIME_ERROR,
                        response,
                        ex
                        );
                    throw ke;
                }
            }

            if (((int)response.StatusCode) < 200 || ((int)response.StatusCode) > 302)
            {
                try
                {
                    response.EnsureSuccessStatusCode();
                }
                catch (Exception ex)
                {
                    var kinveyException = new KinveyException(
                        EnumErrorCategory.ERROR_BACKEND,
                        EnumErrorCode.ERROR_JSON_RESPONSE,
                        response,
                        ex
                        )
                    {
                        RequestID = HelperMethods.getRequestID(response)
                    };
                    throw kinveyException;
                }
            }

            string json = null;

            try
            {
                json = await response.Content.ReadAsStringAsync().ConfigureAwait(false);

                var result = JsonConvert.DeserializeObject <T>(json);

                RequestStartTime = HelperMethods.GetRequestStartTime(response);

                return(result);
            }
            catch (JsonException ex)
            {
                KinveyException kinveyException = new KinveyException(
                    EnumErrorCategory.ERROR_DATASTORE_NETWORK,
                    EnumErrorCode.ERROR_JSON_PARSE,
                    HelperMethods.GetCustomParsingJsonErrorMessage(json, response.RequestMessage.RequestUri.ToString(), typeof(T).FullName),
                    null,
                    ex
                    )
                {
                    RequestID = HelperMethods.getRequestID(response)
                };
                throw kinveyException;
            }
            catch (ArgumentException ex)
            {
                Logger.Log(ex.Message);
                return(default(T));
            }
            catch (NullReferenceException ex)
            {
                Logger.Log(ex.Message);
                return(default(T));
            }
        }
コード例 #2
0
ファイル: ReadRequest.cs プロジェクト: heyzooi/dotnet-sdk
        /// <summary>
        /// Operating with delta set data.
        /// </summary>
        /// <param name="cacheItems">Cache items.</param>
        /// <param name="networkItems">Network items.</param>
        /// <param name="mongoQuery">Mongo query.</param>
        /// <returns>The async task with the list of entities.</returns>
        protected async Task <List <T> > RetrieveDeltaSet(List <T> cacheItems, List <DeltaSetFetchInfo> networkItems, string mongoQuery)
        {
            List <T> listDeltaSetResults = new List <T>();

            #region DSF Step 2: Pull all entity IDs and LMTs of a collection in local storage

            Dictionary <string, string> dictCachedEntities = new Dictionary <string, string>();

            foreach (var cacheItem in cacheItems)
            {
                var item = cacheItem as IPersistable;
                if (item.Kmd?.lastModifiedTime != null)                    //if lmt doesn't exist for cache entity, avoid crashing
                {
                    dictCachedEntities.Add(item.ID, item.Kmd.lastModifiedTime);
                }
            }

            List <string> listCachedEntitiesToRemove = new List <string>(dictCachedEntities.Keys);

            #endregion

            #region DSF Step 3: Compare backend and local entities to see what has been created, deleted and updated since the last fetch

            List <string> listIDsToFetch = new List <string>();

            foreach (var networkEntity in networkItems)
            {
                string ID  = networkEntity.ID;
                string LMT = networkEntity.KMD.lastModifiedTime;

                if (!dictCachedEntities.ContainsKey(ID))
                {
                    // Case where a new item exists in the backend, but not in the local cache
                    listIDsToFetch.Add(ID);
                }
                else if (HelperMethods.IsDateMoreRecent(LMT, dictCachedEntities[ID]))
                {
                    // Case where the backend has a more up-to-date version of the entity than the local cache
                    listIDsToFetch.Add(ID);
                }

                // Case where the backend has deleted an item that has not been removed from local storage.
                //
                // To begin with, this list has all the IDs currently present in local storage.  If an ID
                // has been found in the set of backend IDs, we will remove it from this list.  What will
                // remain in this list are all the IDs that are currently in local storage that
                // are not present in the backend, and therefore have to be deleted from local storage.
                listCachedEntitiesToRemove.Remove(ID);

                // NO-OPS: Should never hit these cases, because a Push() has to happen prior to a pull
                //      Case where a new item exists in the local cache, but not in the backend
                //      Case where the local cache has a more up-to-date version of the entity than the backend
                //      Case where the local cache has deleted an item that has not been removed from the backend
            }

            #endregion

            #region DSF Step 4: Remove items from local storage that are no longer in the backend

            Cache.DeleteByIDs(listCachedEntitiesToRemove);

            #endregion

            #region DSF Step 5: Fetch selected IDs from backend to update local storage

            // Then, with this set of IDs from the previous step, make a query to the
            // backend, to get full records for each ID that has changed since last fetch.
            int numIDs = listIDsToFetch.Count;

            if (numIDs == networkItems.Count)
            {
                //Special case where delta set is the same size as the network result.
                //This will occur either when all entities are new/updated, or in error cases such as missing lmts
                return(await RetrieveNetworkResults(mongoQuery).ConfigureAwait(false));
            }

            int start     = 0;
            int batchSize = 200;

            while (start < numIDs)
            {
                int      count            = Math.Min((numIDs - start), batchSize);
                string   queryIDs         = BuildIDsQuery(listIDsToFetch.GetRange(start, count));
                List <T> listBatchResults = await Client.NetworkFactory.buildGetRequest <T>(Collection, queryIDs).ExecuteAsync().ConfigureAwait(false);

                start += listBatchResults.Count();
                listDeltaSetResults.AddRange(listBatchResults);
            }

            #endregion

            return(listDeltaSetResults);
        }
コード例 #3
0
        /// <summary>
        /// Executes the request asynchronously without any parsing.
        /// </summary>
        /// <returns> The async task with Http response. </returns>
        public async Task <HttpResponseMessage> ExecuteUnparsedAsync()
        {
            var httClient = InitializeRestClient();
            var request   = BuildRestRequest();

            RequestAuth.Authenticate(request);
            Logger.Log(request);
            var response = await httClient.SendAsync(request).ConfigureAwait(false);

            Logger.Log(response);
            var contentType = response.Headers
                              .Where(x => x.Key.ToLower().Equals("content-type"))
                              .Select(x => x.Value)
                              .FirstOrDefault()?
                              .FirstOrDefault();

            if (contentType != null && !contentType.Contains("application/json"))
            {
                var kinveyException = new KinveyException(
                    EnumErrorCategory.ERROR_REQUIREMENT,
                    EnumErrorCode.ERROR_REQUIREMENT_CONTENT_TYPE_HEADER,
                    contentType
                    )
                {
                    RequestID = HelperMethods.getRequestID(response)
                };
                throw kinveyException;
            }

            lastResponseCode    = response.StatusCode;
            lastResponseMessage = response.StatusCode.ToString();
            lastResponseHeaders = new List <KeyValuePair <string, IEnumerable <string> > >();

            foreach (var header in response.Headers)
            {
                lastResponseHeaders.Add(header);
            }

            if ((int)response.StatusCode == 401)
            {
                ServerError error = null;
                try
                {
                    var json = await response.Content.ReadAsStringAsync().ConfigureAwait(false);

                    error = JsonConvert.DeserializeObject <ServerError>(json);
                }
                catch (Exception)
                {
                }

                if (error != null && !error.Error.Equals(Constants.STR_ERROR_BACKEND_INSUFFICIENT_CREDENTIALS))
                {
                    // Attempt to get the refresh token
                    Credential cred         = Client.Store.Load(Client.ActiveUser.Id, Client.SSOGroupKey);
                    string     refreshToken = null;
                    string     redirectUri  = null;
                    string     micClientId  = null;

                    if (cred != null)
                    {
                        refreshToken = cred.RefreshToken;
                        redirectUri  = cred.RedirectUri;
                        micClientId  = cred.MICClientID;

                        if (!string.IsNullOrEmpty(refreshToken) && !refreshToken.ToLower().Equals("null"))
                        {
                            if (!hasRetried)
                            {
                                // Attempting retry - set flag to prevent additional attempts
                                hasRetried = true;

                                //use the refresh token for a new access token
                                JObject result = await Client.ActiveUser.UseRefreshToken(refreshToken, redirectUri, micClientId).ExecuteAsync().ConfigureAwait(false);

                                // log out the current user without removing the user record from the credential store
                                Client.ActiveUser.LogoutSoft();

                                //login with the access token
                                Provider provider = new Provider();
                                provider.kinveyAuth = new MICCredential(result["access_token"].ToString());
                                User u = await User.LoginAsync(new ThirdPartyIdentity(provider), Client).ConfigureAwait(false);

                                //store the new refresh token
                                Credential currentCred = Client.Store.Load(Client.ActiveUser.Id, Client.SSOGroupKey);
                                currentCred.AccessToken  = result["access_token"].ToString();
                                currentCred.RefreshToken = result.GetValidValue("refresh_token");
                                currentCred.RedirectUri  = redirectUri;
                                Client.Store.Store(Client.ActiveUser.Id, Client.SSOGroupKey, currentCred);

                                // Retry the original request
                                RequestAuth = new KinveyAuthenticator(currentCred.AuthToken);
                                var retryResponse = await ExecuteUnparsedAsync().ConfigureAwait(false);

                                return(retryResponse);
                            }
                            else
                            {
                                Client.ActiveUser.Logout();
                            }
                        }
                        else
                        {
                            //logout the current user
                            Client.ActiveUser.Logout();
                        }
                    }
                    else
                    {
                        Client.ActiveUser.Logout();
                    }
                }
            }

            try
            {
                response.EnsureSuccessStatusCode();
            }
            catch (Exception ex)
            {
                throw new KinveyException(
                          EnumErrorCategory.ERROR_BACKEND,
                          EnumErrorCode.ERROR_JSON_RESPONSE,
                          response,
                          ex
                          );
            }


            return(response);
        }