Skip to content
Steve Ives edited this page Apr 20, 2020 · 28 revisions

Harmony Core Logo

Harmony Core is an open-source framework designed to help Synergy developers build RESTful web services that expose Synergy data and business logic using OData and ASP.NET Core with minimal effort.

Harmony Core Block Diagram

We built our framework using best-of-breed industry standard tools, APIs, and environments, including:

Harmony Core consists of libraries, CodeGen templates, and recommended coding practices and conventions. Here is an example Harmony Core service that includes a home page with sample example OData queries against the sample web service.

Why REST?

We think REST is the best possible way to expose Synergy data and logic over a network. Our customers are most successful when they turn the logic and data they've worked on for the years into easily consumable black boxes of functionality. The best black boxes can be used without a proprietary protocol and without needing to make a complex series of calls that have little or no relation to one another. Maintaining state between calls is fraught with peril. It is difficult to protect a system sufficiently from misuse when a web service consumer is allowed to partially complete a transaction and then disappear. When possible, web service operations should be idempotent. If that isn't possible, they should at least strive to be atomic.

Why OData?

Open Data Protocol (OData) is an open protocol that allows the creation and consumption of queryable and interoperable RESTful APIs in a simple and standard way. When using OData for web services, we emit plain JSON data, which is easily consumable by nearly any client you can imagine. OData lets you expose the entities as operations your code supports, but it frees you from explicitly having to make every operation variant. Instead of writing code that exposes all customers, then writing other code that exposes all customer meeting certain criteria (like all customers in the state of California), with OData you simply expose the customers and let Entity Framework Core (an ASP.NET Core component) and OData handle the filtering. For example:

GET https://api.acme.com/customers?$filter=State eq 'CA'

But OData provides so much more than simple filtering. For example, if your Synergy repository includes information about the relationships between various data structures, then you can use OData to follow those relationships when querying the data. This is done using the OData $expand keyword, like this:

GET https://api.acme.com/customers(1234)?$expand=REL_Orders($select=OrderNumber,DateOrdered)

This example retrieves a single customer entity via a primary key read on the customer number, and the response will also include the order number abd order date for all orders placed by the customer. The actual data access is performed by our EF Core Provider, which translates OData queries into Synergy Select class operations.

There are many other built-in functions and predicates supported by OData, and you can learn more about them by following the OData basic tutorial. These functions dramatically reduce the amount of work you need to put into exposing Synergy logic and data via a web service.

You might be starting to wonder, what about security? Maybe you don't want to allow all of the built-in functions and predicates because certain users shouldn't have access to certain types of data. OData supports query validation, so you can implement a query validator to ensure that your extensive query functionality can only be used in the ways you deem appropriate.

Why ASP.NET Core?

ASP.NET Core is a ground-up rewrite of the entire web stack for .NET. Microsoft has applied all the lessons learned over the years with large-scale deployment of ASP.NET. What they've come up with runs on both the full .NET Framework and .NET Core, and they've significantly improved the performance and general scalability characteristics. Unlike the original ASP.NET, everything is being developed in the open on GitHub with significant community engagement and contributions.

Why Entity Framework Core?

Entity Framework Core, commonly referenced as EF Core, is a full rewrite of Entity Framework. Much the like other libraries Microsoft has been naming "Core", there has been a significant focus on portability, performance, and extensibility. The team has an explicit goal to provide support for non-relational databases (of which Synergy DBMS is one). This is a big change from the SQL-Server-centric Entity Framework 6.0 release that preceded EF Core. Because our Synergy Select class is capable of performing all the underlying read operations that EF Core supports, it is a great fit for accessing DataObjects. Write/update/delete operations are supported in our EF Core provider, but these use FileIO classes to enable custom I/O routines.

Foundational Concepts

DataObject

A DataObject is the fundamental building block in Harmony Core. DataObjects are usually generated by CodeGen from a structure defined in a Synergy repository and they inherit from Harmony.Core.DataObjectBase. DataObjects are generated with metadata that communicates the size, type, and location (position in record) of each of your fields to other parts of Harmony Core. You can read a more in-depth exploration of DataObject here.

Dependency Injection

At its most basic level, dependency injection consists of three parts. The first is an IServiceProvider. If you have an instance of IServiceProvider, you can ask it to provide you with an instance of a Type that has previously been registered. The second part is the class that needs to be constructed. For example, if your constructor takes a String parameter, it will receive an instance of a String as registered in your IServiceProvider when an object is constructed. The third part, the part that glues it all together, is ActivatorUtilities.CreateInstance<YourTypeGoesHere>(IServiceProvider). CreateInstance actually takes all the services provided by the passed-in provider and creates a new instance of the type you supplied using a type argument. For more information, see the ASP.NET Core documentation. See Wikipedia for a more general discussion.

Contexts

Harmony Core provides various implementations of IContextBase that can be used to provide highly performant thread-safe access to your Synergy logic and data. You can read more about contexts here.

ODataController

Microsoft.AspNet.OData.ODataController is the base class for controllers in OData. Methods that you want to be routable should be public, and generally should be named based on the HTTP verb you will use to call it. Dependency injection is supported for controller constructors, which means you can declare dependencies as parameters to your public constructor method. If requests for those types can be satisfied by the IServiceProvider your constructor will be called with, those parameters fill out. The following is an example method that will be invoked when the controller is called using HTTP GET without any parameters:

{ODataRoute("Orders")}
{EnableQuery(MaxExpansionDepth=3, MaxSkip=10, MaxTop=5, PageSize=4)}
public method Get, @IActionResult
proc
    mreturn Ok(DBContext.Orders)
endmethod

The above is also an example of how you can provide an explicit route path and enable (and control) the way the underlying framework can satisfy OData queries.


Next topic: Required Tools


Clone this wiki locally