From 3520a67ebe97b1fb29d387d09793ebde4cbc11f0 Mon Sep 17 00:00:00 2001 From: Jason Best Date: Fri, 21 May 2021 18:00:51 -0400 Subject: [PATCH 1/2] Changes from Dmitry --- .../Framework/IAuthenticator.cs | 9 +- .../Framework/SDataRequest.cs | 167 ++++++++++-------- Saleslogix.SData.Client/ISDataClient.cs | 1 + Saleslogix.SData.Client/SDataClient.cs | 67 +++---- 4 files changed, 133 insertions(+), 111 deletions(-) diff --git a/Saleslogix.SData.Client/Framework/IAuthenticator.cs b/Saleslogix.SData.Client/Framework/IAuthenticator.cs index 002b99a5..66739c2e 100644 --- a/Saleslogix.SData.Client/Framework/IAuthenticator.cs +++ b/Saleslogix.SData.Client/Framework/IAuthenticator.cs @@ -7,12 +7,19 @@ namespace Saleslogix.SData.Client.Framework public interface IAuthenticator { void Authenticate(WebRequest request); + ///invoked in response to 401 UnauthorizedAction Unauthorized(WebResponse response); } + public interface IAuthenticator2 : IAuthenticator + { + ///invoked in response to 403 + UnauthorizedAction Forbidden(WebResponse response); + } + public enum UnauthorizedAction { Throw, Retry } -} \ No newline at end of file +} diff --git a/Saleslogix.SData.Client/Framework/SDataRequest.cs b/Saleslogix.SData.Client/Framework/SDataRequest.cs index d2f1f0f4..86aaf510 100644 --- a/Saleslogix.SData.Client/Framework/SDataRequest.cs +++ b/Saleslogix.SData.Client/Framework/SDataRequest.cs @@ -215,11 +215,22 @@ public virtual SDataResponse GetResponse() attempts--; continue; } - if (ex.Status == WebExceptionStatus.ProtocolError && - ((HttpWebResponse) ex.Response).StatusCode == HttpStatusCode.Unauthorized && - Authenticator != null && Authenticator.Unauthorized(ex.Response) == UnauthorizedAction.Retry) + if (ex.Status == WebExceptionStatus.ProtocolError && Authenticator != null) { - continue; + if (((HttpWebResponse)ex.Response).StatusCode == HttpStatusCode.Unauthorized) + { + //401 + if (Authenticator.Unauthorized(ex.Response) == UnauthorizedAction.Retry) continue; + } + else if (((HttpWebResponse)ex.Response).StatusCode == HttpStatusCode.Forbidden) + { + IAuthenticator2 vAuthenticator2 = Authenticator as IAuthenticator2; + if (vAuthenticator2 != null) + { + //403 + if (vAuthenticator2.Forbidden(ex.Response) == UnauthorizedAction.Retry) continue; + } + } } throw new SDataException(ex); } @@ -257,87 +268,87 @@ public virtual IAsyncResult BeginGetResponse(AsyncCallback callback, object stat Action getResponse = null; Action loop = () => + { + MediaType? contentType; + object content; + _request = CreateRequest(uri, out contentType, out content); + if (content != null || Form.Count > 0 || Files.Count > 0) { - MediaType? contentType; - object content; - _request = CreateRequest(uri, out contentType, out content); - if (content != null || Form.Count > 0 || Files.Count > 0) - { - _request.BeginGetRequestStream( - async => + _request.BeginGetRequestStream( + async => + { + try + { + using (var stream = _request.EndGetRequestStream(async)) { - try - { - using (var stream = _request.EndGetRequestStream(async)) - { - WriteRequestContent(contentType, content, stream); - } - TraceRequest(_request); - getResponse(); - } - catch (Exception ex) - { - result.Failure(ex, async.CompletedSynchronously); - _request = null; - Interlocked.Exchange(ref _state, 0); - } - }, null); - } - else - { - TraceRequest(_request); - getResponse(); - } - }; + WriteRequestContent(contentType, content, stream); + } + TraceRequest(_request); + getResponse(); + } + catch (Exception ex) + { + result.Failure(ex, async.CompletedSynchronously); + _request = null; + Interlocked.Exchange(ref _state, 0); + } + }, null); + } + else + { + TraceRequest(_request); + getResponse(); + } + }; getResponse = () => _request.BeginGetResponse( async => + { + try { + WebResponse response; try { - WebResponse response; - try - { - response = _request.EndGetResponse(async); - TraceResponse(response); - } - catch (WebException webEx) - { + response = _request.EndGetResponse(async); + TraceResponse(response); + } + catch (WebException webEx) + { #if PCL || NETFX_CORE || SILVERLIGHT if (attempts > 0) #else - if (webEx.Status == WebExceptionStatus.Timeout && attempts > 0) + if (webEx.Status == WebExceptionStatus.Timeout && attempts > 0) #endif - { - attempts--; - loop(); - return; - } - throw new SDataException(webEx); - } - - var httpResponse = response as HttpWebResponse; - var statusCode = httpResponse != null ? httpResponse.StatusCode : 0; - - if (statusCode != HttpStatusCode.Found) { - result.Success(new SDataResponse(response, location), async.CompletedSynchronously); - _request = null; - Interlocked.Exchange(ref _state, 0); - } - else - { - uri = location = response.Headers["Location"]; + attempts--; loop(); + return; } + throw new SDataException(webEx); } - catch (Exception ex) + + var httpResponse = response as HttpWebResponse; + var statusCode = httpResponse != null ? httpResponse.StatusCode : 0; + + if (statusCode != HttpStatusCode.Found) { - result.Failure(ex, async.CompletedSynchronously); + result.Success(new SDataResponse(response, location), async.CompletedSynchronously); _request = null; Interlocked.Exchange(ref _state, 0); } - }, null); + else + { + uri = location = response.Headers["Location"]; + loop(); + } + } + catch (Exception ex) + { + result.Failure(ex, async.CompletedSynchronously); + _request = null; + Interlocked.Exchange(ref _state, 0); + } + }, null); try { loop(); @@ -356,7 +367,7 @@ public virtual SDataResponse EndGetResponse(IAsyncResult asyncResult) Guard.ArgumentIsType>(asyncResult, "asyncResult"); try { - return ((AsyncResult) asyncResult).End(); + return ((AsyncResult)asyncResult).End(); } finally { @@ -381,7 +392,7 @@ private WebRequest CreateRequest(string uri, out MediaType? contentType, out obj methodOverride = true; contentType = MediaType.Text; content = uri; - uri = new SDataUri(uri) {Query = null}.ToString(); + uri = new SDataUri(uri) { Query = null }.ToString(); } else { @@ -531,18 +542,18 @@ private void WriteRequestContent(MediaType? contentType, object content, Stream { if (contentType != null) { - var part = new MimePart(requestStream) {ContentType = MediaTypeNames.GetMediaType(contentType.Value)}; + var part = new MimePart(requestStream) { ContentType = MediaTypeNames.GetMediaType(contentType.Value) }; multipart.Add(part); } foreach (var data in Form) { var part = new MimePart(new MemoryStream(Encoding.UTF8.GetBytes(data.Value))) - { - ContentType = MediaTypeNames.TextMediaType, - ContentTransferEncoding = "binary", - ContentDisposition = "inline; name=" + data.Key - }; + { + ContentType = MediaTypeNames.TextMediaType, + ContentTransferEncoding = "binary", + ContentDisposition = "inline; name=" + data.Key + }; multipart.Add(part); } @@ -557,11 +568,11 @@ private void WriteRequestContent(MediaType? contentType, object content, Stream } var part = new MimePart(file.Stream) - { - ContentType = file.ContentType ?? "application/octet-stream", - ContentTransferEncoding = "binary", - ContentDisposition = contentDisposition - }; + { + ContentType = file.ContentType ?? "application/octet-stream", + ContentTransferEncoding = "binary", + ContentDisposition = contentDisposition + }; multipart.Add(part); } diff --git a/Saleslogix.SData.Client/ISDataClient.cs b/Saleslogix.SData.Client/ISDataClient.cs index f9f60013..64f19449 100644 --- a/Saleslogix.SData.Client/ISDataClient.cs +++ b/Saleslogix.SData.Client/ISDataClient.cs @@ -42,5 +42,6 @@ public interface ISDataClient Task> ExecuteAsync(SDataParameters parms, CancellationToken cancel = default(CancellationToken)); Task>> ExecuteBatchAsync(IList items, CancellationToken cancel = default(CancellationToken)); #endif + CookieContainer Cookies { get; set; } } } \ No newline at end of file diff --git a/Saleslogix.SData.Client/SDataClient.cs b/Saleslogix.SData.Client/SDataClient.cs index 223a7e1d..1050a0c3 100644 --- a/Saleslogix.SData.Client/SDataClient.cs +++ b/Saleslogix.SData.Client/SDataClient.cs @@ -29,7 +29,6 @@ public class SDataClient : ISDataClient #endif private readonly Func _requestFactory; - private readonly CookieContainer _cookies = new CookieContainer(); public SDataClient(string uri) : this(uri, targetUri => new SDataRequest(targetUri)) @@ -45,6 +44,10 @@ internal SDataClient(string uri, Func requestFactory) MaxGetUriLength = 2000; } + //private readonly CookieContainer _cookies = new CookieContainer(); + private CookieContainer _cookies = new CookieContainer(); + public CookieContainer Cookies { get { return _cookies; } set { _cookies = value; } } + public string Uri { get; set; } public string UserName { get; set; } public string Password { get; set; } @@ -141,22 +144,22 @@ private SDataRequest CreateRequest(SDataParameters parms, bool responseContentIg Guard.ArgumentNotNull(parms, "parms"); var uri = new SDataUri(Uri) - { - StartIndex = parms.StartIndex, - Count = parms.Count, - Where = parms.Where, - OrderBy = parms.OrderBy, - Search = parms.Search, - Include = parms.Include, - Select = parms.Select, - Precedence = parms.Precedence, - IncludeSchema = parms.IncludeSchema, - ReturnDelta = parms.ReturnDelta, - TrackingId = parms.TrackingId, - Format = parms.Format, - Language = parms.Language, - Version = parms.Version - }; + { + StartIndex = parms.StartIndex, + Count = parms.Count, + Where = parms.Where, + OrderBy = parms.OrderBy, + Search = parms.Search, + Include = parms.Include, + Select = parms.Select, + Precedence = parms.Precedence, + IncludeSchema = parms.IncludeSchema, + ReturnDelta = parms.ReturnDelta, + TrackingId = parms.TrackingId, + Format = parms.Format, + Language = parms.Language, + Version = parms.Version + }; if (parms.Method != HttpMethod.Delete) { if (uri.Precedence == null && responseContentIgnored) @@ -371,11 +374,11 @@ private SDataRequest CreateBatchRequest(ICollection items) } var itemUri = new SDataUri(Uri) - { - Include = parms.Include, - Select = parms.Select, - Precedence = parms.Precedence - }; + { + Include = parms.Include, + Select = parms.Select, + Precedence = parms.Precedence + }; if (path != null) { itemUri.AppendPath(path); @@ -394,12 +397,12 @@ private SDataRequest CreateBatchRequest(ICollection items) } var uri = new SDataUri(Uri) - { - Precedence = precedence, - Format = format ?? Format, - Language = language ?? Language, - Version = version ?? Version - }; + { + Precedence = precedence, + Format = format ?? Format, + Language = language ?? Language, + Version = version ?? Version + }; if (path != null) { uri.AppendPath(path); @@ -477,7 +480,7 @@ private ISDataResults CreateResults(SDataResponse response) TraceResponse(response); object obj = null; - if (typeof (T) == typeof (byte[])) + if (typeof(T) == typeof(byte[])) { var str = response.Content as string; if (str != null) @@ -485,7 +488,7 @@ private ISDataResults CreateResults(SDataResponse response) obj = Encoding.UTF8.GetBytes(str); } } - else if (typeof (T) == typeof (string)) + else if (typeof(T) == typeof(string)) { var data = response.Content as byte[]; if (data != null) @@ -494,7 +497,7 @@ private ISDataResults CreateResults(SDataResponse response) } } #if !PCL && !NETFX_CORE && !SILVERLIGHT - else if (typeof (T) == typeof (SDataSchema)) + else if (typeof(T) == typeof(SDataSchema)) { var str = response.Content as string; if (str != null) @@ -509,7 +512,7 @@ private ISDataResults CreateResults(SDataResponse response) T content; if (obj != null) { - content = (T) obj; + content = (T)obj; } else { From 20e5bdffe7b8596104688f422eb15f98851df796 Mon Sep 17 00:00:00 2001 From: Jason Best Date: Fri, 21 May 2021 19:08:27 -0400 Subject: [PATCH 2/2] Version bump --- Saleslogix.SData.Client/Properties/AssemblyInfo.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Saleslogix.SData.Client/Properties/AssemblyInfo.cs b/Saleslogix.SData.Client/Properties/AssemblyInfo.cs index 0f56c03e..67a10f6d 100644 --- a/Saleslogix.SData.Client/Properties/AssemblyInfo.cs +++ b/Saleslogix.SData.Client/Properties/AssemblyInfo.cs @@ -26,7 +26,7 @@ // by using the '*' as shown below: [assembly: AssemblyVersion("2.0")] -[assembly: AssemblyFileVersion("2.0.2.1563")] +[assembly: AssemblyFileVersion("2.0.3.1564")] [assembly: NeutralResourcesLanguage("en-US")] [assembly: AssemblyInformationalVersion("2.0")] [assembly: InternalsVisibleTo("Saleslogix.SData.Client.Test, PublicKey=" +