-
Notifications
You must be signed in to change notification settings - Fork 14
Home
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.
We built our framework using best-of-breed industry standard tools, APIs, and environments, including:
- ASP.NET Core
- ASP.NET Core Web API
- ASP.NET Core OData
- ASP.NET Core Identity
- Entity Framework Core
- Swagger / OpenAPI
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.
- Our source code is hosted on GitHub.
- Our binary releases are available on NuGet.
- Our development builds are available from a private NuGet repository.
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.
Open Data Protocol (OData) is an open protocol which 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. For example, instead of writing code that exposes all customers, and then writing separate code that exposes all customer that meet a certain criteria, for example all customers in the state of California, with OData you just 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.
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.
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. You can read more about our EF Core Provider here.
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.
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.
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.
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.
-
Tutorial 2: Building a Service from Scratch
- Creating a Basic Solution
- Enabling OData Support
- Configuring Self Hosting
- Entity Collection Endpoints
- API Documentation
- Single Entity Endpoints
- OData Query Support
- Alternate Key Endpoints
- Expanding Relations
- Postman Tests
- Supporting CRUD Operations
- Adding a Primary Key Factory
- Adding Create Endpoints
- Adding Upsert Endpoints
- Adding Patch Endpoints
- Adding Delete Endpoints
-
Harmony Core Code Generator
-
OData Aware Tools
-
Advanced Topics
- CLI Tool Customization
- Adapters
- API Versioning
- Authentication
- Authorization
- Collection Counts
- Customization File
- Custom Field Types
- Custom File Specs
- Custom Properties
- Customizing Generated Code
- Deploying to Linux
- Dynamic Call Protocol
- Environment Variables
- Field Security
- File I/O
- Improving AppSettings Processing
- Logging
- Optimistic Concurrency
- Multi-Tenancy
- Publishing in IIS
- Repeatable Unit Tests
- Stored Procedure Routing
- Suppressing OData Metadata
- Traditional Bridge
- Unit Testing
- EF Core Optimization
- Updating a Harmony Core Solution
- Updating to 3.1.90
- Creating a new Release
-
Background Information