Skip to content

Tutorial 04 09 Add Controller Class

Matt Linder edited this page Jun 1, 2023 · 22 revisions

Harmony Core Logo

Exposing Endpoints for Traditional Bridge Routines

You're almost there! Only two more steps to go, the next of which is to actually expose your Traditional Bridge routines as endpoints of your web service.

There are several ways this could be implemented, depending on what the routines do and how they may or may not relate to existing functionality exposed by existing controllers in your service. For example, if your service is exposing OData endpoints for Orders, and your Traditional Bridge routines also expose functionality related to Orders, you may choose to expose them via custom endpoint methods on your existing OrdersController class.

But it may be that your Traditional Bridge functions are not related to other controllers in your service. In that case, it probably makes sense to simply add a new custom controller class. This is what happens when you use xfServerPlus migration, which is what we're using for this tutorial.

Add the Controller Class

When we used the Harmony Core GUI tool to generate code for our solution after selecting an interface from our Synergy method catalog (SMC), code generation created a controller class for the solution. All we need to do at this point is add it to the Services.Controllers project.

  1. In Solution Explorer, right-click on the Services.Controllers project and select Add > Existing Item.

  2. In the Add Existing Item dialog, navigate to the Services.Controllers folder, select BridgeMethodsController.dbl, and click Add.

  3. Open BridgeMethodsController.dbl in the Visual Studio editor and note the following

    • The new class inherits from a base class named ControllerBase (actually Microsoft.AspNetCore.Mvc.ControllerBase), which means that it is an MVC controller (previously referred to as a "WebAPI controller").
    • The dependency injection pattern is again being used, this time to get hold of an instance of a class named BridgeMethodsService. Does that sound familiar? It should; it's the class that you wrote in the previous module of this tutorial, the one that exposes "wrapper" methods for your Traditional Bridge routines. Yes, it's all starting to come together!
    • The controller class is also decorated with a {Route("BridgeMethods")}. This specifies that the endpoints in the controller will be available at the base address of the service, which on this occasion will NOT include the /odata/v1 part, because this controller is an MVC controller, not an OData controller.
  4. The class is not decorated with an {Authorize} attribute, but it must have this attribute if authentication is enabled in your environment. So, if your environment uses custom authentication, add the {Authorize} attribute to the class:

     {Authorize}
     {Produces("application/json")}
     {Route("BridgeMethods")}
     ;;; <summary>
     ;;; BridgeMethods
     ;;; </summary>
     ;;; <remarks>
     ;;; Custom coded endpoints for interface BridgeMethods
     ;;; </remarks>
     public partial class BridgeMethodsController extends ControllerBase
     ...
    

    Then Save the file.

Adding Endpoint Methods

Similar to the BridgeMethodService class, an endpoint is added method for each of the three Traditional Bridge routines being exposed.

The GetEnvironment Endpoint Method

  1. Examine the GetEnvironment method:

     {HttpGet}
     {Route("GetEnvironment")}
     {Consumes(MediaTypeNames.Application.Json)}
     {Produces("application/json")}
     ;;; <summary>
     ;;;   Get environment string
     ;;; </summary>
     ;;; <remarks>
     ;;;   The functionality of this endpoint is based on custom code in the underlying application. 
     ;;; </remarks>
     ;;; <response code="200">OK. The operation completed successfully.</response>
     ;;; <response code="400">Bad request. The request was malformed or contained inappropriate content.</response>
     ;;; <response code="500">Internal server error. Report the issue to the API maintainer.</response>
     ;;; <returns>Returned environment string</returns>
     public async method GetEnvironment, @Task<ActionResult<GetEnvironment_Response>>
     proc
         mreturn ok(await _BridgeMethodsService.GetEnvironment())
     endmethod
    
    

As you can see, this endpoint is available at the URL BridgeMethods/GetEnvironment, and it simply makes a call to the appropriate service wrapper method, returning to the client whatever string value comes back, embedded in a 200 OK response. In this case that's really all that is needed.

The GetLogicalName Endpoint Method

  1. Now take a look at the GetLogicalName method:

     {HttpPost}
     {Route("GetLogicalName")}
     {Consumes(MediaTypeNames.Application.Json)}
     {Produces("application/json")}
     ;;; <summary>
     ;;;   Get a logical names value
     ;;; </summary>
     ;;; <remarks>
     ;;;   The functinality of this endpoint is based on custom code in the underlying application. 
     ;;; </remarks>
     ;;; <response code="200">OK. The operation completed successfully.</response>
     ;;; <response code="400">Bad request. The request was malformed or contained inappropriate content.</response>
     ;;; <response code="500">Internal server error. Report the issue to the API maintainer.</response>
     ;;; <returns></returns>
     public async method GetLogicalName, @Task<ActionResult<GetLogicalName_Response>>
         {FromBody}
         required in aRequest, @GetLogicalName_Request
     proc
         if (!ModelState.IsValid)
             mreturn BadRequest()
         mreturn ok(await _BridgeMethodsService.GetLogicalName(aRequest))
     endmethod
    
    

This endpoint method is very similar. The URL route is different of course, and there is now a parameter decorated with {FromBody}. This means that the body of each /GetLogicalName request to the service must look something like this:

 {
     "aLogicalName":"DBLDIR"
 }

The AddTwoNumbers Endpoint Method

  1. Now take a look at the AddTwoNumbers method:

     {HttpPost}
     {Route("AddTwoNumbers")}
     {Consumes(MediaTypeNames.Application.Json)}
     {Produces("application/json")}
     ;;; <summary>
     ;;;   Add two numbers
     ;;; </summary>
     ;;; <remarks>
     ;;;   The functionality of this endpoint is based on custom code in the underlying application. 
     ;;; </remarks>
     ;;; <response code="200">OK. The operation completed successfully.</response>
     ;;; <response code="400">Bad request. The request was malformed or contained inappropriate content.</response>
     ;;; <response code="500">Internal server error. Report the issue to the API maintainer.</response>
     ;;; <returns></returns>
     public async method AddTwoNumbers, @Task<ActionResult<AddTwoNumbers_Response>>
         {FromBody}
         required in aRequest, @AddTwoNumbers_Request
     proc
         if (!ModelState.IsValid)
             mreturn BadRequest()
         mreturn ok(await _BridgeMethodsService.AddTwoNumbers(aRequest))
     endmethod
    

Another similar endpoint. Of course there is a different URL route, and this time there are two parameters along with the {FromBody} attribute, meaning that the body of a request to /AdddTwoNumbers should look like this:

 {
     "number1":1.1,
     "number2":2.2
 }

Where 1.1 and 2.2 are the numbers that will be added together.

Build the Code

Before moving on, make sure the project builds:

  1. Right-click on the Services.Controllers project and select Build.

  2. Check the Output window and verify that the build was successful.

    1>------ Build started: Project: Services.Controllers, Configuration: Any CPU ------
    ========== Build: 1 succeeded, 0 failed, 2 up-to-date, 0 skipped ==========
    

Next topic: Configure Traditional Bridge Environment


Clone this wiki locally