From e38d552497a36aef262c5db203071c11a208c388 Mon Sep 17 00:00:00 2001 From: richardb Date: Thu, 5 Oct 2023 12:33:45 +0100 Subject: [PATCH 1/3] Target netstandard2.0 and use the new csproj format. Add endpoints listEvents and listRunnerBook. Use keep alive. RescriptClient seems to be broken. --- .../Api-ng-sample-code.csproj | 194 ++---------------- .../Api-ng-sample-code/IClient.cs | 9 +- .../Api-ng-sample-code/JsonRpcClient.cs | 77 +++++-- .../Api-ng-sample-code/Program.cs | 2 +- .../Api-ng-sample-code/RescriptClient.cs | 57 ++++- 5 files changed, 123 insertions(+), 216 deletions(-) diff --git a/cSharp/Api-ng-sample-code/Api-ng-sample-code/Api-ng-sample-code.csproj b/cSharp/Api-ng-sample-code/Api-ng-sample-code/Api-ng-sample-code.csproj index 5ff472f..2c9f0a8 100644 --- a/cSharp/Api-ng-sample-code/Api-ng-sample-code/Api-ng-sample-code.csproj +++ b/cSharp/Api-ng-sample-code/Api-ng-sample-code/Api-ng-sample-code.csproj @@ -1,184 +1,18 @@ - - + + - Debug - x86 - 8.0.30703 - 2.0 - {6B5844C4-BBF3-43D9-9B58-6AEA1FC6E548} - Exe - Properties - Api_ng_sample_code - Api-ng-sample-code - v4.0 - Client - 512 - publish\ - true - Disk - false - Foreground - 7 - Days - false - false - true - 0 - 1.0.0.%2a - false - false - true + netstandard2.0 + disable + disable + 8 + 1.0.1 + 6 - - x86 - true - full - false - bin\Debug\ - DEBUG;TRACE - prompt - 4 - - - x86 - pdbonly - true - bin\Release\ - TRACE - prompt - 4 - - - Api_ng_sample_code.Program - - - - ..\lib\Newtonsoft.Json.dll - - - - - - - - - - - - - - Component - - - - - - - - - - Component - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - - False - Microsoft .NET Framework 4 Client Profile %28x86 and x64%29 - true - - - False - .NET Framework 3.5 SP1 Client Profile - false - - - False - .NET Framework 3.5 SP1 - false - - - False - Windows Installer 3.1 - true - + + + - - - \ No newline at end of file + + diff --git a/cSharp/Api-ng-sample-code/Api-ng-sample-code/IClient.cs b/cSharp/Api-ng-sample-code/Api-ng-sample-code/IClient.cs index f81abe3..31c4c08 100644 --- a/cSharp/Api-ng-sample-code/Api-ng-sample-code/IClient.cs +++ b/cSharp/Api-ng-sample-code/Api-ng-sample-code/IClient.cs @@ -1,13 +1,18 @@ using System; using System.Collections.Generic; -using System.Linq; -using System.Text; using Api_ng_sample_code.TO; namespace Api_ng_sample_code { public interface IClient { + event EventHandler OnAPINGException; + + void KeepAlive(); + AccountFundsResponse getAccountFunds(Wallet wallet); + IList listEvents(MarketFilter mf, string locale = null); + IList listRunnerBook(string marketId, string selectionId, double handicap, PriceProjection priceProjection, MatchProjection matchProjection, bool includeOverallPosition, bool partitionMatchedByStrategyRef, ISet customerStrategyRefs, string currencyCode, string locale, DateTime matchedSince, ISet betIds); + /** * calls api-ng to get a list of events * diff --git a/cSharp/Api-ng-sample-code/Api-ng-sample-code/JsonRpcClient.cs b/cSharp/Api-ng-sample-code/Api-ng-sample-code/JsonRpcClient.cs index 33b61d5..ff31a98 100644 --- a/cSharp/Api-ng-sample-code/Api-ng-sample-code/JsonRpcClient.cs +++ b/cSharp/Api-ng-sample-code/Api-ng-sample-code/JsonRpcClient.cs @@ -1,20 +1,48 @@ using System; using System.Collections.Generic; using System.Collections.Specialized; -using System.Linq; using System.Text; -using Api_ng_sample_code.TO; -using System.Web.Services.Protocols; using System.Net; using System.IO; using Api_ng_sample_code.Json; using Api_ng_sample_code.TO; +using System.Linq; namespace Api_ng_sample_code { - public class JsonRpcClient : HttpWebClientProtocol, IClient + public class JsonRpcClient : HttpWebClientProtocol, IClient { - public string EndPoint { get; private set; } + public void KeepAlive() + { + WebRequest rq = WebRequest.Create(new Uri(EndPointKeepAlive)); + rq.Method = "GET"; + rq.Headers.Add(CustomHeaders); + ((HttpWebRequest)rq).Accept = "application/json"; + using (WebResponse response = GetWebResponse(rq)) + using (Stream stream = response.GetResponseStream()) + using (StreamReader reader = new StreamReader(stream, Encoding.UTF8)) + { + string s = reader.ReadToEnd(); + } + } + + private static readonly string LIST_EVENTS_METHOD = "SportsAPING/v1.0/listEvents"; + public IList listEvents(MarketFilter marketFilter, string locale = null) + { + var args = new Dictionary(); + args[FILTER] = marketFilter; + args[LOCALE] = locale; + return Invoke>(LIST_EVENTS_METHOD, args); + } + + public IList listRunnerBook(string marketId, string selectionId, double handicap, PriceProjection priceProjection, MatchProjection matchProjection, bool includeOverallPosition, bool partitionMatchedByStrategyRef, ISet customerStrategyRefs, string currencyCode, string locale, DateTime matchedSince, ISet betIds) + { + throw new NotImplementedException(); + } + + public string EndPointBetting { get; private set; } + public string EndPointAccount { get; private set; } + public string EndPointKeepAlive { get; private set; } private static readonly IDictionary operationReturnTypeMap = new Dictionary(); public const string APPKEY_HEADER = "X-Application"; public const string SESSION_TOKEN_HEADER = "X-Authentication"; @@ -63,9 +91,13 @@ public class JsonRpcClient : HttpWebClientProtocol, IClient private static readonly string GROUP_BY = "groupBy"; private static readonly string INCLUDE_ITEM_DESCRIPTION = "includeItemDescription"; - public JsonRpcClient(string endPoint, string appKey, string sessionToken) - { - this.EndPoint = endPoint + "/json-rpc/v1"; + private static readonly string[] _AccountApiMethods = { GET_ACCOUNT_FUNDS_METHOD }; + + public JsonRpcClient(string endPointBetting, string endPointAccount, string endPointKeepAlive, string appKey, string sessionToken) + { + EndPointBetting = endPointBetting + "/json-rpc/v1"; + EndPointAccount = endPointAccount + "/json-rpc/v1"; + EndPointKeepAlive = endPointKeepAlive; CustomHeaders = new NameValueCollection(); if (appKey != null) { @@ -75,7 +107,7 @@ public JsonRpcClient(string endPoint, string appKey, string sessionToken) { CustomHeaders[SESSION_TOKEN_HEADER] = sessionToken; } - } + } public IList listEventTypes(MarketFilter marketFilter, string locale = null) @@ -84,7 +116,7 @@ public IList listEventTypes(MarketFilter marketFilter, string l args[FILTER] = marketFilter; args[LOCALE] = locale; return Invoke>(LIST_EVENT_TYPES_METHOD, args); - + } public IList listMarketCatalogue(MarketFilter marketFilter, ISet marketProjections, MarketSort marketSort, string maxResult = "1", string locale = null) @@ -109,7 +141,7 @@ public IList listMarketTypes(MarketFilter marketFilter, string public IList listMarketBook(IList marketIds, PriceProjection priceProjection, OrderProjection? orderProjection = null, MatchProjection? matchProjection = null, string currencyCode = null, string locale = null) { var args = new Dictionary(); - args[MARKET_IDS]= marketIds; + args[MARKET_IDS] = marketIds; args[PRICE_PROJECTION] = priceProjection; args[ORDER_PROJECTION] = orderProjection; args[MATCH_PROJECTION] = matchProjection; @@ -121,11 +153,11 @@ public IList listMarketBook(IList marketIds, PriceProjection public PlaceExecutionReport placeOrders(string marketId, string customerRef, IList placeInstructions, string locale = null) { var args = new Dictionary(); - - args[MARKET_ID] = marketId; + + args[MARKET_ID] = marketId; args[INSTRUCTIONS] = placeInstructions; args[CUSTOMER_REFERENCE] = customerRef; - args[LOCALE] = locale; + args[LOCALE] = locale; return Invoke(PLACE_ORDERS_METHOD, args); } @@ -134,7 +166,7 @@ public PlaceExecutionReport placeOrders(string marketId, string customerRef, ILi protected WebRequest CreateWebRequest(Uri uri) { - WebRequest request = WebRequest.Create(new Uri(EndPoint)); + WebRequest request = WebRequest.Create(uri); request.Method = "POST"; request.ContentType = "application/json-rpc"; request.Headers.Add(HttpRequestHeader.AcceptCharset, "ISO-8859-1,utf-8"); @@ -143,7 +175,7 @@ protected WebRequest CreateWebRequest(Uri uri) return request; } - + public event EventHandler OnAPINGException; public T Invoke(string method, IDictionary args = null) { @@ -152,7 +184,7 @@ public T Invoke(string method, IDictionary args = null) if (method.Length == 0) throw new ArgumentException(null, "method"); - var request = CreateWebRequest(new Uri(EndPoint)); + var request = _AccountApiMethods.Contains(method) ? CreateWebRequest(new Uri(EndPointAccount)) : CreateWebRequest(new Uri(EndPointBetting)); using (Stream stream = request.GetRequestStream()) using (StreamWriter writer = new StreamWriter(stream, Encoding.UTF8)) @@ -160,17 +192,19 @@ public T Invoke(string method, IDictionary args = null) var call = new JsonRequest { Method = method, Id = 1, Params = args }; JsonConvert.Export(call, writer); } - Console.WriteLine("\nCalling: " + method + " With args: " + JsonConvert.Serialize>(args)); + Console.WriteLine("\nCalling: " + method + " With args: " + JsonConvert.Serialize>(args)); using (WebResponse response = GetWebResponse(request)) using (Stream stream = response.GetResponseStream()) using (StreamReader reader = new StreamReader(stream, Encoding.UTF8)) { var jsonResponse = JsonConvert.Import(reader); - // Console.WriteLine("\nGot Response: " + JsonConvert.Serialize>(jsonResponse)); + // Console.WriteLine("\nGot Response: " + JsonConvert.Serialize>(jsonResponse)); if (jsonResponse.HasError) { - throw ReconstituteException(jsonResponse.Error); + APINGException e = ReconstituteException(jsonResponse.Error); + OnAPINGException(this, e); + throw e; } else { @@ -179,8 +213,7 @@ public T Invoke(string method, IDictionary args = null) } } - - private static System.Exception ReconstituteException(Api_ng_sample_code.TO.Exception ex) + private static APINGException ReconstituteException(Api_ng_sample_code.TO.Exception ex) { var data = ex.Data; diff --git a/cSharp/Api-ng-sample-code/Api-ng-sample-code/Program.cs b/cSharp/Api-ng-sample-code/Api-ng-sample-code/Program.cs index 83f2a96..da365aa 100644 --- a/cSharp/Api-ng-sample-code/Api-ng-sample-code/Program.cs +++ b/cSharp/Api-ng-sample-code/Api-ng-sample-code/Program.cs @@ -48,7 +48,7 @@ static void Main(string[] args) }else { Console.WriteLine("Using JsonRpcClient"); - client = new JsonRpcClient(Url, appkey, sessionToken); + client = new JsonRpcClient(Url, null, null, appkey, sessionToken); } Console.WriteLine("\nBeginning sample run!\n"); diff --git a/cSharp/Api-ng-sample-code/Api-ng-sample-code/RescriptClient.cs b/cSharp/Api-ng-sample-code/Api-ng-sample-code/RescriptClient.cs index 9a54227..bfc5321 100644 --- a/cSharp/Api-ng-sample-code/Api-ng-sample-code/RescriptClient.cs +++ b/cSharp/Api-ng-sample-code/Api-ng-sample-code/RescriptClient.cs @@ -4,13 +4,23 @@ using System.Linq; using System.Text; using Api_ng_sample_code.TO; -using System.Web.Services.Protocols; using System.Net; using System.IO; using Api_ng_sample_code.Json; namespace Api_ng_sample_code { + /// + /// Replacement for System.Web.Services.HttpWebClientProtocol + /// + public abstract class HttpWebClientProtocol + { + protected WebResponse GetWebResponse(WebRequest request) + { + return request.GetResponse(); + } + } + public class RescriptClient : HttpWebClientProtocol, IClient { public string EndPoint { get; private set; } @@ -60,9 +70,9 @@ public class RescriptClient : HttpWebClientProtocol, IClient private static readonly string GROUP_BY = "groupBy"; private static readonly string INCLUDE_ITEM_DESCRIPTION = "includeItemDescription"; - + public RescriptClient(string endPoint, string appKey, string sessionToken) - { + { this.EndPoint = endPoint + "/rest/v1/"; CustomHeaders = new NameValueCollection(); if (appKey != null) @@ -73,7 +83,12 @@ public RescriptClient(string endPoint, string appKey, string sessionToken) { CustomHeaders[SESSION_TOKEN_HEADER] = sessionToken; } - } + } + + public AccountFundsResponse getAccountFunds(Wallet wallet) + { + throw new NotImplementedException(); + } public IList listEventTypes(MarketFilter marketFilter, string locale = null) { @@ -133,6 +148,7 @@ protected HttpWebRequest CreateWebRequest(String restEndPoint) return request; } + public event EventHandler OnAPINGException; public T Invoke(string method, IDictionary args = null) { @@ -157,31 +173,34 @@ public T Invoke(string method, IDictionary args = null) } using (HttpWebResponse response = (HttpWebResponse)GetWebResponse(request)) - + using (Stream stream = response.GetResponseStream()) using (StreamReader reader = new StreamReader(stream, Encoding.UTF8)) { var jsonResponse = reader.ReadToEnd(); Console.WriteLine("\nGot response: " + jsonResponse); - - if (response.StatusCode != HttpStatusCode.OK) { - throw ReconstituteException(JsonConvert.Deserialize(jsonResponse)); + + if (response.StatusCode != HttpStatusCode.OK) + { + APINGException e = ReconstituteException(JsonConvert.Deserialize(jsonResponse)); + OnAPINGException(this, e); + throw e; } return JsonConvert.Deserialize(jsonResponse); } } - private static System.Exception ReconstituteException(Api_ng_sample_code.TO.Exception ex) + private static APINGException ReconstituteException(Api_ng_sample_code.TO.Exception ex) { var data = ex.Detail; - + // API-NG exception -- it must have "data" element to tell us which exception var exceptionName = data.Property("exceptionname").Value.ToString(); var exceptionData = data.Property(exceptionName).Value.ToString(); return JsonConvert.Deserialize(exceptionData); - + } public IList listMarketProfitAndLoss(IList marketIds, bool includeSettledBets = false, bool includeBspBets = false, bool netOfCommission = false) @@ -269,5 +288,21 @@ public IList listMarketTypes(MarketFilter marketFilter, string return Invoke>(LIST_MARKET_TYPES_METHOD, args); } + + public IList listEvents(MarketFilter marketFilter, string locale = null) + { + throw new NotImplementedException(); + } + + public void KeepAlive() + { + throw new NotImplementedException(); + } + + public IList listRunnerBook(string marketId, string selectionId, double handicap, PriceProjection priceProjection, MatchProjection matchProjection, bool includeOverallPosition, bool partitionMatchedByStrategyRef, ISet customerStrategyRefs, string currencyCode, string locale, DateTime matchedSince, ISet betIds) + { + throw new NotImplementedException(); + } + } } From 19b62f674b92db7b5f696f091e8b89d6d4779167 Mon Sep 17 00:00:00 2001 From: richardb Date: Thu, 5 Oct 2023 14:29:34 +0100 Subject: [PATCH 2/3] Migrate assembly info to csproj. --- .../Api-ng-sample-code.csproj | 4 ++- .../Api-ng-sample-code/MarketTypeResult.cs | 16 --------- .../Properties/AssemblyInfo.cs | 36 ------------------- 3 files changed, 3 insertions(+), 53 deletions(-) delete mode 100644 cSharp/Api-ng-sample-code/Api-ng-sample-code/MarketTypeResult.cs delete mode 100644 cSharp/Api-ng-sample-code/Api-ng-sample-code/Properties/AssemblyInfo.cs diff --git a/cSharp/Api-ng-sample-code/Api-ng-sample-code/Api-ng-sample-code.csproj b/cSharp/Api-ng-sample-code/Api-ng-sample-code/Api-ng-sample-code.csproj index 2c9f0a8..c080077 100644 --- a/cSharp/Api-ng-sample-code/Api-ng-sample-code/Api-ng-sample-code.csproj +++ b/cSharp/Api-ng-sample-code/Api-ng-sample-code/Api-ng-sample-code.csproj @@ -4,9 +4,11 @@ netstandard2.0 disable disable - 8 1.0.1 6 + Copyright © Betfair 2013 + Api-ng-sample-code + Betfair diff --git a/cSharp/Api-ng-sample-code/Api-ng-sample-code/MarketTypeResult.cs b/cSharp/Api-ng-sample-code/Api-ng-sample-code/MarketTypeResult.cs deleted file mode 100644 index efb3dda..0000000 --- a/cSharp/Api-ng-sample-code/Api-ng-sample-code/MarketTypeResult.cs +++ /dev/null @@ -1,16 +0,0 @@ -using System; -using System.Linq; -using Newtonsoft.Json; - -namespace Api_ng_sample_code.TO -{ - - public class MarketTypeResult - { - [JsonProperty(PropertyName = "marketType")] - public string marketType { get; set; } - - [JsonProperty(PropertyName = "marketCount")] - public int marketCount { get; set; } - } -} diff --git a/cSharp/Api-ng-sample-code/Api-ng-sample-code/Properties/AssemblyInfo.cs b/cSharp/Api-ng-sample-code/Api-ng-sample-code/Properties/AssemblyInfo.cs deleted file mode 100644 index 673e92b..0000000 --- a/cSharp/Api-ng-sample-code/Api-ng-sample-code/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,36 +0,0 @@ -using System.Reflection; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -// General Information about an assembly is controlled through the following -// set of attributes. Change these attribute values to modify the information -// associated with an assembly. -[assembly: AssemblyTitle("Api-ng-sample-code")] -[assembly: AssemblyDescription("")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("Betfair")] -[assembly: AssemblyProduct("Api-ng-sample-code")] -[assembly: AssemblyCopyright("Copyright © Betfair 2013")] -[assembly: AssemblyTrademark("")] -[assembly: AssemblyCulture("")] - -// Setting ComVisible to false makes the types in this assembly not visible -// to COM components. If you need to access a type in this assembly from -// COM, set the ComVisible attribute to true on that type. -[assembly: ComVisible(false)] - -// The following GUID is for the ID of the typelib if this project is exposed to COM -[assembly: Guid("eedffe5b-7330-42b7-a837-51d90e26816b")] - -// Version information for an assembly consists of the following four values: -// -// Major Version -// Minor Version -// Build Number -// Revision -// -// You can specify all the values or you can default the Build and Revision Numbers -// by using the '*' as shown below: -// [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.0.0.0")] From 5c2f8b1adc92ab8a8b8adea170fcb5f352629355 Mon Sep 17 00:00:00 2001 From: richardb Date: Thu, 5 Oct 2023 14:42:21 +0100 Subject: [PATCH 3/3] RunnerState values PLACED and HIDDEN. --- .../Api-ng-sample-code/Api-ng-sample-code/TO/RunnerStatus.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/cSharp/Api-ng-sample-code/Api-ng-sample-code/TO/RunnerStatus.cs b/cSharp/Api-ng-sample-code/Api-ng-sample-code/TO/RunnerStatus.cs index 23b0aa3..6ef74dc 100644 --- a/cSharp/Api-ng-sample-code/Api-ng-sample-code/TO/RunnerStatus.cs +++ b/cSharp/Api-ng-sample-code/Api-ng-sample-code/TO/RunnerStatus.cs @@ -10,6 +10,7 @@ namespace Api_ng_sample_code.TO [JsonConverter(typeof(StringEnumConverter))] public enum RunnerStatus { - ACTIVE, WINNER, LOSER, REMOVED_VACANT, REMOVED + ACTIVE, WINNER, LOSER, REMOVED_VACANT, REMOVED, + PLACED, HIDDEN } }