Skip to content

This is a .NET Core MVC API to demonstrate a potential backend-for-frontend architecture to be consumed by a client application.

Notifications You must be signed in to change notification settings

epiusers-help/EpicorBridge_Template

Repository files navigation

EpicorBridge

.NET Core Web API Facade to present layer for external applications to consume Epicor API. This could be combined with other services in addition to Epicor for a unified application interface connecting an app to Epicor. This app is intended to be run as a web service behind a firewall or application gateway and acts as a proxy between the client application and Epicor services.

Disclaimer

This example application relies on the calling application to pass an api_key (separate from an Epicor API Key) in the query parameter of each call to authenticate the calling app against a known value, which is configured in the app settings. One should take a layered approach to security and not rely on this alone. This is intended to demonstate one way to limit client application access to the API.

Configuration

Connection Configuration

In the app settings, you will see an EpiSettings node. This is where the application is configured to connect to your Epicor instance. This example also utilizs a single company, but it could be extended to multi-company interaction.

Config Setting Where From
Host Epicor Host Server Name
Company Company ID
Instance Epicor Instance Name
ApiKey Epicor API Key generated upon API Key Creation
IntegrationUser Epicor User Account ID for Integration
IntegrationPassword Epicor User Account Password for Integration
LicenceTypeGuid Licence Type Guid for this app to run under ( "00000003-9439-4B30-A6F4-6D2FD4B9FD0F" for WebService License Type)

To establish the known secret between client app and this app, create a client secret in the api_key node. image

Other settings could be configured here as well.

Application Organization

The application is organized into two main sections. The Utils folder holds classes and services responsible for client API Key Authentication, Epicor Session brokering, Epicor Connection settings, and static Function and BAQ definitions that are consumed in this app.

image

EpiUtils is responsible for exposing methods to log into Epicor and grab a SessionID passed in subsequent calls. This is typically done upon app start or after a period of inactivity. This service is instantiated as a singleton upon app start.

EpiSessionSvc runs as a hosted background service upon app start to login to Epicor and periodically refresh its session. Note; this sometimes does not gracefully shut down if the application is put into a dormant state.

EpiFunctions holds a static definiton list of which Function Libraries and Functions are consumed. This was done to allow changes to a particular Epicor Function name without changing the place where it is consumed in this application.

EpiBAQs holds a static definition list of which BAQs are consumed.

EpiAPIConnect is the main service that is injected into each controller and allows the controller to call a Function or BAQ service. It contains two methods; ExecuteBAQ or InvokeFunction.

ApiKeyAuthAttribute checks all requests for the presence of a matching api_key defined in the configuration file.

All GET calls have OData $top and $filter parameters available.

Configuring BAQs

In this example, I provided 3 BAQs and examples of how to call them. Typically, one could organize your BAQ section by domain (i.e. Customer BAQs, Contact BAQs, etc.) in this list, however it is not a requirement and the BAQ name can be passed as a string instead.

Configuring Functions

In this example, I am showing how to call a custom Epicor Function Library and its functions, however since it is rather specific from company to company, this should be used to demonstrate structural functionality (no pun intended) rather than execution functionality.

EpiAPIConnect

This is a special service that is instantiated as a scoped service upon app start. In each controller responsible for extending endpoints that in turn call the Epicor API, this service should be made available by dependency injection. It follows a predicatble pattern; 1 method to call a BAQ, 1 method to invoke a function. Within both BAQ and Function calls, the SessionID and ClaimedLicense headers are added to the call to Epicor.

In the ExecuteBAQ method, the call is passed a BAQ ID, an IQueryCollection of any forwarded query string, and finally an HTTP Verb. This will typically be GET or PATCH on a BAQ. Of note; BAQ call responses are trimmed down to their value node and exlude any other metadata. Function calls are of the response type defined in the Function out parameters. If metadata is required, one could simply return the entire response and not just the value node. image image image

In the InvokeFunction method, the call is passed a Function Library name, the Function ID, and a collection of data (JSON) as a dynamic object to be forwarded on as the Function request parameters. The HTTP verb to invoke is always POST, so this is built into the call. When passing JSON into an endpoint that calls a Function, I use the [FromBody] tag to indicate the location of the data and is always of type dynamic. Classes could be used to define the JSON in true MVC style, but I've found the dynamic object gets the job done (with a little help from some well placed remarks in the source. image

Controllers

There is one controller shown with several examples of presenting endpoints and calling the EpiAPIConnect within them. Extending the solution to multiple domains is very easy; simply create your controller by domain, inject the EpiAPIConnect service, and build away. image

Controller Routes

In this example I configured the controller routes to follow the pattern [Route("api/v{version:apiVersion}/[controller]/[action]")] as indicated in the route annotation in the controller. This could be changed if needed but provides a high level of predictability when extending the solution to many endpoints.

Starting and Consuming the app

The app is pre-configured to use port 44372 but this can be changed. Starting the app will spin up the services and grab an Epicor Session. The app Swagger UI page is available to test with. image

Prior to using the Swagger page, the ApiKey must be filled out with the client api_key variable. image

From there, the calls can be made.

Consuming the application

Once the app is deployed and hosted on a web server (I used IIS for mine), the API is available to call. Example: https://hostserver:port/api/v1/samplecustomer/getcustomerlist/?$top=10&api_key=apikeyvalue

Conclusions

Hopefully this gives a good starting point for building out a flexiable backend-for-frontend application layer. This allows one to decouple their front end technology and Epicor (or any other related services) into a unified API.

About

This is a .NET Core MVC API to demonstrate a potential backend-for-frontend architecture to be consumed by a client application.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages