This was a project done for NHS Digital in the United Kingdom. The initial work was a website where suppliers of software to the NHS could:
- register a product/s with an NHS framework
 - select which capabilities the product provides
 - select which standards the product meets
 - submit evidence to support its claimed capabilities
 - submit evidence to support its claimed standards
 - have the evidence reviewed against its claimed capabilities
 - have the evidence reviewed against its claimed standards
 - engage in dialogue with an NHSD capabilities review team
 - engage in dialogue with an NHSD standards compliance team
 - create an information page about the product
 - be approved for sale
 
The overall architecture is a classic 3-tier application ie:
- presentation
- web app in NodeJS
 
 - business logic
- C# .NET core
 
 - data storage
- relational database eg Microsoft SQL Server
 - Microsoft Dynamics CRM
 - Microsoft SharePoint
 
 
- 
RESTful APIs for data
 - 
Swagger UI for testing
 - 
pluggable datastores for supplier data (SQL database or MS Dynamics CRM)
 - 
pluggable blobstore for supplier evidence aka binary data (MS SharePoint or MongoDB)
 - 
pluggable OAuth provider (currently Auth0)
 - 
Swagger UI : https://localhost:5000/swagger/index.html
 
- .NET Core 2.1
 - Optional:
- Docker
 - Microsoft SQL Server
 
 
  git clone https://github.com/TrevorDArcyEvans/NHSBuyingCatalogue.git
  cd NHSBuyingCatalogue/beta-private/api/NHSD.GPITF.BuyingCatalog
  dotnet build
  dotnet test- Various settings are output to the console log on startup
 - Settings are obtained from:
- appsettings.json
 - hosting.json
 - autofac.json
 - nLog.config
 - user secrets file
 - environment variables
 
 
Description
| Setting | Environment Variable | Description | 
|---|---|---|
| urls | URL to host Swagger UI for testing | |
| RepositoryDatabase:Connection | DATASTORE_CONNECTION | Which database connection to use eg SqLite | 
| RepositoryDatabase:SqLite:Type | DATASTORE_CONNECTIONTYPE | Type of database to which we are connecting eg PostgreSql  Valid values: 
  | 
| RepositoryDatabase:SqLite:ConnectionString | DATASTORE_CONNECTIONSTRING | .NET connection string to database to store results  eg: ```Data Source=  | 
| UseCRM | USE_CRM | whether to use Microsoft Dynamics CRM as a datastore eg false | 
| CRM:ClientId | CRM_CLIENTID | |
| CRM:ClientSecret | CRM_CLIENTSECRET | |
| CRM:CacheExpiryMins | CRM_CACHE_EXPIRY_MINS | |
| CRM:ShortTermCacheExpirySecs | CRM_SHORT_TERM_CACHE_EXPIRY_SECS | |
| CrmUrl | GIF_CRM_URL | |
| CrmAuthority | GIF_CRM_AUTHORITY | |
| GIF:Authority_Uri | GIF_AUTHORITY_URI | default: http://localhost:5001 | 
| AzureClientId | GIF_AZURE_CLIENT_ID | |
| EncryptedClientSecret | GIF_ENCRYPTED_CLIENT_SECRET | |
| Jwt:Authority | OIDC_ISSUER_URL | |
| Jwt:Audience | OIDC_AUDIENCE | |
| Jwt:UserInfo | OIDC_USERINFO_URL | |
| SharePoint:BaseUrl | SHAREPOINT_BASEURL | |
| SharePoint:OrganisationsRelativeUrl | SHAREPOINT_ORGANISATIONSRELATIVEURL | |
| SharePoint:ClientId | SHAREPOINT_CLIENT_ID | |
| SharePoint:ClientSecret | SHAREPOINT_CLIENT_SECRET | |
| SHAREPOINT_PROVIDER_ENV | SHAREPOINT_PROVIDER_ENV | set to test to use fake SharePoint server | 
| SharePoint:FileDownloadServerUrl | SHAREPOINT_FILE_DOWNLOAD_SERVER_URL | default: http://localhost:9000/ | 
| AMQP:UseAMQP | USE_AMQP | default: false | 
| AMQP:UseAzureServiceBus | USE_AZURE_SERVICE_BUS | default: false | 
| AMQP:Protocol | AMQP_PROTOCOL | default: amqp | 
| AMQP:PolicyName | AMQP_POLICY_NAME | default: admin | 
| AMQP:PolicyKey | AMQP_POLICY_KEY | default: admin | 
| AMQP:NamespaceUrl | AMQP_NAMESPACE_URL | default: localhost:5672 | 
| AMQP:TopicPrefix | AMQP_TOPIC_PREFIX | default: topic:// | 
| AMQP:TtlMins | AMQP_TTL_MINS | default: 72460 ie 7 days | 
| Log:ConnectionString | LOG_CONNECTIONSTRING | .NET connection string to a database to send logs | 
| Log:CRM | LOG_CRM | whether or not to log communications with Microsoft Dynamics CRM eg false | 
| Log:SharePoint | LOG_SHAREPOINT | whether or not to log communications with Microsoft SharePoint eg false | 
| Log:BearerAuth | LOG_BEARERAUTH | whether or not to log communications with OAuth provider eg false | 
| Cache:Host | CACHE_HOST | .NET connection string to Redis instance | 
Sample hosting.json
{
 "urls": "http://*:5100",
 "wwwroot": "wwwroot",
 "UseCRM": false,
 "GIF":
 {
   "Authority_Uri": "http://crm:5001"
 },
 "Log":
 {
   "ConnectionString": "Data Source=|DataDirectory|Data/NHSD.GPITF.BuyingCatalog.sqlite3;",
   "CRM": true,
   "SharePoint": true,
   "BearerAuth": true
 },
 "Cache":
 {
   "Host": "localhost"
 },
 "RepositoryDatabase":
 {
   "Connection": "SqLite",
   "SqLite":
   {
     "Type": "SqLite",
     "ConnectionString": "Data Source=|DataDirectory|Data/NHSD.GPITF.BuyingCatalog.sqlite3;"
   },
   "SqlServer":
   {
     "Type": "SqlServer",
     "ConnectionString": "Data Source=localhost;Initial Catalog=BuyingCatalog;Integrated Security=True;MultipleActiveResultSets=True"
   },
   "MySql":
   {
     "Type": "MySql",
     "ConnectionString": "server=127.0.0.1;uid=NHSD;pwd=DisruptTheMarket;database=BuyingCatalog;SslMode=none"
   }
 },
 "Jwt":
 {
   "Authority": "https://buying-catalogue-beta-prototype.eu.auth0.com/",
   "Audience": "api.buying-catalogue-beta-prototype",
   "UserInfo": "https://buying-catalogue-beta-prototype.eu.auth0.com/userinfo",
 },
 "Logging":
 {
   "PathFormat": "Logs/NHSD-GPITF-BuyingCatalog-{Date}.txt",
   "IncludeScopes": false,
   "Debug":
   {
     "LogLevel":
     {
       "Default": "Warning"
     }
   },
   "Console":
   {
     "LogLevel":
     {
       "Default": "Warning"
     }
   }
 }
}Configuration keys adopt the following conventions:
- Keys are case-insensitive. For example, ConnectionString and connectionstring are treated as equivalent keys.
 - If a value for the same key is set by the same or different configuration providers, the last value set on the key is the value used.
 - Hierarchical keys
- Within the Configuration API, a colon separator (:) works on all platforms.
 - In environment variables, a colon separator may not work on all platforms. A double underscore (__) is supported by all platforms and is automatically converted into a colon.
 - In Azure Key Vault, hierarchical keys use -- (two dashes) as a separator. You must provide code to replace the dashes with a colon when the secrets are loaded into the app's configuration.
 
 - The ConfigurationBinder supports binding arrays to objects using array indices in configuration keys. Array binding is described in the Bind an array to a class section.
 
Configuration values adopt the following conventions:
- Values are strings.
 - Null values can't be stored in configuration or bound to objects.
 
Logging is provided by nLog its settings are in nLog.config
Typical SQL script to create a log table would be:
-- MS SQL Server
CREATE TABLE Log 
(
  Timestamp DATETIME2,
  Loglevel TEXT,
  Callsite TEXT,
  Message TEXT
);
CREATE INDEX IDX_Timestamp ON Log(Timestamp);
-- MySQL aka MariaDB
CREATE TABLE Log 
(
  Timestamp DATETIME,
  Loglevel TEXT,
  Callsite TEXT,
  Message TEXT
);
CREATE INDEX IDX_Timestamp ON Log(Timestamp);
-- PostgreSQL
CREATE TABLE Log 
(
  "Timestamp" TIMESTAMP,
  "Loglevel" TEXT,
  "Callsite" TEXT,
  "Message" TEXT
);
CREATE INDEX IDX_Timestamp ON Log("Timestamp");
-- SQLite
CREATE TABLE Log 
(
  Timestamp TEXT,
  Loglevel TEXT,
  Callsite TEXT,
  Message TEXT
);
CREATE INDEX IDX_Timestamp ON Log(Timestamp);


