Beispiel #1
0
 public CreateController(IBoxPacker packer, IBoxStorage attic, IApiRequest dropbox)
 {
     _packer = packer;
     _attic = attic;
     _dropbox = dropbox;
     _mimeTypes = new List<string> { "image/jpeg", "image/png" };
     _client = new HttpClient();
     //ViewBag.IsMobile = Identity.IsMobile;
 }
Beispiel #2
0
        private object GetParameter(Type paraType, IApiRequest request)
        {
            object para = null;
            var reader = new StreamReader(request.InputStream);
            var body = reader.ReadToEnd();

            if (!string.IsNullOrWhiteSpace(body))
            {
                para = JsonConvert.DeserializeObject(body, paraType);
            }
            return para;
        }
Beispiel #3
0
        public void FireRequestFailureEvent(IApiRequest request, IApiResponse response, RequestFailureReason reason, Action onResume = null, bool foregroundAction = false)
        {
            LogUtility.LogMessage(String.Format("firing RequestFailure event (request type:{0}, reason:{1}, callback:{2}, foreground:{3})",
                                                (request != null ? request.GetType().Name : "<null>"),
                                                Enum.GetName(typeof(RequestFailureReason), reason),
                                                (onResume == null ? "no" : "yes"),
                                                (foregroundAction ? "yes" : "no")));

            if (this._requestFailed != null)
            {
                this._requestFailed(this, new RequestFailureEventArgs(request, response, reason, foregroundAction, onResume));
            }
        }
Beispiel #4
0
        private IApiRequest GenerateVideoDeleteRequest(long clipId)
        {
            ThrowIfUnauthorized();

            IApiRequest request = ApiRequestFactory.GetApiRequest(AccessToken);

            request.Method = HttpMethod.Delete;
            request.Path   = Endpoints.Video;

            request.UrlSegments.Add("clipId", clipId.ToString());

            return(request);
        }
        public async Task FireWebhookAndForgetAsync(IApiRequest request, CancellationToken cancelToken = default)
        {
            if (request == null)
            {
                throw new ArgumentNullException(nameof(request));
            }
            if (!request.IsWebhookRequest)
            {
                throw new InvalidOperationException("Only call this for webhook configured requests");
            }

            using var response = await SendRequest(request, HttpCompletionOption.ResponseHeadersRead, cancelToken);
        }
        /// <summary>
        /// Adds the Query to request.
        /// </summary>
        /// <param name="request">The <see cref="IRestRequest" /> request.</param>
        /// <param name="query">The <see cref="IApiRequest" /> query.</param>
        protected virtual void AddQuiriesToRequest(ref IRestRequest request, IApiRequest query)
        {
            if (query == null)
            {
                return;
            }

            foreach (var parameter in query.QueryParameters)
            {
                request.AddParameter(parameter.Key, parameter.Value, ParameterType.QueryString);
            }
            request.AddParameter("apikey", _config.ConsumerKey, ParameterType.QueryString);
        }
        /// <summary>
        /// Executes the request but limits the number of threads that can be used
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="request"></param>
        /// <returns></returns>
        public async Task <IApiResponse <T> > EnqueueAsync <T>(IApiRequest request)
            where T : class
        {
            await _throttler.WaitAsync().ConfigureAwait(false);

            try
            {
                return(await _handler.ExecuteAsync <T>(request).ConfigureAwait(false));
            }
            finally
            {
                _throttler.Release();
            }
        }
        private IApiRequest GenerateAddTagRequest(long clipId, string tag)
        {
            ThrowIfUnauthorized();

            IApiRequest request = _apiRequestFactory.GetApiRequest(AccessToken);

            request.Method = Method.PUT;
            request.Path   = Endpoints.VideoTag;

            request.UrlSegments.Add("clipId", clipId.ToString());
            request.UrlSegments.Add("tag", tag);

            return(request);
        }
Beispiel #9
0
        public async Task GetPetsGroupedOnOwnerGender(IApiRequest apiRequest, IPeoplePetRepository peoplePetRepository, List <PetsGroupedOnOwnerGender> expectedResult)
        {
            //Arrange
            IPeoplePetService sut = new PeoplePetservice(peoplePetRepository);

            //Act
            List <PetsGroupedOnOwnerGender> result = await sut.getPetsGroupedOnOwnerGender(apiRequest);

            string resultJson         = JsonConvert.SerializeObject(result);
            string expectedResultJson = JsonConvert.SerializeObject(expectedResult);

            //Assert
            Assert.Equal(expectedResultJson, resultJson);
        }
Beispiel #10
0
        /*--------------------------------------------------------------------------------------------*/
        private static IApiResponse ExecuteAcc(IApiRequest pApiReq, string pGrantType, string pClientId,
                                               string pSecret, string pCode, string pRefresh, string pRedirUri)
        {
            Func <FabOauthAccess> getResp = (() => {
                var op = new OauthAccessOperation();
                return(op.Execute(pApiReq.OpCtx, new OauthAccessTasks(), pGrantType,
                                  pClientId, pSecret, pCode, pRefresh, pRedirUri));
            });

            var exec = new JsonExecutor <FabOauthAccess>(pApiReq, getResp);

            exec.OnException = OnAccessExecption;
            return(exec.Execute());
        }
Beispiel #11
0
        private static CancellationToken GetCancellationTokenForRequest(IApiRequest request, CancellationToken cancellationToken)
        {
            var cancellationTokenForRequest = cancellationToken;

            if (request.Timeout == TimeSpan.Zero)
            {
                return(cancellationTokenForRequest);
            }
            var timeoutCancellation      = new CancellationTokenSource(request.Timeout);
            var unifiedCancellationToken = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, timeoutCancellation.Token);

            cancellationTokenForRequest = unifiedCancellationToken.Token;
            return(cancellationTokenForRequest);
        }
Beispiel #12
0
        /// <summary>
        /// Sends the specified request and returns a response.
        /// </summary>
        /// <param name="request">A <see cref="IApiRequest"/> that represents the HTTP request</param>
        /// <param name="cancellationToken">Used to cancel the request</param>
        /// <returns>A <see cref="Task" /> of <see cref="IHttpResponse"/></returns>
        public async Task <IHttpResponse> GetDataAsync(IApiRequest request, CancellationToken cancellationToken)
        {
            Ensure.ArgumentNotNull(nameof(request), request);

            var cancellationTokenForRequest = GetCancellationTokenForRequest(request, cancellationToken);

            using (var requestMessage = BuildRequestMessage(request))
            {
                using (var httpResponseMessage = await GetResponseMessageAsync(requestMessage, request, cancellationTokenForRequest))
                {
                    return(await BuildResponseAsync(httpResponseMessage).ConfigureAwait(false));
                }
            }
        }
Beispiel #13
0
        private IApiRequest AwaitDatastoreChangesRequest(IEnumerable <Datastore> datastores)
        {
            JObject args = new JObject();

            args["cursors"] = new JObject();
            foreach (var store in datastores)
            {
                args["cursors"][store.Handle] = store.Rev;
            }

            IApiRequest request = ApiRequestFactory.Current.CreateRequest("GET", "await?get_deltas=" + Uri.EscapeDataString(args.ToString(Formatting.None)), ApiToken);

            return(request);
        }
        /// <summary>
        /// request handler.  retrives a response using the IApiRequest
        /// </summary>
        /// <param name="request">request</param>
        /// <returns>ResponseObject for the given request</returns>
        public T HandleRequest(IApiRequest request)
        {
            // We only want 1 API attempt at a time.
            // This will prevent two calls from retriving the same data at the same time.
            lock (_lock)
            {
                // First attempt to retrive the
                ResponseObject response = ResponseCache.Cache.Get(Network.BuildUri(request), IgnoreCache);
                T apiResponse           = null;

                if (response == null)
                {
                    Debug.WriteLine(string.Format("Getting {0} from GW2 API", typeof(T).Name));
                    GwApi.Logger.Debug("Getting {0} from GW2 API", typeof(T).Name);
                    // Response is not cached or has expired
                    var apiResponseObject = Network.GetResponse(request);
                    Debug.WriteLine(string.Format("Parsing {0}", request.Resource));
                    GwApi.Logger.Debug("Parsing {0}", request.Resource);
                    try
                    {
                        apiResponse = Parser.Parse(apiResponseObject);
                        if (apiResponse != null)
                        {
                            apiResponse.LastUpdated = DateTime.Now;
                            apiResponse.Url         = Network.BuildUri(request);
                            apiResponse.SetResponse(apiResponseObject);
                            ResponseCache.Cache.Add(apiResponse);
                        }
                    }
                    catch (ResponseException)
                    {
                        throw;
                    }
                    catch (Exception e)
                    {
                        GwApi.Logger.Error(e);
                        throw;
                    }
                }
                else
                {
                    Debug.WriteLine(string.Format("Getting {0} from cache", typeof(T).Name));
                    GwApi.Logger.Debug("Getting {0} from cache", typeof(T).Name);
                }
                //Debug.WriteLine(response == null ? "Retriving Response using " + Network.GetType() : "Using Cache");
                // Return cached response if it's not null
                // otherwise return the fresh new response
                return(response as T ?? apiResponse);
            }
        }
        public static IRestRequest CreateGetRequest(IApiRequest request, string relativePath)
        {
            var searchRequest = new RestRequest(relativePath, Method.GET)
            {
                RequestFormat = DataFormat.Json
            };

            if (request is IApiGetRequest)
            {
                searchRequest.AddParameter("id", (request as IApiGetRequest).Id, ParameterType.UrlSegment);
            }

            return(searchRequest);
        }
        public async Task <User> GetUserInformationAsync(long userId)
        {
            IApiRequest request = _apiRequestFactory.AuthorizedRequest(
                AccessToken,
                Method.GET,
                Endpoints.User,
                new Dictionary <string, string>()
            {
                { "userId", userId.ToString() }
            }
                );

            return(await ExecuteApiRequest <User>(request));
        }
        public async Task <bool> DeleteAlbumAsync(long albumId)
        {
            IApiRequest request = _apiRequestFactory.AuthorizedRequest(
                AccessToken,
                Method.DELETE,
                Endpoints.GetCurrentUserEndpoint(Endpoints.UserAlbum),
                new Dictionary <string, string>()
            {
                { "albumId", albumId.ToString() }
            }
                );

            return(await ExecuteApiRequest(request));
        }
Beispiel #18
0
        private IApiRequest GenerateUserInformationRequest(long?userId = null)
        {
            ThrowIfUnauthorized();

            IApiRequest request = _apiRequestFactory.GetApiRequest(AccessToken);

            request.Method = Method.GET;
            request.Path   = userId.HasValue ? Endpoints.User : Endpoints.GetCurrentUserEndpoint(Endpoints.User);
            if (userId.HasValue)
            {
                request.UrlSegments.Add("userId", userId.ToString());
            }
            return(request);
        }
Beispiel #19
0
        public static T FabricateLoginFailureResponse <T>(IApiRequest request) where T : IApiResponse, new()
        {
            var response = new T();

            response.Header    = new RequestResponseHeader(ResponseType.Connection, request.Header.Channel, request.Header.SessionId);
            response.ErrorBody = new ErrorResponseBody()
            {
                ResponseMessageShort = StringLiterals.AuthFailure,                 //"Authentication Failure",
                ResponseMessageLong  = StringLiterals.UserNotAuthenticated,        //"User not authenticated.",
                ErrorType            = ErrorResponseType.AuthFailure
            };

            return(response);
        }
Beispiel #20
0
        private IApiRequest GenerateVideoAllowedDomainPatchRequest(long clipId, string domain)
        {
            ThrowIfUnauthorized();

            IApiRequest request = ApiRequestFactory.GetApiRequest(AccessToken);

            request.Method = HttpMethod.Put;
            request.Path   = Endpoints.VideoAllowedDomain;

            request.UrlSegments.Add("clipId", clipId.ToString());
            request.UrlSegments.Add("domain", domain);

            return(request);
        }
Beispiel #21
0
        public static T FabricateRequestTimeoutResponse <T>(IApiRequest request) where T : IApiResponse, new()
        {
            var response = new T();

            response.Header    = new RequestResponseHeader(ResponseType.TimeoutError, request.Header.Channel, request.Header.SessionId);
            response.ErrorBody = new ErrorResponseBody()
            {
                ResponseMessageShort = "Request Timeout",
                ResponseMessageLong  = String.Format("The {0} request timed out on the client side. Please check your connection.", request.Header.Type),
                ErrorType            = ErrorResponseType.ResponseTimeout
            };

            return(response);
        }
Beispiel #22
0
        public static T FabricateConnectionTimeoutResponse <T>(IApiRequest request) where T : IApiResponse, new()
        {
            var response = new T();

            response.Header    = new RequestResponseHeader(request.Header.Type, request.Header.Channel, request.Header.SessionId);
            response.ErrorBody = new ErrorResponseBody()
            {
                ResponseMessageShort = StringLiterals.ConnectionTimeout,                 //"Connection Timeout",
                ResponseMessageLong  = StringLiterals.UnableToEstablishConnection,       //"Unable to establish a connection with the server."),
                ErrorType            = ErrorResponseType.ConnectionTimeout
            };

            return(response);
        }
        public async Task <bool> AddToAlbumAsync(long albumId, long clipId)
        {
            IApiRequest request = _apiRequestFactory.AuthorizedRequest(
                AccessToken,
                Method.PUT,
                Endpoints.GetCurrentUserEndpoint(Endpoints.UserAlbumVideo),
                new Dictionary <string, string>()
            {
                { "albumId", albumId.ToString() },
                { "clipId", clipId.ToString() }
            }
                );

            return(await ExecuteApiRequest(request));
        }
        public async Task <Album> UpdateAlbumAsync(long albumId, EditAlbumParameters parameters = null)
        {
            IApiRequest request = _apiRequestFactory.AuthorizedRequest(
                AccessToken,
                Method.PATCH,
                Endpoints.GetCurrentUserEndpoint(Endpoints.UserAlbum),
                new Dictionary <string, string>()
            {
                { "albumId", albumId.ToString() }
            },
                parameters
                );

            return(await ExecuteApiRequest <Album>(request));
        }
Beispiel #25
0
        /// <summary>
        /// Sends the API request to the REST server and obtains a response asynchronously.
        /// </summary>
        /// <param name="restApiRequest">The request to send.</param>
        /// <param name="cancellationToken">The cancellation token.</param>
        /// <returns>The response from the server.</returns>
        public virtual async Task <IApiResponse> SendAsync(IApiRequest restApiRequest, CancellationToken cancellationToken)
        {
            PrepareForSend(restApiRequest);

            var client      = BuildClient(restApiRequest);
            var restRequest = BuildRequest(restApiRequest);

            var restResponse = await client
                               .ExecuteTaskAsync(restRequest, cancellationToken)
                               .ConfigureAwait(false);

            var apiResponse = BuildResponse(restResponse);

            return(apiResponse);
        }
        private IApiRequest GenerateDeleteTextTrackRequest(long clipId, long trackId)
        {
            ThrowIfUnauthorized();

            IApiRequest request  = ApiRequestFactory.GetApiRequest(AccessToken);
            string      endpoint = Endpoints.TextTrack;

            request.Method = Method.DELETE;
            request.Path   = endpoint;

            request.UrlSegments.Add("clipId", clipId.ToString());
            request.UrlSegments.Add("trackId", trackId.ToString());

            return(request);
        }
Beispiel #27
0
        /*--------------------------------------------------------------------------------------------*/
        private static IApiResponse DoRemoveMember(IApiRequest pApiReq)
        {
            Func <object> getResp = (() => {
                var op = new InternalRemoveMemberOperation();
                op.Perform(pApiReq.OpCtx,
                           pApiReq.GetQueryValue("pass", false),
                           pApiReq.GetQueryValue("memId", false),
                           pApiReq.GetQueryValue("delete", false));
                return(op.GetResult());
            });

            var exec = new JsonExecutor <object>(pApiReq, getResp);

            return(exec.Execute());
        }
        /// <summary>
        /// Get album by AlbumId asynchronously
        /// </summary>
        /// <param name="albumId">AlbumId</param>
        /// <returns>Album</returns>
        public async Task <Album> GetAlbumAsync(long albumId)
        {
            IApiRequest request = ApiRequestFactory.AuthorizedRequest(
                AccessToken,
                Method.GET,
                Endpoints.GetCurrentUserEndpoint(Endpoints.UserAlbum),
                new Dictionary <string, string>()
            {
                { "albumId", albumId.ToString() }
            },
                null
                );

            return(await ExecuteApiRequest <Album>(request));
        }
        public string BuildRequest(IApiRequest request)
        {
            if (CachedUrls.ContainsKey(request.Type))
            {
                return(BuildFullUrl());
            }

            var url = $"{ _apiConfig.Protocol}://{ _apiConfig.BaseUrl }/{ _apiConfig.Version }/{ _apiConfig.GetRequestPath(request.Type) }?";

            CachedUrls.TryAdd(request.Type, url);

            string BuildFullUrl() => CachedUrls[request.Type] + request.BuildQueryString();

            return(BuildFullUrl());
        }
        public async Task <Paginated <Album> > GetAlbumsAsync(long userId, GetAlbumsParameters parameters = null)
        {
            IApiRequest request = _apiRequestFactory.AuthorizedRequest(
                AccessToken,
                Method.GET,
                Endpoints.UserAlbums,
                new Dictionary <string, string>()
            {
                { "userId", userId.ToString() }
            },
                parameters
                );

            return(await ExecuteApiRequest <Paginated <Album> >(request));
        }
Beispiel #31
0
        ////////////////////////////////////////////////////////////////////////////////////////////////
        /*--------------------------------------------------------------------------------------------*/
        private static IApiResponse GetLogout(IApiRequest pApiReq)
        {
            Func <FabOauthLogout> getResp = (() => {
                string token = pApiReq.GetQueryValue(LogoutAccessTokenParam, false);

                var op = new OauthLogoutOperation();
                return(op.Execute(pApiReq.OpCtx, new OauthLogoutTasks(), token));
            });

            var          exec = new JsonExecutor <FabOauthLogout>(pApiReq, getResp);
            IApiResponse resp = exec.Execute();

            resp.SetUserCookie(null, false);
            return(resp);
        }
Beispiel #32
0
        public override Task <IApiResponse> ExecuteAsync(IApiRequest request)
        {
            switch (_command.Action)
            {
            case SqlCommandAction.LoadModel:
                return(LoadModelAsync(request));

            case SqlCommandAction.UpdateModel:
                return(UpdateModelAsync(request));

            case SqlCommandAction.ExecuteSql:
                return(ExecuteSqlAsync(request));
            }
            throw new ApiV2Exception($"invalid sql action {_command.Action}");
        }
Beispiel #33
0
        public void ProcessRequest(IApiRequest request, IApiResponse response)
        {
            if (string.IsNullOrWhiteSpace(request.Path)) return;
            ApiPath apiPath;
            ApiConfig config = ApiConfig.GetInstance();
            if (!config.RequestPathCollection.TryGetValue(request.Path, out apiPath)) return;
            if (apiPath == null) return;
            var apiInstance = Activator.CreateInstance(apiPath.ServiceType);
            var method = apiPath.ServiceType.GetMethod(apiPath.Operation);

            var paraTypes = apiPath.Parameters;
            List<object> parameters = null;
            if (paraTypes != null)
            {
                parameters = paraTypes.Select(paraType => GetParameter(paraType, request)).ToList();
            }

            var _response = method.Invoke(apiInstance, parameters == null ? null : parameters.ToArray());
            if (_response == null) throw new ArgumentNullException("request");
            response.Content = _response;
            response.ContentType = "text/json";
        }
Beispiel #34
0
 public SabNzbdRestRequest(IApiRequest request, ILogger logger)
     : base(request, logger)
 {
     Api = request;
     Request = new RestRequest { Resource = "api" };
 }
 public CouchPotatoRestRequest(IApiRequest request, ILogger logger)
     : base(request, logger)
 {
 }
Beispiel #36
0
 public DropboxController(ITokenStorage storage, IApiRequest dropbox)
 {
     _dropbox = dropbox;
     _storage = storage;
 }
 public RefugeesUnitedAccountManager(IApiRequest apiRequest)
 {
     this.apiRequest = apiRequest;
 }
Beispiel #38
0
        static void TQServerStatusUpdate(IApiRequest request)
        {
            if (request.LastResult != null && request.LastResult.Error == null && request == m_TQServerStatus)
            {
                ApiResult<ServerStatus> status = request.LastResult as ApiResult<ServerStatus>;

                if(OnTQServerUpdate != null)
                    OnTQServerUpdate(status.Result);
            }
        }
Beispiel #39
0
 static void OnRequestUpdated(IApiRequest request)
 {
     //Remove requests that are flagged as one shot
     if (request.RemoveAfterUpdate)
         m_ApiRequests.Remove(request);
 }
Beispiel #40
0
 public PictureController(IResize resize, IBoxStorage attic, IApiRequest dropbox)
 {
     _resize = resize;
     _attic = attic;
     _dropbox = dropbox;
 }
 public VkApi(IApiRequest ApiRequest, IApiSettingsProvider ApiSettingsProvider)
     : base(ApiRequest, ApiSettingsProvider)
 {
 }
Beispiel #42
0
        void AccountKeyInfoUpdate(IApiRequest request)
        {
            if (request.LastResult != null && request.LastResult.Error == null && request == m_accountKeyInfo)
            {
                ApiResult<ApiKeyInfo> keyInfo = request.LastResult as ApiResult<ApiKeyInfo>;

                KeyAccess = keyInfo.Result.Key.AccessMask;
                Expires = keyInfo.Result.Key.Expires;

                foreach (CharacterListItem character in keyInfo.Result.Key.Characters)
                {
                    AddCharacter(character.CharacterID, character.Name);
                }

                OnAccountUpdated(request.LastResult);
            }
        }
Beispiel #43
0
 public PlexRestRequest(IApiRequest request, ILogger logger)
     : base(request, logger)
 {
     Api = request;
 }
Beispiel #44
0
        void AccountStatusUpdate(IApiRequest request)
        {
            if (request.LastResult != null && request.LastResult.Error == null && request == m_accountStatus)
            {
                ApiResult<AccountStatus> accStatus = request.LastResult as ApiResult<AccountStatus>;

                LogonCount = accStatus.Result.LogonCount;
                LogonMinutes = accStatus.Result.LogonMinutes;
                CreateDate = accStatus.Result.CreateDate;
                PaidUntil = accStatus.Result.PaidUntil;

                OnAccountUpdated(request.LastResult);
            }
        }
Beispiel #45
0
 protected BaseRequest(IApiRequest request, ILogger logger)
 {
     Api = request;
     Logger = logger;
 }
Beispiel #46
0
        public static void AddRequest(IApiRequest request)
        {
            request.OnRequestUpdate += new RequestUpdated(OnRequestUpdated);

            m_ApiRequests.Add(request);
        }
Beispiel #47
0
 public SonarrRestRequest(IApiRequest request, ILogger logger)
     : base(request, logger)
 {
     Api = request;
 }
Beispiel #48
0
 public NzbGetRestRequest(IApiRequest request, ILogger logger)
     : base(request, logger)
 {
 }
Beispiel #49
0
        void ApiRequestUpdate(IApiRequest request)
        {
            if (request.LastResult != null && request.LastResult.Error == null)
            {
                if (request == m_charSheetRequest)
                {
                    ApiResult<CharacterSheet> charSheet = request.LastResult as ApiResult<CharacterSheet>;
                    UpdateCharacter(charSheet.Result);
                }
                else if (request == m_charInfoRequest)
                {
                    ApiResult<CharacterInfo> charInfo = request.LastResult as ApiResult<CharacterInfo>;
                    UpdateCharacter(charInfo.Result);
                }
                else if (request == m_skillQueueRequest)
                {
                    ApiResult<SkillQueue> queue = request.LastResult as ApiResult<SkillQueue>;
                    SkillQueue = queue.Result;
                }
                else if (request == m_AssetListRequest)
                {
                    ApiResult<AssetList> assets = request.LastResult as ApiResult<AssetList>;

                    // Create asset dictionary keyed on locationID
                    Dictionary<long, List<AssetListInfo>> newAssets = new Dictionary<long, List<AssetListInfo>>();

                    foreach (API.EVE.AssetListInfo info in assets.Result.Assets)
                    {
                        if (!newAssets.ContainsKey(info.LocationID))
                            newAssets.Add(info.LocationID, new List<AssetListInfo>());

                        newAssets[info.LocationID].Add(info);
                    }

                    //TODO: Better - as calling the dictionary itself doesn't trigger a save
                    Assets = newAssets;
                }
                else if (request == m_StandingsRequest)
                {
                    ApiResult<CharacterStandings> standingsResult = request.LastResult as ApiResult<CharacterStandings>;
                    Standings = standingsResult.Result.NPCStandings;
                }

                if (!IsUpdating && CharacterUpdated != null)
                {
                    CharacterUpdated(this, null);
                }
            }
        }