public void SnTrace_DynamicCategories() { // Test initialization CleanupAndEnableAll(); // Activate Custom and Test categories. Any other be inactive. SnTrace.DisableAll(); SnTrace.Custom.Enabled = true; SnTrace.Test.Enabled = true; // Write 7 lines including dynamic categories SnTrace.Write("Line1"); SnTrace.Category("asdf").Write("Line2"); SnTrace.Test.Write("Line3"); SnTrace.Category("qwer").Write("Line4"); SnTrace.Test.Write("Line5"); SnTrace.Category("yxcv").Write("Line6"); SnTrace.Write("Line7"); // Get log var log = DisableAllAndGetLog(); // Get categories var categories = log .Select(Entry.Parse) .Where(e => e != null) .Select(e => e.Category) .ToArray(); var actual = string.Join(",", categories); // Verify Assert.AreEqual("Custom,asdf,Test,qwer,Test,yxcv,Custom", actual); }
public void SnTrace_DynamicCategoryOnOff() { // Test initialization CleanupAndEnableAll(); // Activate Custom and Test categories. Any other be inactive. SnTrace.DisableAll(); SnTrace.Custom.Enabled = true; SnTrace.Test.Enabled = true; // Pin custom categories var asdf = SnTrace.Category("asdf"); var qwer = SnTrace.Category("qwer"); var yxcv = SnTrace.Category("yxcv"); asdf.Write("0"); qwer.Write("1"); yxcv.Write("2"); asdf.Enabled = false; asdf.Write("3"); qwer.Write("4"); yxcv.Write("5"); yxcv.Enabled = false; asdf.Write("6"); qwer.Write("7"); yxcv.Write("8"); asdf.Enabled = true; yxcv.Enabled = true; qwer.Enabled = false; asdf.Write("9"); qwer.Write("A"); yxcv.Write("B"); qwer.Enabled = true; asdf.Write("C"); qwer.Write("D"); yxcv.Write("E"); // Get log var log = DisableAllAndGetLog(); // Get categories var categories = log .Select(Entry.Parse) .Where(e => e != null) .Select(e => e.Message) .ToArray(); var actual = string.Join("", categories); // Verify Assert.AreEqual("0124579BCDE", actual); }
private static async Task <Content> UploadInternalAsync(Stream binaryStream, UploadData uploadData, ODataRequest requestData, ServerContext server = null, Action <int> progressCallback = null) { server ??= ClientContext.Current.Server; // force set values uploadData.UseChunk = binaryStream.Length > ClientContext.Current.ChunkSizeInBytes; if (uploadData.FileLength == 0) { uploadData.FileLength = binaryStream.Length; } requestData.Parameters.Add("create", "1"); dynamic uploadedContent = null; // Get ChunkToken try { SnTrace.Category(ClientContext.TraceCategory).Write("###>REQ: {0}", requestData); var retryCount = 0; await Retrier.RetryAsync(10, 1000, async() => { retryCount++; var retryText = retryCount > 1 ? $" (retry {retryCount})" : string.Empty; server.Logger?.LogTrace($"Uploading initial data of {uploadData.FileName}{retryText}."); var httpContent = new StringContent(uploadData.ToString()); httpContent.Headers.ContentType = new MediaTypeHeaderValue(JsonContentMimeType); await ProcessWebResponseAsync(requestData.ToString(), HttpMethod.Post, server, httpContent, response => { uploadData.ChunkToken = response.Content.ReadAsStringAsync().GetAwaiter().GetResult(); }, CancellationToken.None).ConfigureAwait(false); }, (i, exception) => { // choose the exceptions when we can retry the operation return(exception switch { null => true, ClientException cex when (int) cex.StatusCode == 429 || cex.ErrorData?.ExceptionType == "NodeIsOutOfDateException" => false, _ => throw exception }); });
/// <summary> /// Gets the raw response of a general HTTP request from the server. /// </summary> /// <param name="uri">Request URI.</param> /// <param name="server">Target server.</param> /// <param name="method">HTTP method (SenseNet.Client.HttpMethods class has a few predefined methods).</param> /// <param name="jsonBody">Request body in JSON format.</param> /// <returns>Raw HTTP response.</returns> public static async Task <string> GetResponseStringAsync(Uri uri, ServerContext server = null, HttpMethod method = null, string jsonBody = null) { string result = null; SnTrace.Category(ClientContext.TraceCategory).Write("###>REQ: {0}", uri); await ProcessWebResponseAsync(uri.ToString(), method, server, jsonBody != null?new StringContent(jsonBody) : null, async response => { if (response != null) { result = await response.Content.ReadAsStringAsync().ConfigureAwait(false); } }, CancellationToken.None).ConfigureAwait(false); return(result); }
private static async Task <Content> UploadInternalAsync(Stream binaryStream, UploadData uploadData, ODataRequest requestData, ServerContext server = null, Action <int> progressCallback = null) { // force set values uploadData.UseChunk = binaryStream.Length > ClientContext.Current.ChunkSizeInBytes; if (uploadData.FileLength == 0) { uploadData.FileLength = binaryStream.Length; } requestData.Parameters["create"] = "1"; dynamic uploadedContent = null; var retryCount = 0; // send initial request while (retryCount < REQUEST_RETRY_COUNT) { try { var myReq = CreateInitUploadWebRequest(requestData.ToString(), server, uploadData); SnTrace.Category(ClientContext.TraceCategory).Write("###>REQ: {0}", myReq.RequestUri); using (var wr = await myReq.GetResponseAsync()) { uploadData.ChunkToken = await ReadResponseStringAsync(wr); } // succesful request: skip out from retry loop break; } catch (WebException ex) { if (retryCount >= REQUEST_RETRY_COUNT - 1) { var ce = new ClientException("Error during binary upload.", ex); ce.Data["SiteUrl"] = requestData.SiteUrl; ce.Data["Parent"] = requestData.ContentId != 0 ? requestData.ContentId.ToString() : requestData.Path; ce.Data["FileName"] = uploadData.FileName; ce.Data["ContentType"] = uploadData.ContentType; throw ce; } else { Thread.Sleep(50); } } retryCount++; } var boundary = "---------------------------" + DateTime.UtcNow.Ticks.ToString("x"); var trailer = Encoding.ASCII.GetBytes("\r\n--" + boundary + "--\r\n"); // send subsequent requests var buffer = new byte[ClientContext.Current.ChunkSizeInBytes]; int bytesRead; var start = 0; // reuse previous request data, but remove unnecessary parameters requestData.Parameters.Remove("create"); while ((bytesRead = binaryStream.Read(buffer, 0, buffer.Length)) != 0) { retryCount = 0; //get the request object for the actual chunk while (retryCount < REQUEST_RETRY_COUNT) { Stream requestStream = null; HttpWebRequest chunkRequest; try { chunkRequest = CreateChunkUploadWebRequest(requestData.ToString(), server, uploadData, boundary, out requestStream); SnTrace.Category(ClientContext.TraceCategory).Write("###>REQ: {0}", chunkRequest.RequestUri); if (uploadData.UseChunk) { chunkRequest.Headers.Set("Content-Range", string.Format("bytes {0}-{1}/{2}", start, start + bytesRead - 1, binaryStream.Length)); } //write the chunk into the request stream requestStream.Write(buffer, 0, bytesRead); requestStream.Write(trailer, 0, trailer.Length); await requestStream.FlushAsync(); } finally { if (requestStream != null) { requestStream.Close(); } } //send the request try { using (var wr = await chunkRequest.GetResponseAsync()) { var rs = await ReadResponseStringAsync(wr); uploadedContent = JsonHelper.Deserialize(rs); } // successful request: skip out from the retry loop break; } catch (WebException ex) { if (retryCount >= REQUEST_RETRY_COUNT - 1) { var ce = new ClientException("Error during binary upload.", ex); ce.Data["SiteUrl"] = requestData.SiteUrl; ce.Data["Parent"] = requestData.ContentId != 0 ? requestData.ContentId.ToString() : requestData.Path; ce.Data["FileName"] = uploadData.FileName; ce.Data["ContentType"] = uploadData.ContentType; throw ce; } else { Thread.Sleep(50); } } retryCount++; } start += bytesRead; // notify the caller about every chunk that was uploaded successfully if (progressCallback != null) { progressCallback(start); } } if (uploadedContent == null) { return(null); } int contentId = uploadedContent.Id; var content = Content.Create(contentId); content.Name = uploadedContent.Name; content.Path = uploadedContent.Url; return(content); }
/// <summary> /// Gets the raw response of a general HTTP request from the server. /// </summary> /// <param name="uri">Request URI.</param> /// <param name="method">HTTP method (SenseNet.Client.HttpMethods class has a few predefined methods).</param> /// <param name="body">Request body.</param> /// <param name="server">Target server.</param> /// <returns>Raw HTTP response.</returns> public static async Task <string> GetResponseStringAsync(Uri uri, ServerContext server = null, HttpMethod method = null, string body = null) { var retryCount = 0; while (retryCount < REQUEST_RETRY_COUNT) { SnTrace.Category(ClientContext.TraceCategory).Write("###>REQ: {0}", uri); var myRequest = GetRequest(uri, server); if (method != null) { myRequest.Method = method.Method; } if (!string.IsNullOrEmpty(body)) { try { using (var requestWriter = new StreamWriter(myRequest.GetRequestStream())) { requestWriter.Write(body); } } catch (Exception ex) { throw new ClientException("Error during writing to request stream: " + ex.Message, ex); } } else { myRequest.ContentLength = 0; } try { using (var wr = await myRequest.GetResponseAsync()) { return(await ReadResponseStringAsync(wr)); } } catch (WebException ex) { var webResponse = ex.Response as HttpWebResponse; // a 404 result is not an error in case of simple get requests, so return silently if (webResponse != null && webResponse.StatusCode == HttpStatusCode.NotFound && (method == null || method != HttpMethod.Post)) { return(null); } if (retryCount >= REQUEST_RETRY_COUNT - 1) { throw await GetClientExceptionAsync(ex, uri.ToString(), method, body); } else { var responseString = await ReadResponseStringAsync(ex.Response); Thread.Sleep(50); SnTrace.Category(ClientContext.TraceCategory).Write("###>REQ: {0} ERROR:{1}", uri, responseString.Replace(Environment.NewLine, " ").Replace("\r\n", " ") + " " + ex); } } retryCount++; } return(string.Empty); }
private static async Task <Content> UploadInternalAsync(Stream binaryStream, UploadData uploadData, ODataRequest requestData, ServerContext server = null, Action <int> progressCallback = null) { // force set values uploadData.UseChunk = binaryStream.Length > ClientContext.Current.ChunkSizeInBytes; if (uploadData.FileLength == 0) { uploadData.FileLength = binaryStream.Length; } requestData.Parameters.Add("create", "1"); dynamic uploadedContent = null; // Get ChunkToken try { SnTrace.Category(ClientContext.TraceCategory).Write("###>REQ: {0}", requestData); var httpContent = new StringContent(uploadData.ToString()); httpContent.Headers.ContentType = new MediaTypeHeaderValue(JsonContentMimeType); await ProcessWebResponseAsync(requestData.ToString(), HttpMethod.Post, server, httpContent, async response => { uploadData.ChunkToken = await response.Content.ReadAsStringAsync().ConfigureAwait(false); }, CancellationToken.None).ConfigureAwait(false); } catch (WebException ex) { var ce = new ClientException("Error during binary upload.", ex); ce.Data["SiteUrl"] = requestData.SiteUrl; ce.Data["Parent"] = requestData.ContentId != 0 ? requestData.ContentId.ToString() : requestData.Path; ce.Data["FileName"] = uploadData.FileName; ce.Data["ContentType"] = uploadData.ContentType; throw ce; } // Reuse previous request data, but remove unnecessary parameters requestData.Parameters.Remove("create"); // Send subsequent requests var boundary = "---------------------------" + DateTime.UtcNow.Ticks.ToString("x"); var uploadFormData = uploadData.ToKeyValuePairs(); var contentDispositionHeaderValue = new ContentDispositionHeaderValue("attachment") { FileName = uploadData.FileName }; var buffer = new byte[ClientContext.Current.ChunkSizeInBytes]; int bytesRead; var start = 0; while ((bytesRead = binaryStream.Read(buffer, 0, buffer.Length)) != 0) { // Prepare the current chunk request var httpContent = new MultipartFormDataContent(boundary); foreach (var item in uploadFormData) { httpContent.Add(new StringContent(item.Value), item.Key); } httpContent.Headers.ContentDisposition = contentDispositionHeaderValue; if (uploadData.UseChunk) { httpContent.Headers.ContentRange = new ContentRangeHeaderValue(start, start + bytesRead - 1, binaryStream.Length); } // Add the chunk as a stream into the request content var postedStream = new MemoryStream(buffer, 0, bytesRead); httpContent.Add(new StreamContent(postedStream), "files[]", uploadData.FileName); // Process await ProcessWebResponseAsync(requestData.ToString(), HttpMethod.Post, server, httpContent, async response => { var rs = await response.Content.ReadAsStringAsync().ConfigureAwait(false); uploadedContent = JsonHelper.Deserialize(rs); }, CancellationToken.None).ConfigureAwait(false); start += bytesRead; // Notify the caller about every chunk that was uploaded successfully progressCallback?.Invoke(start); } if (uploadedContent == null) { return(null); } int contentId = uploadedContent.Id; var content = Content.Create(contentId); content.Name = uploadedContent.Name; content.Path = uploadedContent.Url; return(content); }