Using VB2008 to acccess the Betfair API: A tutorial

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Mumbles0
    Junior Member
    • Jan 2009
    • 240

    #421
    Step 30. Saving your project’s settings.

    A while back Welcometomylair1 asked a question about saving project settings so they would persist from one run to the next. In my reply I outlined a way to extend the existing SessToken.txt file to save project settings as well as the session token. G-Factor suggested a simpler way of doing this using VB’s inbuilt application settings facility. In this step we look at this.

    1. Saving the value of a control’s property.

    For example the Text property of a TextBox.

    TextBoxes are handy controls which are commonly used to hold settings for your project, e.g. marketId, sample frequency, etc. For this exercise drag a TextBox from the ToolBox onto the TestForm and rename it to tParam (or anything you like).

    With this TextBox selected so that its properties appear in the "Properties" widow, expand the (ApplicationSettings) node. Click on (PropertyBindings) then click (...) to show the "Applications Setting for tParam" form. Select the Text property then click (New...) in the property’s associated drop down list window to show the "New Application Setting" form. Enter these settings:

    DefaultValue: 123
    Name: Param1
    Scope: User
    Click OK, OK. With this procedure we have bound the tParam.Text property to an application setting we have created named Param1. Think of an application setting as being a special variable whose value is retained from one run to the next.

    Now run the project. Notice that the default value we entered appears in the TextBox. Change this value to something else (e.g. 456), then close the form to stop the project running. Re-run the project and notice that the new value is now in the TextBox. Thus the TextBox always retains the most recently entered value. We have achieved this without writing any code.

    2. Saving any value.

    The application settings can be used to retain any value you like. You can create a new setting by clicking "BetfairX Properties" on the Project menu to show the Properties form. Select the "Settings" tab. Here you will see all the settings used by the project, including Param1 which we added above. You add a new setting by adding a new entry to the table. For example, add the name Param2, having value "This is Param2". This setting becomes a property of the My.Settings object and can be accessed from anywhere in you code with:

    My.Settings.Param2
    To demonstrate, put this code in Sub TestForm_Load:

    Code:
      .....
      Print("Last run: " & My.Settings.Param2)  'Previous run time
      My.Settings.Param2 = Now              'Re-assign the setting 
      Print("This run: " & My.Settings.Param2)   'Current run time
      .....
    and run the project a few times. You will see that Param2 initially holds the previous run time.

    Note:

    We could have used an application setting to hold the session token rather than storing it in the auxiliary file SessToken.txt.

    Two "scopes" are available. With "User" scope the values of the settings apply only to the current (Windows) user. With "Application" scope the settings values apply to all users.

    Comment

    • granted
      Junior Member
      • Jun 2009
      • 14

      #422
      how do i access the oMarketResp.market.runners(i).selectionId from another sub

      in lesson 29 we had the code below...how can i access the oMarketResp.market.runners(i).selectionId from another sub?

      here is the code where its from:

      Public Class MarketForm

      Const PosLeft = 25 'Position of buttons from left edge of form
      Const PosTop = 25 'Position of buttons from top of form
      Const PosBut = 30 'Button spacing
      Const Bwidth = 150 'Button width

      Private Buttons As Button() 'The array of buttons

      Sub AddRunnerButtons(ByVal oMarketResp As BFUK.GetMarketResp)
      Dim Tpos As Integer = PosTop 'Top position of first button
      Dim m As Integer = oMarketResp.market.runners.Length - 1 'Number of runners - 1

      ReDim Buttons(m)
      For i = 0 To m 'For each runner
      Buttons(i) = New Button 'Create a new button object in the array element
      With Buttons(i) 'Set button properties as required
      .Left = PosLeft 'Set left position
      .Text = oMarketResp.market.runners(i).name 'Set the text
      .Tag = oMarketResp.market.runners(i).selectionId 'Save the selectionId in the button's Tag property
      .TextAlign = ContentAlignment.MiddleLeft 'Set the text alignment
      .Top = Tpos 'Set top position
      .Width = Bwidth 'Set button width
      End With
      Controls.Add(Buttons(i)) 'Display this button on the form
      AddHandler Buttons(i).Click, AddressOf RunnerButton_Click 'Assign the event handler for this button's click event
      Tpos += PosBut 'Top position of the next button
      Next

      End Sub

      'The 'Click' event handler

      Private Sub RunnerButton_Click(ByVal sender As Object, ByVal e As System.EventArgs)
      Dim RunnerButton As Button = sender 'A reference to the button that was clicked
      With RunnerButton
      MsgBox(.Tag & " " & .Text) 'Show the data for the clicked button
      End With
      End Sub

      End Class
      Last edited by granted; 09-09-2010, 02:35 PM.

      Comment

      • Peter Simple
        Junior Member
        • Aug 2009
        • 32

        #423
        Mumbles0

        Thank you very much for this tutorial. It is extremely helpfull to make the first steps.

        In Step 2 you define new Global Service object so

        Dim BetfairGL As New BFGlobal.BFGlobalService
        I used these declaration

        Dim service As New Session_Manager.BFGlobalServiceClient
        Session_Manager = BFGlobal, the difference is the "Client".

        (even when your code was my guide my test app had an other structure). Was there an update of the API. The same happened when i wanted access to the exchange markets.

        I have now tested various calls and it worked like it should.

        Comment

        • Peter Simple
          Junior Member
          • Aug 2009
          • 32

          #424
          System.ServiceModel.CommunicationException

          When i use the "getAllMarkets" method i am running in a problem when the API sends a large data file. Then it will cause a

          System.ServiceModel.CommunicationException

          because the MaxReceivedMessageSize (65536) is exceeded.

          Comment

          • Oldb
            Junior Member
            • Feb 2009
            • 6

            #425
            Compresses Problem...

            I am trying to get the latest BACK and LAY prices ( eg as i see it on the betfair web page)

            Using uncompressed i am getting the figures all ok

            BUT

            When using the compressed option... as below

            I am getting the figures i need but they are not consistantly in the same place in the array....

            The lines start with the id and the m= ie 50/5

            Code...


            m = UBound(Field) \ 5 - 1 'm = number of prices - 1
            ReDim .prices(m) : k = 0

            POdds(i) = POdds(i) & m & " / "

            For j = 0 To m ' eg m=5

            .prices(j) = New PricesType

            With .prices(j)
            'Load the price array
            .price = Val(Field(k + 0))
            POdds(i) = POdds(i) & .price & " / "
            .backAmount = Val(Field(k + 1))
            .layAmount = Val(Field(k + 2))
            .totalBspBackAmount = Val(Field(k + 3))
            .totalBspLayAmount = Val(Field(k + 4))
            k += 5
            End With
            Next

            I am loading into Podds()

            BUT the current Back and Lay are not allways at the end of the array Podds()


            This is the output of Podds

            4970766 @ 11 / 1.01 / 1.02 / 1.06 / 1.11 / 1.4 / 2.38 / 3.05 / 6 / 6.2 / 8 / 160 / 200 /
            4970767 @ 12 / 1.01 / 1.02 / 1.06 / 1.11 / 1.4 / 2.68 / 2.76 / 6 / 7.2 / 8.2 / 10 / 75 / 990 /
            4333840 @ 11 / 1.01 / 1.02 / 1.06 / 1.11 / 1.4 / 2.88 / 5.1 / 6 / 30 / 280 / 320 / 1000 /
            4970764 @ 18 / 1.01 / 1.02 / 1.06 / 1.11 / 1.4 / 1.46 / 1.72 / 1.73 / 2 / 2.02 / 2.1 / 2.22 / 2.88 / 2.9 / 3 / 11 / 100 / 990 / 1000 /
            4970765 @ 12 / 1.01 / 1.02 / 1.06 / 1.11 / 1.4 / 3 / 3.05 / 6 / 6.2 / 14.5 / 20 / 150 / 190 /
            4935477 @ 11 / 1.01 / 1.02 / 1.06 / 1.11 / 1.4 / 2.18 / 2.98 / 6 / 27 / 40 / 50 / 990 /
            4919959 @ 11 / 1.01 / 1.02 / 1.06 / 1.11 / 1.4 / 2.26 / 3.9 / 6 / 6.2 / 10 / 160 / 180 /
            4970772 @ 14 / 1.01 / 1.02 / 1.06 / 1.11 / 1.33 / 1.4 / 2.14 / 2.5 / 6 / 6.2 / 7 / 10 / 65 / 90 / 990 /
            4970771 @ 11 / 1.01 / 1.02 / 1.06 / 1.11 / 1.4 / 1.71 / 1.72 / 6 / 6.2 / 7 / 42 / 990 /
            4970770 @ 12 / 1.01 / 1.02 / 1.06 / 1.11 / 1.4 / 2 / 2.02 / 6 / 6.2 / 9 / 55 / 170 / 1000 /
            4970769 @ 10 / 1.01 / 1.02 / 1.06 / 1.11 / 1.4 / 2.64 / 4.3 / 6 / 16 / 150 / 230 /
            4970768 @ 12 / 1.01 / 1.02 / 1.06 / 1.11 / 1.33 / 1.4 / 2.5 / 4.5 / 6 / 12 / 90 / 370 / 390 /

            Regards
            Oldb

            Comment

            • Mumbles0
              Junior Member
              • Jan 2009
              • 240

              #426
              Reply to Peter Simple

              Peter,

              BFGlobalServiceClient

              Looks like you've added a service reference instead of a web reference in Step 2. See this post. It's interesting to see that you're getting somewhere with the service reference, but the tutorial exercises use the web reference.

              System.ServiceModel.CommunicationException

              Sometimes users have got this exception when requesting a large amount of data from getAllMarkets. See this conversation. You may have to increase the value of the maxStringContentLength (and possibly other values) in your app.config file.

              Comment

              • Mumbles0
                Junior Member
                • Jan 2009
                • 240

                #427
                Reply to Oldb (re: compressed prices)

                There are 2 API calls which return compressed prices: getMarketPricesCompressed and getCompleteMarketPricesCompressed.

                If you want the data to be the same as getMarketPrices, then call getMarketPricesCompressed (as shown in my post).

                I think you are calling getCompleteMarketPricesCompressed instead.

                Comment

                • Mumbles0
                  Junior Member
                  • Jan 2009
                  • 240

                  #428
                  Reply to granted (Re: accessing the selectionId)

                  If you want to access the SelectionId for a clicked runner button then you can call a sub from the event handler. For example:

                  Code:
                  [COLOR="Gray"]'The 'Click' event handler
                  
                  Private Sub RunnerButton_Click(ByVal sender As Object, ByVal e As System.EventArgs)
                    Dim RunnerButton As Button = sender  'A reference to the button that was clicked
                    With RunnerButton
                      [COLOR="Black"]ProcessYourSelection(.Tag)  'Call your sub with the selectionId for the clicked button[/COLOR]
                    End With
                  End Sub[/COLOR]
                  
                  [COLOR="Black"]Sub ProcessYourSelection(ByVal SelectionId As Integer)
                    [I]'Code to do something with the clicked selection[/I]
                  End Sub[/COLOR]
                  The selectionId for each runner is in the button's Tag property. When you call the sub the SelectionId is passed in as the parameter.

                  Comment

                  • Oldb
                    Junior Member
                    • Feb 2009
                    • 6

                    #429
                    Mumbles0...

                    Yes i was calling "getCompleteMarketPricesCompressed" in error

                    Your original instructions were 100% accurate.. sorry.

                    Appreciate your patience

                    Regards Oldb

                    Comment

                    • Peter Simple
                      Junior Member
                      • Aug 2009
                      • 32

                      #430
                      Some interesting observations.

                      1. It was my fault to use a service reference. But i could do all calls (login, logout, gunds, event etc) using the global and the UK_Exchange service. Every call was repsonded with correct .Resp which i could transform in usefull datas (using the common techniques which here are also shown).

                      2. After adding the web reference and changing the code the "MaxReceivedMessageSize" exception was gone ! That is a dramatic difference because i can now receive much, much larger message files. So it was no problem to get all saturday football matches.

                      3. It seems that the "MaxReceivedMessageSize" is a common problem. Here is an interesting link

                      http://craigrandall.net/archives/200...size/#more-995

                      I have also found various articles by MSDN but i have no real clue about the matter. It seems to me that there is a default size which depends on the RAM in your system but you can change it manually when you understand the technique.

                      Comment

                      • John10
                        Junior Member
                        • Sep 2010
                        • 4

                        #431
                        Mumbles0 Great tutorial, however i have a problem getting the UnpackAllMarkets data into a DataGrid, could you help.
                        The DataGrid gets the rows with no data

                        Code:
                        Private TableMarkets As New DataTable  'The Markets data table
                        
                        Sub GetAllMarkets()
                        
                                Dim row As DataRow
                        
                                With TableMarkets.Columns    'Set up all columns
                                    .Add("colId")
                                    .Add("colJump")
                                    .Add("colNo")
                                    .Add("colTrack")
                                    .Add("colName")
                                    .Add("ColExtra")
                                End With
                        
                                Dim oMarketsReq As New BFAU.GetAllMarketsReq
                                Dim oMarketsResp As BFAU.GetAllMarketsResp
                        
                                With oMarketsReq
                                    .header = oHeaderAU()
                                    'Set request parameters here
                                    ReDim .eventTypeIds(0) : .eventTypeIds(0) = 7  'For horse racing
                                    ReDim .countries(1) : .countries(0) = "AUS" : .countries(1) = "NZL"
                                    .fromDate = Today
                                    .toDate = Today.AddDays(1)
                                End With
                        
                                oMarketsResp = BetFairAU.getAllMarkets(oMarketsReq) 'Call AU exchange
                                With oMarketsResp
                                    CheckHeader(.header)
                                    If .errorCode = BFAU.GetAllMarketsErrorEnum.OK Then
                                        Print("**Markets**")
                                        'Print(.marketData)
                                        Dim AllMarkets As New UnpackAllMarkets(.marketData)  'Create an object and unpack the string
                        
                                        With AllMarkets
                                            For i = 0 To .marketData.Length - 1
                                                With .marketData(i)
                                                    Print(.marketId & " " & .marketStatus & "  " & .marketName & "  " & .menuPath)
                                                    row = TableMarkets.NewRow
                                                    row("colId") = .marketId  'Add the Markets Ids
                                                    row("colJump") = FormatDateTime(.eventDate, DateFormat.ShortTime) 'and Start Time
                                                    row("colNo") = 1             'and Race No
                                                    row("colTrack") = .eventDate                'and Track names
                                                    row("colName") = .eventDate                'and Race names
                                                    row("ColExtra") = ""
                                                    TableMarkets.Rows.Add(row)
                                                End With
                                            Next
                                        End With
                                    Else
                                        Print("ErrorCode = " & .errorCode.ToString)
                                    End If
                                End With
                                dgvMarkets.DataSource = TableMarkets  'Show the data
                                dgvMarkets.Refresh()
                        
                            End Sub
                        Last edited by John10; 14-09-2010, 03:41 AM. Reason: adding more info

                        Comment

                        • Mumbles0
                          Junior Member
                          • Jan 2009
                          • 240

                          #432
                          John10,

                          Your code works for me. Data is appearing in the rows of the grid.

                          John10-1.png

                          You've obviously got more work to do getting the column data right, but the basic structure seems OK. What problems are you having?

                          Also - when you say you are using a DataGrid, do you mean a DataGridView? (A DataGrid is something else.)

                          Comment

                          • John10
                            Junior Member
                            • Sep 2010
                            • 4

                            #433
                            Mumbles0 just found the problem, I set columns in the DataGridVeiw first, what happened the data table columns also got added to the right (out of veiw) Removed columns from DataGridView and works properly. ps thanks for the quick response.

                            Comment

                            • Mumbles0
                              Junior Member
                              • Jan 2009
                              • 240

                              #434
                              Using DataGridView

                              John10,

                              A few thoughts on using DataGridView.

                              I see that you are first loading the data into a DataTable object, then assigning this to the DataGridView. This is a perfectly valid approach, but did you know that you can load the DataGridView directly?

                              You can set up column properties (header, width, alignment, format, etc.) with the columns editor. To launch the columns editor select the Columns property (in the properties window for dgvMarkets) and click on (...).

                              Although there are many different ways to do this, the code to load the data can be similar to what you already have:

                              Code:
                                ......
                                With AllMarkets
                                  For i = 0 To .marketData.Length - 1
                                    With .marketData(i)
                                      dgvMarkets.Rows.Add()  'Add a new row to dgvMarkets
                                      Dim row As DataGridViewRow = dgvMarkets.Rows(i)   'A reference to the new row
                                      row.Cells("colId").Value = .marketId  'Add the MarketIds
                                      row.Cells("colJump").Value = .eventDate.ToLocalTime   'and Start Time
                                      row.Cells("colNo").Value = ""        'and Race No (to do)
                                      row.Cells("colTrack").Value = ""        'and Track names (to do)
                                      row.Cells("colName").Value = .marketName         'and Race names
                                      row.Cells("ColExtra").Value = i
                                    End With
                                  Next
                                End With
                                ......
                              This gives the result:

                              [ATTACH]119[/ATTACH]


                              Notice that the time value has been formatted with the columns editor (by setting the DefaultCellStyle.Format property for colJump).

                              It’ easy to access a particular cell using row and column numbers, for example:

                              x = dgvMarkets(4, 2).Value
                              gets the value of the cell at column 4, row 2.
                              Alternatively you can use the column name:

                              x = dgvMarkets("colName", 2).Value
                              You can get the corresponding marketId when you click on a row with a handler for the CellContentClick event:

                              Code:
                              Private Sub dgvMarkets_CellContentClick(ByVal sender As Object, ByVal e As System.Windows.Forms.DataGridViewCellEventArgs) Handles dgvMarkets.CellContentClick
                                Dim marketId As Integer
                                marketId = dgvMarkets("colId", e.RowIndex).Value  'get the marketId
                                Print(marketId)  'To test
                              End Sub
                              Even though DataGridView looks complicated, it’s fairly easy to use as an output UI device.

                              Comment

                              • Peter Simple
                                Junior Member
                                • Aug 2009
                                • 32

                                #435
                                I am using VB 10 and WPF 4.0 and i am missing really the DataGridView because you could load datas directly.

                                In WPF 4.0 you have only a DataGrid and here is a direct loading not possible. You can not simply add a row. A DataGrid requires an item source like a class or datatable.

                                Comment

                                Working...
                                X