Tutorial: Developing Web Application Projects

Overview

This tutorial shows how to create a COBOL Web application project and how to make it interact with an existing COBOL program. The project includes a page that is generated in managed COBOL. The page calls an intermediary program to map .NET data types onto COBOL data types. The intermediary program then calls the existing COBOL program to perform the business logic.

The Web application project has three programs:

  • A Web page. The Microsoft form designer enables you to create a Web page (also known as a Web form) in any .NET language, such as C# and COBOL. This tutorial shows how to generate these forms in .NET COBOL.
  • Existing COBOL program, the Book program. This program simulates a pre-existing COBOL program, which contains the business logic and which remains unchanged. This program is supplied and this tutorial adds it as a reference to the Web application project so that it is recompiled as managed code and exposed as a class that can be called by .NET managed code without needing any changes to the source.
  • Intermediary COBOL class, the BookWrapper program. This program acts as an interface between the client form and the pre-existing COBOL program. This intermediary class interfaces with the .NET client form using objects, and it interfaces with the existing COBOL using the standard COBOL PIC X data types. This intermediary class is supplied and this tutorial adds it as a reference to the Web application project.

Create a Web Application Project

The first task is to create a Web Application Project, which you do as follows:

  1. Start Visual Studio.
  2. In Visual Studio, click File > New > Project.
  3. In the New Project dialog box, expand Installed > Templates > COBOL.
  4. Select Web.
  5. In the center pane, select ASP.NET Web Application.
  6. Ensure .NET Framework 4.5 is selected in the dropdown list above the center pane.
  7. Specify a name such as BookDemoWebApplication.
  8. Specify a location to store the project on your file system such as c:\tutorials.
  9. Uncheck Create Directory for Solution.
  10. Click OK.

This creates the BookDemoWebApplication project, which is shown in the Solution Explorer. The project includes:

  • App_Data, which is an empty folder for holding application data
  • Default.aspx, which is the trigger program that displays the main form
  • Default.aspx.cbl, which contains your code for the form
  • Web.config, which is the application configuration file

Add the Legacy Code and the Wrapper Code

You now need to add the existing COBOL code that contains the business logic, so that the form can use it. This code is supplied in a LegacyBook project containing book.cbl.

In addition, you need some wrapper code to convert the data from .NET types to COBOL types. The project uses .NET data types; these are System.String objects in our case. The book program uses COBOL types such as PIC X and PIC 99V99. The supplied program BookWrapper.cbl does this conversion, and you need to add this to the solution.

The supplied files are in the %PUBLIC%\Documents\Micro Focus\Visual COBOL\Samples and in the Forms subfolder.

To include dependant code in your Web application project, you need to add a reference to the code in your solution as follows:

  1. Right-click the solution in Solution Explorer.
  2. Click Add > Existing Project.
  3. Navigate to the Forms\BookWrapper subfolder in the Samples directory.
  4. Select the .cblproj file and click Open.
  5. Similarly, add the LegacyBook project from the Forms\LegacyBook subfolder in the Samples.
  6. Add the two projects as references to the BookDemoWebApplication project as follows:
    • Right-click BookDemoWebApplication in Solution Explorer and click Add Reference.
    • Expand Solution in the left-hand pane and then click Projects.
    • Check the BookWrapper and the LegacyBook projects and click OK.

      The projects are now added to the References folder in your solution.

Provide Access to the Legacy Code

You now need to add some code to the form to call the wrapper code:

  1. Open Default.aspx.cbl and declare the data item my-book in the working storage section, as follows:
           01 my-book   type BookWrapper.Book.
  2. Rebuild the entire solution.

    You should have no parsing errors, now that BookWrapper is declared. If you do have errors, check the supplied demonstration in the Forms\BookDemoWebApplication subfolder of the Samples to see where yours differs.

  3. In Solution Explorer, right-click the Web.config file in the BookDemoWebApplication project and click Open to open the file in the editor.
  4. In the Web.config file, add the following configuration sections after the opening tag line that starts with <configuration>:
    <!--The following code declares a section group for application configuration -->
      <configSections>
        <sectionGroup name="MicroFocus.COBOL.Application">
          <section name="Switches" type="System.Configuration.NameValueSectionHandler" />
          <section name="Environment" type="System.Configuration.NameValueSectionHandler" />
        </sectionGroup>
        <sectionGroup name="MicroFocus.COBOL.Runtime">
          <section name="Tunables" type="System.Configuration.NameValueSectionHandler" />
          <section name="Switches" type="System.Configuration.NameValueSectionHandler" />
        </sectionGroup>
      </configSections>
  5. Set up an environment variable to point to the bookfile.* data files, which are supplied in the Samples\BookData directory. To do this:

    In the Web.config file, add the following text immediately after the </configSections> line:

    <MicroFocus.COBOL.Application>
          <Switches/>
          <Environment>
             <add key="dd_bookfile" value="MyPath\bookfile.dat"/>
          </Environment>
       </MicroFocus.COBOL.Application>

    Where you need to replace MyPath with the full path to the data file bookfile.dat, which is in the BookData subfolder in the Samples directory.

Start Painting the Form

In this section, you paint the form. You can also examine the code generated. For basic help on painting a form, see the tutorial Tutorial: Developing .NET COBOL Applications.

  1. Display the empty form by right-clicking Default.aspx in the Solution Explorer and clicking View Designer.
  2. Paint a number of labels, text boxes and a button as detailed in the table below.

    To lay out the Web form, use spaces and new lines, in the same way as you do in a text editor or in HTML.

  3. Edit the properties of the controls, being careful to not double-click any of the controls.

    To view the properties of a control, click the control in the designer and view its properties in the Properties pane. You can then scroll to the relevant property and edit it.

    Double-clicking a control creates an event for the control, which we don't want to do till the next step. Edit the properties to the following values:
    Control ID Property Text Property
    Label label1 CATALOG SEARCH
    Label catalogNumberLabel Catalog Number
    TextBox textBoxStockNo (the case is significant) (blank)
    Button searchButton Search
    Label errorLabel File Status

    Also, set the Visible property to False.

    TextBox errorField (blank)

    Also, set the Visible property to False.

    Label label2 RESULTS
    Label titleLabel Title
    TextBox textBoxTitle (the case is significant) (blank)
    Label authorLabel Author
    TextBox textBoxAuthor (blank)
    Label typeLabel Type
    TextBox textBoxType (blank)
    Label priceLabel Price
    TextBox textBoxPrice (the case is significant) (blank)
    Label soldLabel Sold
    TextBox textBoxSold (blank)
    Label onHandLabel On Hand
    TextBox textBoxOnhand (blank)
    Label stockValueLabel Stock Value
    TextBox textBoxStockValue (blank)
  4. Create a click event for the Search button. Do this by double-clicking the button, which creates an event called searchButton_Click, and then displays the code that is generated for the form.
  5. Notice that the code for the searchButton_Click method doesn't do anything yet; the procedure division is empty. You can scroll through and review the rest of the generated code.
  6. You can build the solution, by selecting it in Solution Explorer and choosing Build > Build Solution. You should have no errors.

Handle the Click Events

Now you need to add the code for the button click, which needs to call the legacy COBOL program and to populate the form with the information returned.

  1. In code view, in the Default.aspx.cbl file, find the searchButton_Click method. Update the code so that it reads as follows:
           method-id searchButton_Click protected.
           working-storage section.
           01 aBook type BookWrapper.Book.
           01 anException type System.Exception.
           
           local-storage section.
           
           procedure division using by value lnkSender as object by value lnkEvent as type EventArgs.
           try
               set aBook to type BookWrapper.Book::Read(textBoxStockNo::Text)
               invoke self::PopulateForm(aBook)
           catch anException 
               invoke self::DisplayException(anException)
           end-try
           
                          
           end method.
  2. Notice the red squiggles underlining some words. These indicate a syntax error from automatic parsing happening in the background. Hover over an underlined word and read the popup that gives information on the error. Notice that the status bar tells you the number of background parsing errors. You can see the actual errors in the Error List window.
  3. Notice that the above code invokes the PopulateForm and the DisplayException method. Add the following methods to your code, after the searchButton_Click method and before the end class statement.
           method-id  PopulateForm final private.
           procedure division using aBook as type BookWrapper.Book.
    
               if aBook <> null
                   set errorLabel::Visible to false
                   set errorField::Visible to false
                   set textBoxStockNo::Text    to aBook::StockNumber
                   set textBoxTitle::Text      to aBook::Title
                   set textBoxAuthor::Text     to aBook::Author
                   set textBoxType::Text       to aBook::Type
                   set textBoxPrice::Text      to type System.Convert::ToString(aBook::RetailPrice)
                   set textBoxOnhand::Text     to type System.Convert::ToString(aBook::NumberOnHand)
                   set textBoxSold::Text       to type System.Convert::ToString(aBook::NumberSold)
                   set textBoxStockValue::Text to type System.Convert::ToString(aBook::StockValue)
               else
                   set textBoxStockNo::Text    to "****"
                   set textBoxTitle::Text      to "*************************************"
                   set textBoxAuthor::Text     to "*************************************"
                   set textBoxType::Text       to "****"
                   set textBoxPrice::Text      to "****"
                   set textBoxOnhand::Text     to "****"
                   set textBoxSold::Text       to "****"
               end-if
    
           end method.
           method-id DisplayException private.
           procedure division using by value lnkException as type System.Exception.
               set my-book to null
               set errorLabel::Visible to true
               set errorField::Visible to true
               set errorField::Text to lnkException::Message
               invoke self::PopulateForm(my-book)
           end method.
  4. Save your changes. There should be no errors in the file now.

Run the Application

You can now run the application.

  1. Right-click BookDemoWebApplication in Solution Explorer.
  2. Select Rebuild.
  3. Click Debug > Start Without Debugging.

    This starts the Web application in a new browser instance.

  4. Experiment entering information and using the Search button.

    You can search for data for catalog numbers 1111 and 2222.

Examine the Sample Code

If there were any problems with running this demonstration, you can compare your application with the same sample available in the Samples folder.

Legacy Book Program

The book.cbl program is a long-standing demonstration program that has been shipped with Micro Focus products for several years. It is written in procedural COBOL. The program reads and writes to an indexed file containing book records.

In this solution, the Book program is recompiled to managed code without any changes. Recompiling the program exposes it as a class and exposes its main entry point as a static method.

The program's Linkage section defines data as standard COBOL types, such as PIC X, which non-COBOL client programs will not understand. These types need to be mapped to .NET compatible types before communication with the client program. This mapping is done by the intermediary program BookWrapper.cbl.

Client Web Form

The client Web form Default.aspx.cbl is generated as COBOL. The user enters data into the form and receives the return data there. The client form does the following:

  1. Extracts the input data from text boxes on the form as System.Strings.
  2. Calls BookWrapper passing it the string objects.
  3. Populates the text boxes on the form with the System.Strings.

Book Wrapper Program

The BookWrapper.cbl program acts as an intermediary between the pre-existing COBOL program book.cbl and the Web form. This enables you to leave the pre-existing COBOL unchanged.

The important point here is that you need to use compatible types when mixing languages. The Web form stores the data as .NET types and yet the Book program expects data as COBOL types.

The purpose of the BookWrapper program is to map your COBOL PICTUREs to .NET System.Strings. The program receives data from the Web form as System.Strings, and maps them onto standard COBOL data types before passing them to the pre-existing book program.

The working storage declares the data items in a book record by using a copybook, as follows:

working-storage section.
        copy "book-rec-dotnet.cpy" replacing == (prefix) == by == book ==.
    ...

The copybook book-rec-dotnet.cpy declares the book-details record. It declares book-title and book-stockno as COBOL pictures and also as properties so that Getter/Setter methods can be used to access them. The copybook contains:

    01 (prefix)-details.
        03 (prefix)-text-details.
            05 (prefix)-title  pic x(50) property as "Title".
        ...
        03 (prefix)-stockno pic x(4) property as "StockNumber".

The following property method gets a pointer to the book-details record:

       property-id BookDetails pointer.
       getter. 
           set property-value to address of book-details
       end property.

The Read method is implemented as follows:

       method-id Read static. 
       local-storage section.
       01 file-status pic xx.
       procedure division using by value stockno-in as string
                          returning      myBook     as type BookWrapper.Book. 

           set myBook to new BookWrapper.Book()
           set myBook::StockNumber to stockno-in

           call "BookLegacy" using by value readRecord
                                   by value myBook::BookDetails
                                   by reference file-status       
            
           invoke self:RaiseExceptionIfError(file-status)
           goback.
       end method.

Where:

  • procedure division using ...

    shows a .NET System.String, stockno-in, being passed in from client form. It also shows an instance of the Book class being returned. BookWrapper.cbl defines a new .NET type, Book, which can be used by programs written in any .NET language.

  • set myBook to new BookWrapper.Book() 

    creates a new instance of the BookWrapper class.

  • set mybook::StockNumber

    takes the data from the .NET System.String (stockno-in) and stores it as the StockNumber property of myBook. This property is declared in the copybook as a picture string, and so the data is stored as a standard COBOL data type in book-stockno. The COBOL Compiler implicitly converts the data from the .NET string into a COBOL usage display item (pic x).

  • call BookLegacy using ...

    calls the legacy program, book.cbl. It passes it the “BookDetails” property of myBook. If you look at the code in BookWrapper.cbl, you can see that what BookDetails does is pass a pointer to the BookRecord structure defined in book-rec-net.cpy. This structure matches the structure in the old book-rec.cpy, so what the legacy Book program sees is a book record being passed in by reference – which is what it expects. Book reads the stock number from this record, reads a record from the indexed file, and then puts the data in the other fields of the record.

  • invoke self::RaiseExceptionIfError(file-status)

    checks the file status returned from reading the file, and raises a .NET exception if there was an error. Exceptions are the standard .NET mechanism for signaling error conditions.