Alliance Business Suite

Alliance Business Suite

Version Documentation License: ABS EULA Twitter: fenixalliance

Welcome to the Alliance Business Suite!

The Alliance Business Suite is a set of intelligent, extensible, multi-tenant applications built to enable users to jumpstart their business through the acceleration of several core aspects of any given business.

The Alliance Business Suite gives users a Modular, Full-Stack, Low-Code Application Framework built on top of the Alliance Business Platform.

Both client and server code are written in C#, allowing users to extend the product with their own code through Module libraries. It builds upon next-generation technologies such as Blazor, SignalR, Razor Pages, and MVC through .NET, an open-source and cross-platform framework for building web-mobile apps using C#, with or without the use of JavaScript.

The power of the Alliance Business Suite can be leveraged from small personal blogs, eCommerce platforms, and professional portfolios to the infrastructure of large corporations.

About the Alliance Creed

We're designed to succeed when you and your business succeed; that's why we're committed to helping as many people as possible to harness their entire potential. By building on top of word-class technologies, we're designing this solution to jumpstart your business without having to worry about any of the complexity and technical aspects. We simply want to help you make your life easier while increasing your odds for success through the right tools and support on the path to digitalization.

The fact is, since our inception, we've steered towards creating a culture designed to reach beyond expectations together by building an organization whose success strategy is to help others to succeed.

Well then. What do I get?

We are creating our applications in such a form that they deliver as much value to your business and cause as we can. They work primarily as an interface for users to manage their services, products, and cloud resources. But the truth is that isn't limited to just that.

Our applications are being developed to give you access to every functionality that we implement for our business, to power your business and vision as well. This is because if we can add value to our business and gain a competitive advantage through these tools, chances are you can too!

So far, we've created a few extensions and connectors for the Alliance Business Suite, but you can extend it too! Some of these extensions are open source, so feel free to check their code for extension reference.

Connectors are always free and you can find them on your ABS Extensions page, and some of our extensions have free tiers. You will get the Alliance Business Suite Community Edition, for free, with the following Modules:

  • ABS Contact Sight. (CRM)
  • ABS Media Portals. (CMS)
  • ABS Accounting. (AMS)
  • ABS Learning. (LMS)
  • ABS Social Networks. (Intranet Social Network)
  • ABS IAM (Identity and Access Management)
  • Infinity Comex (eCommerce Engine)

To learn more about our privacy policy, please visit: https://fenixalliance.com.co/legal/policies/privacypolicy

User Guide

Getting Started

  • Install .NET 5 SDK (v5.0.100).

  • Install the latest edition (v16.8 or higher) of Visual Studio 2019 (Community, Professional, or Enterprise Editions) with the ASP.NET and web development workload enabled. Alliance Business Suite works with ALL editions of Visual Studio from Community to Enterprise. If you do not have a SQL Server installation available already and you wish to use LocalDB for development, you must also install the .NET desktop development workload.

  • Download a release or Clone the ABS. Portal repository to your local system using Git. Open the FenixAlliance.ABS.Portal.sln solution file and Build the solution. Make sure you specify FenixAlliance.ABS.Portal as the Startup Project and then Run the application.

Installing an official release:

Additional Instructions

  • If you have already installed a previous version of Alliance Business Suite and you wish to do a clean database install, simply point the DefaultConnection value in the ABS Portal Settings Manager to a fresh database record. This will trigger a re-install when you run the application which will execute the database installation scripts.

  • Every ABS Repo ignores appsettings.json by default, so as long as you don't delete the directive from .gitignore, you're cleared to submit a pull request.

Video Series

  • If you are getting started with Alliance Business Suite, a series of videos are available which explain how to install the product, interact with the user interface, and develop custom modules.

Documentation

There is a separate Documentation repository, which contains various types of documentation for the Alliance Business Suite, including the C# API documentation for every class on every library. The contents of the repository are available at https://docs.absuite.net as interactive documentation.


Easy Install

The Easy Way: As a Docker Container.

docker pull FenixAlliance.ABS:latest

Conventional Install

git clone https://github.com/FenixAlliance/ABS.Bin
cd ABS.Bin
./FenixAlliance.ABS.Studio.exe

or

dotnet FenixAlliance.ABS.Studio.dll

As application dependency

Add the NuGet package

dotnet add package FenixAlliance.ABS.Hub --version latest

Register Services and Configuration

using FenixAlliance.ABS.Hub.Extensions;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting.Server.Features;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using System;

namespace FenixAlliance.ABS
{
    public class Startup
    {
        public IHostEnvironment Environment { get; set; }
        public IConfiguration Configuration { get; }

        // Constructor
        public Startup(IConfiguration Configuration, IHostEnvironment Environment)
        {
            this.Environment = Environment;
            this.Configuration = Configuration;
        }

        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
          services.AddAllianceBusinessSuite(Configuration, Environment);
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app)
        {
          app.UseAllianceBusinessSuite(Configuration, Environment);
        }
    }
}

Release Announcements

Alliance Business Suite v1.2

Example Screenshots

ABS Studio Dashboard:

image.png

ABS Extensions:

The ABS is absolutely modular. Whether you need to add pages, products, or posts with no code at all (using the ABS Web Designer), modify the style or layout, or add your own Types, Controllers, Pages, Views, Components, or Tag Helpers

ABS Extensions

ABS Commander Terminal:

The ABS Commander Terminal is a Built-In functionality that allows users to execute commands against the ABP set of APIs.

ABS Commander Terminal

ABS WOPI Connector:

The ABS Workplace Module allows users to create, view, and edit Office files with Office for the web, right from their ABS Instances. It also allows users to manage files for pretty much every entity type.

ABS WOPI Connector

ACS Bot Maker:

The Alliance Conversational Services Bot Maker Platform is an ABS extension that allows users to create conversational flows using NLP and a graphical UI.

ABS Bot Maker

Versioning

Maintaining forward and backward compatibility is a key goal of the ABS. Therefore, the ABS now uses only additive versioning, which means any revision of the ABM following the "2.0" release will not:

  • Introduce new mandatory attributes on previously published entities, or change an optional attribute to be mandatory
  • Rename previously published attributes or entities
  • Remove previously published attributes

🤝 Contributing

Contributions, issues, and feature requests are welcome!
Feel free to check issues page. You can also take a look at the contributing guide.

  1. Issue Guidelines
  2. Report Security Vulnerabilities
  3. Pull Request Requirements
  4. Translations
  5. Chart of Accounts

Show your support

Give this project a ⭐️ if this project helped you!

Author

👤 Fenix Alliance Inc.

Logo and Trademark

The brand name Alliance Business Suite and its logos are trademarks of Fenix Alliance S.A.S in Colombia and Fenix Alliance Inc in other countries ("Fenix Alliance").

Fenix Alliance owns and oversees the trademarks for the ABS name and logos. We have developed this trademark usage policy with the following goals in mind:

  • We’d like to make it easy for anyone to use the ABS name or logo for community-oriented efforts that help spread and improve ABS.
  • We’d like to make it clear how ABS-related businesses and projects can (and cannot) use the ABS name and logo.
  • We’d like to make it hard for anyone to use the ABS name and logo to unfairly profit from, trick, or confuse people who are looking for official ABS resources.

Licensing and Contributions

Your access to and use of the Alliance Business Suite's source code is governed by the Fenix Alliance's End User License Agreement "EULA". If you don't agree to those terms, as amended from time to time, you are not permitted to access or use the Alliance Business Suite.

We welcome any contributions to the Alliance Business Suite development through pull requests on GitHub. Most of our active development is in the develop branch, so we prefer to take pull requests there (particularly for new features). We try to make sure that all new code adheres to the Fenix Alliance coding standards. All contributions are governed by the terms of the EULA.

A note about your account and the privacy of your information.

The Alliance Passport Services engine is built on top of a highly compliant service to keep your identity private. This engine supports Facebook, Microsoft Accounts, Google+, LinkedIn, and many other identity providers, but you can also integrate your own.

We think that it's also worth pointing out that we DO NOT store any identity information into our databases; instead, that data is always encrypted and sent to the same systems that governments and enterprises worldwide are using to keep your data safe, and then we access that data by using industry-standard protocols so that you can rest assured that your sensitive information is protected through various security controls in addition to multi-factor authentication.

To learn more about our privacy policy, please visit: https://fenixalliance.com.co/legal/policies/privacypolicy

Legal Notices

Fenix Alliance and any contributors grant you a license to the documentation and other content in this repository under the Creative Commons Attribution 4.0 International Public License and grant you a license to any code in the repository under the ABS EULA.

Fenix Alliance, Alliance Business Suite, Infinity Comex, and/or other Fenix Alliance's products and services referenced in the documentation may be trademarks or registered trademarks of Fenix Alliance Inc. in the United States/or other countries. The licenses for this project do not grant you rights to use any of Fenix Alliance's names, logos, or trademarks. Fenix Alliance's general trademark guidelines can be found at http://docs.fenix-alliance.com.

Privacy information can be found at https://fenix-alliance.com/legal/policies/privacypolicy

Fenix Alliance and any contributors reserve all other rights, whether under their respective copyrights, patents, or trademarks, whether by implication, estoppel, or otherwise.

Alliance Business Suite - Low-Code Next-Generation Business Development Platform. | Product Hunt

About this Documentation

Welcome to the Alliance Business Suite documentation! We are on the mission to create the Ultimate Business Development Platform to provide you an unprecedented suite of capabilities to ensure your business can exceed customer's expectations through next-generation experiences.

We believe that knowing your customers and your business enables you to personalize each experience and optimizes efficiencies so you can earn customers for life.

This documentation is constantly being developed and adapted to the latest version of the Alliance Business Suite and its goal is to provide an extensive guide for technical and non-technical audiences alike. At a very high level, this documentation provides guides on how to perform common tasks within the Alliance Business Suite, but it also digs deeper, sometimes, into technical details; but don't worry, we'll let you know the technical difficulty at the beginning of every guide.

Some guides contained in this documentation require special Business Permissions or installable software. Requirements, if any, will be highlighted at the beginning of each guide.

Some parts of this documentation are still being developed and changes are made to it every day, so please feel free to request further explanation or provide feedback about features you would like us to explain in more detail.

Contributing to the Alliance Business Suite and/or its documentation

Woohoo! You've decided to contribute? That's amazing! We want to make contributions to the Alliance Business Suite as easy and frictionless as we can. Contributing requires a GitHub account. If you don't have an account, follow the instructions for the GitHub account setup.

Then, you just need to create an Issue to report bugs, propose APIs, request features and tooling, propose designs and improvements.

All of these contributions will be filled as Issues on the Alliance Business Suite Documentation Repository and they adhere to the Issue Management Policy.

Roadmap

This project is a work in progress and the schedule for implementing enhancements is dependent upon the availability of community members who are willing/able to assist. For a more comprehensive look at our roadmap, please visit our Progess Board.

V.1.3 ( release: July 12, 2022 )

  • Node.js SDK
  • PowerShell SDK
  • .NET 6.0 LTS Update
  • Agreement Template Definitions
  • Email Signature Template Definitions
  • Document Template Definitions
  • Article Template Definitions
  • gRPC Modularization
  • Reporting Dashboard
  • Dynamic Dashboards
  • gRPC Modularization
  • ACS Modularization
  • UBL 2.1 Support
  • Process Canvas.
  • Granular Property Set Access
  • Custom Includes Definitions
  • Virtual Entity Data Sources
  • Studio Static Localization
  • In-Portal Live Chat Widget
  • Code Editor: Razor Syntax Highlighting
  • ML-Based Search Results Ranking Engine
  • ML-Based Fraud Detection Engine (Anomaly Detection), (Binary Classification)
  • ML-Based Price Prediction Engine
  • ML-Based Sales Spike Detection Engine (Anomaly Detection)
  • ML-Based Sales Forecasting Engine (Regression), (Time Series)
  • ML-Based Sentiment Analysis Engine
  • ML-Based Customer Segregation Engine (Clustering)
  • ✅ ML-Based Natural Language Processing Engine
  • ✅ ML-Based eCommerce Recommendation Engine
  • ✅ Template Definitions
  • ✅ ML-Based Spam Detection Engine
  • ✅ In-Studio Live Chat Manager
  • ✅ Code Editor: Diagnostics Highlighting
  • ✅ Workflow Manager Engine (Experimental)
  • ✅ Workflow Visual Designer (Experimental)
  • ✅ ML-Based Language Detection Engine
  • ✅ Fluid Support (Experimental)
  • ✅ Email Template Definitions
  • ✅ Blazor Support (Experimental)
  • ✅ Options & Settings API
  • ✅ .NET SDK

V.1.2 LTS ( release: July 12, 2021 )

  • ✅ Custom Options Manager
  • ✅ Custom Portal Option Definitions
  • ✅ Virtual SPA Support (Angular/React)
  • ✅ Razor Templating Engine
  • ✅ Live Web Designer Integration
  • ✅ Dynamic Entity Views
  • ✅ Content Live Builder
  • ✅ Custom Controller Definitions
  • ✅ Portal Settings Manager UI
  • ✅ Custom Option Definitions
  • ✅ Custom Service Endpoint Definitions
  • ✅ Custom Web Portal Resources
  • ✅ Alliance Passport Services (Auth Engine)
    • ✅ TOTP MFA Enabled
    • ✅ Local Account Support
    • ✅ Microsoft Identity Integration
    • ✅ Twitter Identity Integration
    • ✅ Facebook Identity Integration
    • ✅ Google Identity Integration
    • ✅ Azure AD Identity Integration
    • ✅ Azure AD B2C Identity Integration
    • ✅ Okta Identity Integration (Preview)
    • ✅ AWS Cognito Identity Integration
    • ✅ Default Identity Management
  • ✅ Module Manager Dashboard
    • ✅ Trusted Publisher Rules
    • ✅ Module Assembly Manager
    • ✅ Managed Module Support
    • ✅ Unmanaged Module Support

V.1.1 ( release: July 12, 2020 )

  • ✅ Authentication / User Management / Profile Management
  • ✅ Authorization / Roles Management / Granular Permissions
  • ✅ Blazor Support
  • ✅ Cross-Platform Database Support ( MySQL, MSSQL )
  • ✅ Dynamic CSS/Lazy Loading
  • ✅ Dynamic Page Compositing Model / Site & Page Management
  • ✅ Dynamic Routing
  • ✅ Dynamic Swagger Specs
  • ✅ EF Core Migrations for Database Installation / Upgrade
  • ✅ Enabled for Infinity Comex (eCommerce Extension)
  • ✅ Event Logging / Audit Trail
  • ✅ Extensibility via Custom Modules
  • ✅ Extensibility via Custom Themes
  • ✅ Folder / File Management (Azure Storage, File System)
  • ✅ GraphQl API with Voyager, GraphiQl y GraphQl Playground
  • ✅ Headless API with Swagger Support
  • ✅ HealthCheck Rules with UI Support
  • ✅ i18n Enabled (Based on GeoAPI and Custom Settings)
  • ✅ Improved JavaScript reference support
  • ✅ In-App CLI (Studio Commander)
  • ✅ Infinity Comex Support (ABS' eCommerce Engine)
  • ✅ JavaScript Lazy Loading
  • ✅ Modular Architecture
  • ✅ Multi-Currency Support
  • ✅ Multi-Portal ( Monolith & Microservice Distributed )
  • ✅ Multi-Tenant ( Shared Database & Isolated Database )
  • ✅ Notifications / Email Delivery
  • ✅ Notifications / SMTP Delivery
  • ✅ Progressive Web Application Support
  • ✅ Recycle Bin
  • ✅ REST API with Swagger Support
  • ✅ Scheduled Flows ( Background Processing )
  • ✅ Scheduled Jobs ( Background Processing )
  • ✅ Seamless Upgrade Experience
  • ✅ Slack integration (OAuth)
  • ✅ Support For Additional Authentication Providers (OAuth)

Constant Considerations

  • ✅ Code Annotations
  • ✅ A11y Improvements
  • ✅ i18n Improvements
  • ✅ UI/UX Improvements
  • ✅ 100% Code Coverage
  • ✅ Security Improvements
  • ✅ SOLID Code Improvements
  • ✅ Performance Improvements
  • ✅ Scalability Improvements
  • ✅ Extensibility Improvements
  • ✅ Generic Integrations Improvements
  • ✅ Developer productivity enhancements
  • ✅ Separation of Concerns Improvements
  • ✅ Bug fixes & core Dependency Management

Alliance Business Suite API References

System requirements

The following browsers are supported:

  • Google Chrome
  • Microsoft Edge (supported on Windows 10)
  • Apple Safari 11
  • Internet Explorer 11
  • Quad-core x64 2 GHz CPU or higher (x64 compatible dual-core 1.5 GHz processor)
  • 16GB Memory (8GB Memory)
  • 40GB free hard disk space (10GB free hard disk) SSD Recommended

Supported Operating Systems

The following operating systems are supported with the recommendation that the latest Windows updates are applied.

  • Windows Server 2012 R2 x64 Datacenter / Standard
  • Windows Server 2016 x64 Datacenter w/ Containers
  • Windows Server 2016 x64 Datacenter w/ Containers

Supported SQL Server Editions

The following SQL Server Editions are supported with the recommendation that the latest Windows updates are applied.

  • SQL Server 2019
  • SQL Server 2017
  • SQL Server 2016
  • Azure SQL Service

Internet Information Services (IIS)

  • IIS 10, Windows Server 2016
  • IIS 10.0, Windows 10 & Windows Server 2019

Optional Software Components

  • SQL – SQL Word Breakers
  • SQL – SQL Server Agent Service
  • SQL – Server Full-Text Indexing

Getting Started with the Alliance Business Suite

Data is at the center of every modern business, unlocking new paths and ideas for operational performance and customer experience, but gathering and analyzing data is rather a complicated, time-consuming task. In an increasingly globalized world, technology is a key differentiator between those who stay ahead and those who don't.

To help businesses across the world to harness this promise, we've created a digital solution aimed to give organizations the ability to cover their main operations without constraining our customers with opinionated business development platforms.

The Alliance Business Suite lets you build outstanding and secure web and mobile apps. This is what you need to get started:

  1. Get an Alliance Business Suite license:

  2. Install the Alliance Business Suite

  3. Start building your business

Alliance Business Suite Fundamentals

This article provides an overview of key topics for understanding how to develop Alliance Business Suite apps.

Tutorial: Get started with the Alliance Business Suite

This tutorial shows how to create and run your first Alliance Business Suite instance.

You'll learn how to:

  • [✔] Install an Alliance Business Suite instance.
  • [✔] (optional) Trust the development certificate.
  • [✔] Run the app.

In the end, you'll have a working Alliance Business Suite instance running on your local machine.

Prerequisites

  • .NET Core 6.0 SDK or later
  • MySQL Server 8.0 or later

Installation

Conventional Install

git clone https://github.com/FenixAlliance/ABS.Bin
cd ABS.Bin
./FenixAlliance.ABS.Studio.exe

or

dotnet FenixAlliance.ABS.Studio.dll

Development Install

Install as a Docker Container.

docker pull FenixAlliance.ABS:latest

Install as an Application Extension

There are certain cases where customers prefer to install the Alliance Business Suite so that they can extend the standard functionalities, create modules, integrations, SPAs, or really, any kind of extensions without having to worry about all the required wiring for it to work properly.

In these cases, the best approach is to install the Alliance Business Suite as an application extension into a new or existing ASP.NET Application.

To do this:

  1. Add the NuGet package
dotnet add package FenixAlliance.ABS.Hub --version latest
  1. Register Services and Configuration
using FenixAlliance.ABS.Hub.Extensions;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting.Server.Features;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using System;

namespace FenixAlliance.ABS
{
    public class Startup
    {
        public IHostEnvironment Environment { get; set; }
        public IConfiguration Configuration { get; set; }

        // Constructor
        public Startup(IConfiguration Configuration, IHostEnvironment Environment)
        {
            this.Environment = Environment;
            this.Configuration = Configuration;
        }

        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
          services.AddAllianceBusinessSuite(Configuration, Environment);
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app)
        {
          app.UseAllianceBusinessSuite(Configuration, Environment);
        }
    }
}
  1. Trust the HTTPS development certificate:

cert.png

Select Yes if you agree to trust the development certificate.

Installation wizard

The Alliance Business Suite uses the suitesettings.json configuration file to determine whether or not the Alliance Business Suite instance is already configured to work. The Status section of the configuration file is used to instruct the system on the current configuration step.

The first step towards having an operational instance is to set up the basic options such as Database Connections Strings, seeding the database, create the primary Business Tenant, and the root account holder.

Customers can achieve this installation through a web wizard aimed to beat WordPress's 5 Minutes installation.

On this wizard, you'll be prompted with a few configuration steps:

1. Primary Database Options

Primary Database Options

2. Business Tenant Basic Information

Business Tenant Basic Information

3. Primary Portal Basic Information

Primary Portal Basic Information

4. Identity Provider Options

Identity Provider Options

5. Root Account Credentials

Root Account Credentials

Fill in the required information on each step and click on "Install". This will create the ABM Scheme to the Database, seed data such as countries, currencies, states, cities, timezones, the selected COA, and other important, standardized data. The creation and seeding process might take up to 5 minutes, depending on your connection and system's specifications.

Seeding Process

Let the application finish this process, reload the page & log in with the Root Account credentials defined in previous steps.

Configuring an Alliance Business Suite Instance

Short Notation for this page

  • Acting Business Tenant ("ABT")
  • Current Web Portal ("CWP")

The Alliance Business Suite is designed to be as easy to use as it can be by abstracting complexity through a clean UI and multiple navigation features designed to take you where you need to perform.

Once installed, your instance will be functional, but not quite yet ready for production. For this reason, new instances are created with a Not Operational Status. This Status means that even new users can be created and pretty much every functionality will work right out of the box, several unconfigured functionalities won't be available until proper setup.

In order to get your instance to an Operational State, you should first configure for the first time the Alliance Passport Service, perform some internal configurations, and properly set up your Root Web Portal.

Configuring your instance

One of the most important files in your Alliance Business Suite instance is the suitesettings.json file. This file is located in the root of your instance's file directory and contains your website’s base configuration details, such as database-connection information.

When you first download the Alliance Business Suite, this file does not exist, as it will be created during the initial setup process.

Although you can manually provide a suitesettings.json file for your instance (bypassing like so the initial setup process), you will be required to run this initial setup process at least once to create your initial database schema and insert required records.

Once this installation process has been completed, multiple instances can retrieve their configuration files through the ABS Management API from the root instance, and thus sharing the data layer, allowing customers to scale both the data and application layer independently, depending on their specific requirements.

Each Alliance Business Suite instance contains its own administrator portal. Instances are bounded each a Business Tenant's Primary Web Portal's configuration.

The first towards configuring your Root Web Portal is to finish creating information for your Business Tenant. The amount of configuration required will depend on the number of Modules included in your instance.

Note: Although currently possible, it is not recommended to edit the suitesettings.json file directly unless required.

Administration Flow Optimization

Due to the massive amount of different types of data that the Alliance Business Suite is built to manage, and the tremendous amount of control given to our customers, it can be easy to get lost among all the different options and configurations available. We understand this and We want your workflow to be as fluid as possible, so we've been tackling this issue through several shortcuts and UI optimizations that will help you manage your business tenant's with an incredibly high APM ("Actions per Minute") rate.

These optimizations include:

  1. Drastically reducing the number of page loads required to manage everything inside the Alliance Business Suite: Our goal is to bring this number to 1, meaning that once you're into the Alliance Business Studio,
  2. Drastically reducing the number of clicks required to get from point A to point B inside the application: Our goal is to provide multiple ways to get you where you need to be across your business tenants.
  3. Optimizing performance and improving both UX/UI to deliver clear, readable interfaces to manage data across Business Tenants.
  4. Including accessibility features to improve the way people with limitations interact with the application.
  5. Delivering additional interfaces other than the Studio to help Customers to automate and extend

Understanding the GenericOption Table and the Options API.

The GenericOption Table

To maximize your ability to extend the Alliance Business Suite, we've created the GenericOptions table, which is a table containing a few columns to store optional and configuration data for external applications without the need to modify nor extend the Alliance Business Model Schema, not to bring another data persistence mechanism.

The options table stores a different kind of data from the other tables: instead of storing data about your Web Portal's content, it stores data about the Web Portal itself. Data is written to the options table using the Options API, both of which consist of a set of functions used to add, update and delete data from this table.

The Options API

To make it easier for developers to create custom configurations, we've created a set of methods specified into the IOptionsService interface. This interface comes configured with its default implementation right out of the box, but custom implementations could override this default implementation.

As the GenericOption table stores data which is related to the setup and administration of the site as a whole, access to it is restricted. The Alliance Business Studio gives users the ability to modify the value of each configuration given the proper permissions to do so.

To be able to amend settings and options, users will need to have the manage_options Business Permission. The only default user role with this capability is the root role.

This means that if you need to add options that other user roles have access to, you'll have to assign the manage_options capability to them. This carries risks, so only do it if you're sure!

Structure of the GenericOption Table

The options table has a similar structure to the three metadata tables. It has the following fields:

  • ID: The Global Unique Identifier for every option.
  • Name: The Option Name for Friendly Access
  • Value: The option value, usually stored in JSON format.
  • Autoload: (boolean) whether or not this option would be loaded on memory cache.
  • Timestamp: The time for the last option update.
  • Transient: whether or not this option is a temporal option.
  • WebPortalID: The ID for the Web Portal who owns this option.
  • Discriminator: The Option Type.

Option Types.

GenericOptins have different types (also called scopes). As of v1.3.0, the following types are available:

  • AccountHolderOption: An option that's bound to an account holder and, optionally, to a Web Portal.
  • BusinessOption: An option that's bound to a Business Tenant and, optionally, to a Web Portal.
  • BusinessApplicationOption: An option that's bound to a Business Application and, optionally, to a Web Portal.

Aditional considerations

One of the important things to understand about the GenericOption table is the autoload field. This contains a boolean value (yes or a no). This essentially controls whether or not it is loaded on cached memory by the OptionsService.LoadOptions() function. Autoloaded data is data that is loaded on every page of your Alliance Business Suite instance. Just like we showed you how to disable certain scripts from loading sitewide, the same idea applies here. The autoload attribute is set to “yes” by default for developers, but not every option should be loaded on every page.

Hosting the Alliance Business Suite

You can deploy the Alliance Business Suite on-premises (self-hosted). Unlike cloud deployments, when you choose an on-premises deployment, different system requirements like hardware type, sizing, and functionality needs to be considered. This chapter contains guides on self-hosted/on-premise deployments.

Getting Started

Hosting the Alliance Business Suite on IIS

Internet Information Services (IIS) is a flexible, secure and manageable Web Server for hosting web apps, including ASP.NET Core.

Supported platforms

The following operating systems are supported:

  • Windows 10 or later
  • Windows Server 2012 R2 or later

The Alliance Business Suite is a 64-bit (x64) for the following reasons:

  • Requires the larger virtual memory address space available to a 64-bit app.
  • Requires the larger IIS stack size.
  • Has 64-bit native dependencies.

Install the ASP.NET Core Module/Hosting Bundle

Download the installer using the following link:

Current .NET Core Hosting Bundle installer (direct download)

For more detailed instructions on how to install the ASP.NET Core Module, or installing different versions, see Install the .NET Core Hosting Bundle.

Publish an Alliance Business Suite instance to IIS

Create the IIS site

  1. On the IIS server, create a folder to contain the Alliance Business Suite folders and files. In a further step, the folder's path is provided to IIS as the physical path to the app. For more information on an app's deployment folder and file layout, see ASP.NET Core directory structure.

  2. In IIS Manager, open the server's node in the Connections panel. Right-click the Sites folder. Select Add Website from the contextual menu.

  3. Provide a Site name and set the Physical path to the app's deployment folder that you created. Provide the Binding configuration and create the website by selecting OK.

  4. Confirm the process model identity has the proper permissions: If the default identity of the app pool (Process Model > Identity) is changed from ApplicationPoolIdentity to another identity, verify that the new identity has the required permissions to access the app's folder, database, and other required resources. For example, the app pool requires read and write access to folders where the app reads and writes files.

Warning

Top-level wildcard bindings (http://*:80/ and http://+:80) should not be used. Top-level wildcard bindings can open up your app to security vulnerabilities. This applies to both strong and weak wildcards. Use explicit hostnames rather than wildcards. Subdomain wildcard binding (for example, *.mysub.com) doesn't have this security risk if you control the entire parent domain (as opposed to *.com, which is vulnerable).

Clone the Alliance Business Suite Distributable

The best way to manage the Alliance Business Suite Update Flow is to clone the Alliance Business Suite to the publish directory using Git.

  1. Navigate to the Publish Directory, make sure is empty, and open a CLI into it.
  2. Run the following command: git clone https://github.com/fenixalliance/abs.bin .
    • If you're unable to deploy directly to the IIS site folder on the IIS server, pick your desired ring from the Releases Repo and clone on removable media and physically move them to the IIS site folder on the server, which is the site's Physical path in IIS Manager. Move the contents of the cloned repository to the IIS site folder on the server, which is the site's Physical path in IIS Manager.
    • If you're unable to use git, you'll face additional considerations regarding the Update Process.
  3. Restart the IIS Site.

Browse the website

The app is accessible in a browser after it receives the first request. Make a request to the app at the endpoint binding that you established in IIS Manager for the site.

Logging across the Alliance Business Suite

The Alliance Business Suite contains a powerful logging engine based on Serilog, a popular .NET library that provides diagnostic logging that's built with powerful structured event data in mind.

using Serilog;

var position = new { Latitude = 25, Longitude = 134 };
var elapsedMs = 34;

Log.Information("Processed {@Position} in {Elapsed:000} ms.", position, elapsedMs);

This example records two properties, Position and Elapsed along with the log event. The properties captured in the example, in JSON format, would appear like:

{"Position": {"Latitude": 25, "Longitude": 134}, "Elapsed": 34}

The @ operator in front of Position tells Serilog to serialize the object passed in, rather than convert it using ToString().

The :000 segment following Elapsed is a standard .NET format string that affects how the property is rendered. The console sink included with Serilog will display the above message as:

09:14:22 [Information] Processed { Latitude: 25, Longitude: 134 } in 034 ms.

Through the Alliance Business Studio, customers are able to manage these logs without the need to access the server directly.

To manage logs for your Alliance Business Suite instance, navigate to the /Studio/Network/Logs route on any configured Web Portal.

Understanding Request Routing through the Alliance Business Suite

The Alliance Business Suite contains a powerful routing engine based on .NET's Routing System.

At a high level, routing is responsible for matching incoming HTTP requests and dispatching those requests to the Alliance Business Suite's executable endpoints. Endpoints are the app's units of executable request-handling code. Endpoints are defined in the app and configured when the app starts. The endpoint matching process extracts values from the request's URL and provides those values for request processing. Using endpoint information from the app, routing is also able to generate URLs that map to endpoints.

The Alliance Business Suite's routing configurations abstract the complexities out of the routing process through several techniques depending on the execution context. This means that routing is as simple as providing a relative URL ("Slug") when creating a page.

In cases where customers might want to create a custom Module, they can expose custom endpoints while still taking advantage of the Routing Engine, meaning they can create and manage routing rules through the Alliance Business Studio and apply them to their custom endpoints.

Rate limiting

The Alliance Business Platform contains a rate-limiting solution designed to control the rate of requests that clients can make to a Web API or MVC app based on IP address or client ID. Through the Alliance Business Studio, you can configure the rate-limiting middleware and set multiple limits for different scenarios like allowing an IP or Client to make a maximum number of calls in a time interval. You can define these limits to address all requests made to an API or you can scope the limits to each executable API URL or HTTP verb and path.

Working with static files.

This topic describes the overall functionality for the Alliance Business Platform | File System Engine, how to upload static files into an Alliance Business Suite instance, and how to retrieve the URL and file name that can be used to request that file.

About Uploading Files on Studio

The Alliance Business Platform contains a powerful file system engine called ABP-FS. Through ABP-FS, users can upload files and relate them to almost any ABM Record. By exposing several API endpoints on both code and REST APIs, users can upload files of any kind. Default restrictions are provided for security purposes, and files can also be uploaded through FTP or through the Alliance Business Studio (using the GUI file manager).

File Upload Scopes

By leveraging the ABP-FS APIs, customers and developers can upload files scoped to an Alliance Business Model Record; this allows customers to access, manage, and share files related to, for example, an Account, a Contact, or a Portal, in one place.

Public Files.

Scoped Public Files

The ABP-FS allows customers to upload public files within the scope of a Web Portal. These files are exposed through the /Public/{PortalID} endpoint available to every portal.

Unscoped Public Files

When developing single or multiple portals, customers might want to share common files between them. To do so, they can now upload Unscoped Public Files that will be available through the /Public endpoint.

Unscoped files are marked as read-only files by default and can only be uploaded by an Account Holder with global_admin Business Permission.

Public Files URL

Regardless of how you upload a file, you can retrieve the file URL by using the Alliance Business Studio File Manager or by recomposing the URL from the File Path by prepending the /Public/ endpoint to it, so that it is relative to the /AppData/Public folder where both Scoped and Unscoped Public Files are uploaded.

Accessing data from the Alliance Business Model engine.

If you've ever had to bring data from multiple systems and applications together, you know what an expensive and time-consuming task that can be. Without being able to share and understand the same data easily, each application or data integration project requires a custom implementation.

The Alliance Business Model simplifies this process by providing a common data model that includes entities that represent commonly used business concepts and activities, such as Contact, Invoice, and Account, to simplify the creation, aggregation, and analysis of data.

Why use the Alliance Business Model?

Commonly, businesses have more than one application to cover specific business operations such as eCommerce, Accounting, Sales, Marketing, CRM, and more. These are a lot of applications and they consume time and money, but that's not it! they all have different representations for the Contact Entity. This can be frustrating when trying to integrate these applications together to produce better and automated outcomes. To solve this issue, you can build those apps on top of a standardized data schema, allowing you to share the same entities across applications. Of course, your application might have different data requirements between them, so you can extend the predefined schemas and even create new schemas!

One cool thing about this is that when it comes the time to create a new business application, your data schemas will be ready to provide the required data infrastructure for your application and share this data with every other application.

Alliance Business Model simplifies data management and app development by unifying data into a known form and applying structural and semantic consistency across multiple apps and deployments. To summarize the benefits:

  • A unified shape, where data integrations can combine existing enterprise data with other sources and use that data holistically to develop apps or derive insights.
  • Structural and semantic consistency across applications and deployments.
  • Simplified integration and disambiguation of data that's collected from processes, digital interactions, product telemetry, people interactions, and so on.
  • The ability to extend the Alliance Business Model schema standard entities to tailor the model to your organization. This is enabled thanks to both the ABM Mongo Interop Service and the ABS Virtual Entities functionalities.

Alliance Business Model in action

The Alliance Business Model is influenced by data schemas that are present in both UBL Schema and Common Data Model, covering a range of business areas. If you are a customer or a partner of Fenix Alliance Group, you are already using the Alliance Business Model.

Businesses, institutions, Partners, and independent software vendors (ISVs) use the Alliance Business Model to extend and interoperate with any given Alliance Business Suite instance.

Organizations from industries such as manufacturing, government, and education are working closely with Fenix Alliance Group to extend the Alliance Business Model to their specific business scenarios, and the dynamic ABM Engine allows seamless data integration even when schemas are not exactly the same. This allows customers from an unlimited range of industries to leverage the benefit of the Alliance Business Model's standard entities and extend to their specific verticals so that industry solutions can interoperate more easily.

// Get all the contacts from the configured ABM Provider.
var contacts = await DataContext.Contact.ToListAsync();

foreach(var contact in contacts){
    Console.WriteLine(contact.ID);
}

Introduction to Razor Templating Engine

Portal Pages can make coding page-focused scenarios easier and more productive than using controllers and views.

This document provides an introduction to the Alliance Business Suite - Razor Templating Engine

#Rendering HTML The default Razor language is HTML. Rendering HTML from Razor markup is no different than rendering HTML from an HTML file. HTML markup in .cshtml Razor files is rendered by the server unchanged.

#Razor syntax Razor supports C# and uses the @ symbol to transition from HTML to C#. Razor evaluates C# expressions and renders them in the HTML output.

When an @ symbol is followed by a Razor reserved keyword, it transitions into Razor-specific markup. Otherwise, it transitions into plain C#.

To escape an @ symbol in Razor markup, use a second @ symbol:

<p>@@Username</p>

The code is rendered in HTML with a single @ symbol:

<p>@Username</p>

HTML attributes and content containing email addresses don't treat the @ symbol as a transition character. The email addresses in the following example are untouched by Razor parsing:

<a href="mailto:Support@contoso.com">Support@contoso.com</a>

Implicit Razor expressions

Implicit Razor expressions start with @ followed by C# code:

<p>@DateTime.Now</p>
<p>@DateTime.IsLeapYear(2016)</p>

With the exception of the C# await keyword, implicit expressions must not contain spaces. If the C# statement has a clear ending, spaces can be intermingled:

<p>@await DoSomething("hello", "world")</p>

Getting Started with Alliance Business Suite Web Portals

The Alliance Business Suite includes a powerful multi-portal CMS to help businesses to offer external-facing websites that allow users outside their organizations to sign in with a wide variety of identities, create and view data in and from the Alliance Business Model, or even browse content anonymously. The full capabilities of Alliance Business Suite Portals are available as of Version 1.2.

You have the ability to create a Portals Web Portals Network ("WPN") for each Business Tenant by using the multi-portal feature. Business tenants can create as many Web Portals under the same instance as they need.

Web Portals are scoped to a Business Tenant to allow customers to deliver experiences that directly transact data with the Alliance Business Model and additional Data Sources. This means that users can perform a controlled (yet extensible) number of actions (like adding products to their cart, update their profile, create addresses, generate orders, access quotes, invoices and so much more)

How do Portals Work?

Web Portals are content sets that belong to a Business Tenant. Portals make use of the powerful Alliance Business Suite Razor Engine to group Web Content under a single domain.

Configuring Domains

Compared with a typical single-portal ABS instance, a WPN installation has additional considerations.

Every fresh Alliance Business Suite instance comes with one default Portal owned by the Business Tenant that was created through the installation process. This Root Portal must exist and is defined by your instance's settings file.

Alliance Business Suite Portals can have additional related domains/subdomains.

Domains should resolve to your instance's public IP Address. Also, domains should be related to a portal for the multi-tenant data router to work properly.

Themes and Modules

When you enable a WPN Instance: each Web Portal of a network can activate both modules and themes individually, but installation is done at an instance scope, which means they are available to every Web Portal present on your instance.

You must have access to your domain's DNS settings.

Configuring a Multi-Portal Network

1. Preparing your instance

Unless this is a fresh install and you have no data to lose, please backup your database and file system.

2. Select a Business Tenant

When you create a new portal, you do so under the scope of a Business Tenant. This means that you should have permissions from the Business Tenant to access the Studio and "create_portals" at the very least.

3. Create Web Portal

To create a Web Portal, login as an authorized user and select the Business Tenant that will own the Web Portal.

Acting as the selected Business Tenant, click on the cogs icon on the top-right hand side of the Studio Header.

Click on Portals and provide a Title and a root domain (the Root Domain should be a Subdomain of the Root Portal's Root Domain. This means that every portal's Root Domain is relative to the domain that you used to install your instance).

E.g: If you installed your instance under the https://example.com domain, each subsequent Web Portal will have a Root Domain that's scoped to the Root Portal's domain, like so: https://NewPortalRootDomain.example.com

4. Create a Primary Domain (optional)

In order to set up another domain that's not related to the Root PortalDomain, you should create a security rule to allow traffic through certain domains and then map the rule to your new Web Portal.

5. Create Additional Domains (optional)

You can have more than one domain mapping to the same Web Portal. You can choose whether or not this mapping should be performed through an HTTP redirection. To create and map an additional domain to a Web Portal, create the new domain under the Admin section for your Business Tenant, under Admin > Security > Domains. Then, navigate to the portal that this Domain should map to and select it from the domains tab.

Working with Web Pages

Web pages are meant to represent content located at a particular URL, scoped to a Web Portal (and therefore to a Business Tenant), and is based on one of the core tables of the Alliance Business Model Schema.

Web Pages are related through parent and child relationships to other web pages, this structure forms the hierarchy of a website, and therefore, its site map is automatically generated.

Web pages also form the basis for including other, specialized table types in the portal site map – web files, shortcuts, forums, advanced forms, and blogs are all situated in the portal site map through – and thus derive their URLs from – a relationship to a parent web page.

Manage web pages

Web pages can be created, edited, and deleted from the Alliance Business Platform REST API. However, the Media Portals Module provides advanced customization that can be performed from the Alliance Business Studio.

  • Open the Alliance Business Studio.

  • Go to Modules > Media Portals > Web Pages.

    • To edit an existing web page using the standard editor, select the "Edit" option below the web page name.
    • To edit an existing web page using the Visual WYSIWYG editor, select the "Live Edit" option below the web page name.
    • To create a new Web Page, click on the Create Button.
  • Enter appropriate values in, at least, the required fields.

  • Select Save & Close.

Content Engines

The Alliance Business Suite contains a powerful content engine to provide the level of customizability required to give the highest level of control over every bit that's to be presented to a user on a Web Page. These engines are meant to work with Web Content records and they have several capability sets.

Razor Engine:

The Razor Engine is a derivate from .NET's Server Side Markup Language. Web Content marked as .razor will be compiled and rendered using a Service Abstraction which means that its default can be replaced by a custom implementation.

Razor is a markup syntax that lets you embed server-based code (Visual Basic and C#) into web pages at a very high level.

Server-based code can use every available service inside any given Alliance Business Suite instance to dynamically generate web content on the fly, while a web page is written to the browser.

When a web page is called (either by slug or id), the server executes the server-based code inside the page before it returns the page to the browser. The code can perform complex tasks by running on the server, like accessing the Alliance Business Model or leveraging our extensive set of APIs.

Razor is based on ASP.NET and designed for creating web applications. The ABS Razor Engine has the power of traditional Razor, but it is easier to use.

Blazor Engine

The Alliance Business Suite lets you build interactive web UIs using C# instead of JavaScript. By using Blazor under the hood, apps are composed of reusable web UI components implemented using C#, HTML, and CSS. Both client and server code is written in C#, allowing you to share code and libraries already present.

Liquid Engine (Experimental)

The Alliance Business Suite supports Liquid template language, which is a secure template language that is also very accessible for non-programmer audiences.

HTML Engine

In cases where customers decide to use plain HTML5, the Alliance Business Suite contains the ability to bypass all Content Engines and render HTML fragments whenever they are called. This is also the most efficient type of Web Content.

Markdown Engine

The last Content Engine, and therefore the least privileged, is the Markdown Engine, which is a lightweight markup language for creating formatted plain text using an embedded markdown-text editor.

Razor Pages Introduction

Pages are very important components for the Alliance Business Suite. They allow customers to implement unique, visually outstanding web pages by using a templating engine that's based on .NET's Razor Syntax.

Pages in the Alliance Business Suite can be added through the Admin Portal of your ABS instance and live edited through the ABS Web Builder.

Pages are WebContent Components, which makes them extremely powerful. They are stored in the Alliance Business Model Database provider and C# is server-side evaluated to then render the output as HTML, CSS, and JavaScript.

Although pages can inject services and even interact with the ABM Database Provider through the DataContext instance present at every page, pages can optionally contain a caller method. This method's responsibility is to produce the model that's going to be used to fill the page's Model property, sort of like a controller method passing a Model to a view.

Creating a Web Page

To create a Web Page in the Alliance Business Suite you must have Studio Access (access_studio) permission and the create WebContent entities permission (create_webcontent).

  • Head to your ABS Instance's Admin Portal at https://{yourdomain}/admin
  • Select the Business Tenant for which you want to create a Web Page.
  • Click on the Add button of your Command Bar and Select Web Page
  • Give the entry a Title, a Slug, and (optionally) select a template and parent page to use on the page.
  • Write some code using the Razor Syntax and the Code Editor.
  • Validate your code for errors.
  • Save Changes.

Once you've saved changes for your Web Page, the system will automatically redirect you to the Edition page. Here you will be able to edit everything about your page, and new options will be available, such as categorization and tags.

Page Routing

Pages must define a "Slug". This relative route gets combined with the parent's page slug to produce the Absolute Slug of the page and defines the route over which your page will be located and invoked. It can be changed at any time.

Currently, Pages other than the Home Page are available at the /Pages/{AbsoluteSlug} route.

Home Page

Each portal on the Alliance Business Suite must be provided with a Home Page. this can be any page you've created and it will allow each portal to find the page that will be rendered at the root of the portal. Customers can mark a page as the Home Page by ticking the respective option on a portal-related or by setting the page on each Portal's Options Manager.

If you set a portal-related page as the home page by ticking the "Is Home Page" option, that will replace any other Home Page related to that specific portal, becoming, like so, the Active Home Page.

The above is a legacy method for Home page discovery. To improve consistency across portals, we've implemented a new method to select the Home Page on the Portal's Options Manager. To use the new method, head to your Instance's administration portal and over General Settings, select the page you would like to render at the root of each portal.

Client-Side UI Frameworks

The Alliance Business Suite is configured to allow customers to use, right out of the box, several UI Frameworks such as:

These frameworks can be enabled or disabled on a template basis to allow customers to create and combine unique experiences with the tools they already use and love.

ABS Razor Syntax

Razor is a markup syntax for embedding server-based code into web pages. The Razor syntax consists of Razor markup, C#, and HTML. Files containing Razor generally have a .cshtml file extension. Razor is also found in Razor components files (.razor).

Razor syntax

Razor supports C# and uses the @ symbol to transition from HTML to C#. Razor evaluates C# expressions and renders them in the HTML output.

When an @ symbol is followed by a Razor reserved keyword, it transitions into Razor-specific markup. Otherwise, it transitions into plain C#.

To escape an @ symbol in Razor markup, use a second @ symbol:

<p>@@Username</p>

The code is rendered in HTML with a single @ symbol:

<p>@Username</p>

HTML attributes and content containing email addresses don't treat the @ symbol as a transition character. The email addresses in the following example are untouched by Razor parsing:

<a href="mailto:Support@contoso.com">Support@contoso.com</a>

Implicit Razor expressions

Implicit Razor expressions start with @ followed by C# code:

<p>@DateTime.Now</p>
<p>@DateTime.IsLeapYear(2016)</p>

With the exception of the C# await keyword, implicit expressions must not contain spaces. If the C# statement has a clear ending, spaces can be intermingled:

<p>@await DoSomething("hello", "world")</p>

Implicit expressions cannot contain C# generics, as the characters inside the brackets (<>) are interpreted as an HTML tag. The following code is not valid:

<p>@GenericMethod<int>()</p>

The preceding code generates a compiler error similar to one of the following:

  • The "int" element wasn't closed. All elements must be either self-closing or have a matching end-tag.
  • Cannot convert method group 'GenericMethod' to non-delegate type 'object'. Did you intend to invoke the method?`

Generic method calls must be wrapped in an explicit Razor expression or a Razor code block.

Templated Razor delegates

Razor templates allow you to define a UI snippet with the following format:

Explicit Razor expressions

Explicit Razor expressions consist of an @ symbol with balanced parenthesis. To render last week's time, the following Razor markup is used:

<p>Last week this time: @(DateTime.Now - TimeSpan.FromDays(7))</p>

Any content within the @() parenthesis is evaluated and rendered to the output.

Implicit expressions, described in the previous section, generally can't contain spaces. In the following code, one week isn't subtracted from the current time:

<p>Last week: @DateTime.Now - TimeSpan.FromDays(7)</p>

The code renders the following HTML:

<p>Last week: 7/7/2016 4:39:52 PM - TimeSpan.FromDays(7)</p>

Explicit expressions can be used to concatenate text with an expression result:

@{
    var joe = new Person("Joe", 33);
}

<p>Age@(joe.Age)</p>

Without the explicit expression, <p>Age@joe.Age</p> is treated as an email address, and <p>Age@joe.Age</p> is rendered. When written as an explicit expression,

Age33

is rendered.

Explicit expressions can be used to render output from generic methods in .cshtml files. The following markup shows how to correct the error shown earlier caused by the brackets of a C# generic. The code is written as an explicit expression:

<p>@(GenericMethod<int>())</p>

Expression encoding

C# expressions that evaluate to a string are HTML encoded. C# expressions that evaluate to IHtmlContent are rendered directly through IHtmlContent.WriteTo. C# expressions that don't evaluate to IHtmlContent are converted to a string by ToString and encoded before they're rendered.

@("<span>Hello World</span>")

The preceding code renders the following HTML:

&lt;span&gt;Hello World&lt;/span&gt;

The HTML is shown in the browser as plain text: Hello World

HtmlHelper.Raw output isn't encoded but rendered as HTML markup.

Warning: Using HtmlHelper.Raw on unsanitized user input is a security risk. User input might contain malicious JavaScript or other exploits. Sanitizing user input is difficult. Avoid using HtmlHelper.Raw with user input.

@Html.Raw("<span>Hello World</span>")

The code renders the following HTML:

<span>Hello World</span>

Razor code blocks

Razor code blocks start with @ and are enclosed by {}. Unlike expressions, C# code inside code blocks isn't rendered. Code blocks and expressions in a view share the same scope and are defined in order:

@{
    var quote = "The future depends on what you do today. - Mahatma Gandhi";
}

<p>@quote</p>

@{
    quote = "Hate cannot drive out hate, only love can do that. - Martin Luther King, Jr.";
}

<p>@quote</p>

The code renders the following HTML:

<p>The future depends on what you do today. - Mahatma Gandhi</p>
<p>Hate cannot drive out hate, only love can do that. - Martin Luther King, Jr.</p>

In code blocks, declare local functions with markup to serve as templating methods:

@{
    void RenderName(string name)
    {
        <p>Name: <strong>@name</strong></p>
    }

    RenderName("Mahatma Gandhi");
    RenderName("Martin Luther King, Jr.");
}

The code renders the following HTML:

<p>Name: <strong>Mahatma Gandhi</strong></p>
<p>Name: <strong>Martin Luther King, Jr.</strong></p>

Implicit transitions

The default language in a code block is C#, but the Razor Page can transition back to HTML:

@{
    var inCSharp = true;
    <p>Now in HTML, was in C# @inCSharp</p>
}

Explicit delimited transition

To define a subsection of a code block that should render HTML, surround the characters for rendering with the Razor tag:

@for (var i = 0; i < people.Length; i++)
{
    var person = people[i];
    <text>Name: @person.Name</text>
}

Use this approach to render HTML that isn't surrounded by an HTML tag. Without an HTML or Razor tag, a Razor runtime error occurs.

The <text> tag is useful to control whitespace when rendering content:

  • Only the content between the tag is rendered.
  • No whitespace before or after the tag appears in the HTML output.

Explicit line transition

To render the rest of an entire line as HTML inside a code block, use @: syntax:

@for (var i = 0; i < people.Length; i++)
{
    var person = people[i];
    @:Name: @person.Name
}

Without the @: in the code, a Razor runtime error is generated.

Extra @ characters in a Razor file can cause compiler errors at statements later in the block. These compiler errors can be difficult to understand because the actual error occurs before the reported error. This error is common after combining multiple implicit/explicit expressions into a single code block.

Control structures

Control structures are an extension of code blocks. All aspects of code blocks (transitioning to markup, inline C#) also apply to the following structures:

Conditionals @if, else if, else, and @switch

@if controls when code runs:

@if (value % 2 == 0)
{
    <p>The value was even.</p>
}

else and else if don't require the @ symbol:

@if (value % 2 == 0)
{
    <p>The value was even.</p>
}
else if (value >= 1337)
{
    <p>The value is large.</p>
}
else
{
    <p>The value is odd and small.</p>
}

The following markup shows how to use a switch statement:

@switch (value)
{
    case 1:
        <p>The value is 1!</p>
        break;
    case 1337:
        <p>Your number is 1337!</p>
        break;
    default:
        <p>Your number wasn't 1 or 1337.</p>
        break;
}

Looping @for, @foreach, @while, and @do while

Templated HTML can be rendered with looping control statements. To render a list of people:

@{
    var people = new AccountHolder[]
    {
          new AccountHolder(){...},
          new AccountHolder(){...},
          ...
    };
}

The following looping statements are supported:

@for

@for (var i = 0; i < people.Length; i++)
{
    var person = people[i];
    <p>Name: @person.Name</p>
    <p>Age: @person.Age</p>
}

@foreach

@foreach (var person in people)
{
    <p>Name: @person.Name</p>
    <p>Age: @person.Age</p>
}

@while

@{ var i = 0; }
@while (i < people.Length)
{
    var person = people[i];
    <p>Name: @person.Name</p>
    <p>Age: @person.Age</p>

    i++;
}

@do while

@{ var i = 0; }
@do
{
    var person = people[i];
    <p>Name: @person.Name</p>
    <p>Age: @person.Age</p>

    i++;
} while (i < people.Length);

Compound @using

In C#, a using statement is used to ensure an object is disposed. In Razor, the same mechanism is used to create HTML Helpers that contain additional content. In the following code, HTML Helpers render a

tag with the @using statement:

@using (Html.BeginForm())
{
    <div>
        Email: <input type="email" id="Email" value="">
        <button>Register</button>
    </div>
}

@try, catch, finally

Exception handling is similar to C#:

@try
{
    throw new InvalidOperationException("You did something invalid.");
}
catch (Exception ex)
{
    <p>The exception message: @ex.Message</p>
}
finally
{
    <p>The finally statement.</p>
}

@lock

Razor has the capability to protect critical sections with lock statements:

@lock (SomeLock)
{
    // Do critical section work
}

Comments

Razor supports C# and HTML comments:

@{
    /* C# comment */
    // Another C# comment
}
<!-- HTML comment -->

The code renders the following HTML:

<!-- HTML comment -->

Razor comments are removed by the server before the webpage is rendered. Razor uses @* *@ to delimit comments. The following code is commented out, so the server doesn't render any markup:

@*
    @{
        /* C# comment */
        // Another C# comment
    }
    <!-- HTML comment -->
*@

Directives

Razor directives are represented by implicit expressions with reserved keywords following the @ symbol. A directive typically changes the way a view is parsed or enables different functionality.

Understanding how Razor generates code for a view makes it easier to understand how directives work.

@{
    var quote = "Getting old ain't for wimps! - Anonymous";
}

<div>Quote of the Day: @quote</div>

The code generates a class similar to the following:

public class _Views_Something_cshtml : RazorPage<dynamic>
{
    public override async Task ExecuteAsync()
    {
        var output = "Getting old ain't for wimps! - Anonymous";

        WriteLiteral("/r/n<div>Quote of the Day: ");
        Write(output);
        WriteLiteral("</div>");
    }
}

@functions

The @functions directive enables adding C# members (fields, properties, and methods) to the generated class:

@functions {
    // C# members (fields, properties, and methods)
}

For example:


@functions {
    public string GetHello()
    {
        return "Hello";
    }
}

<div>From method: @GetHello()</div> 

The code generates the following HTML markup:

<div>From method: Hello</div>

The following code is the generated Razor C# class:


using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc.Razor;

public class _Views_Home_Test_cshtml : RazorPage<dynamic>
{
    // Functions placed between here 
    public string GetHello()
    {
        return "Hello";
    }
    // And here.
#pragma warning disable 1998
    public override async Task ExecuteAsync()
    {
        WriteLiteral("\r\n<div>From method: ");
        Write(GetHello());
        WriteLiteral("</div>\r\n");
    }
#pragma warning restore 1998
}

@functions methods serve as templating methods when they have markup:


@{
    RenderName("Mahatma Gandhi");
    RenderName("Martin Luther King, Jr.");
}

@functions {
    private void RenderName(string name)
    {
        <p>Name: <strong>@name</strong></p>
    }
}

The code renders the following HTML:

<p>Name: <strong>Mahatma Gandhi</strong></p>
<p>Name: <strong>Martin Luther King, Jr.</strong></p>

@implements

The @implements directive implements an interface for the generated class.

The following example implements System.IDisposable so that the Dispose method can be called:


@implements IDisposable

<h1>Example</h1>

@functions {
    private bool _isDisposed;

    ...

    public void Dispose() => _isDisposed = true;
}

@inherits

The @inherits directive provides full control of the class the view inherits:

@inherits TypeNameOfClassToInheritFrom

The following code is a custom Razor page type:

using Microsoft.AspNetCore.Mvc.Razor;

public abstract class CustomRazorPage<TModel> : RazorPage<TModel>
{
    public string CustomText { get; } = 
        "Gardyloo! - A Scottish warning yelled from a window before dumping" +
        "a slop bucket on the street below.";
}

The CustomText is displayed in a view:

@inherits CustomRazorPage<TModel>

<div>Custom text: @CustomText</div>

The code renders the following HTML:

<div>
    Custom text: Gardyloo! - A Scottish warning yelled from a window before dumping
    a slop bucket on the street below.
</div>

The following code is an example of a strongly-typed view:

@inherits CustomRazorPage<TModel>

<div>The Login Email: @Model.Email</div>
<div>Custom text: @CustomText</div>

If "rick@contoso.com" is passed in the model, the view generates the following HTML markup:


<div>The Login Email: rick@contoso.com</div>
<div>
    Custom text: Gardyloo! - A Scottish warning yelled from a window before dumping
    a slop bucket on the street below.
</div>

@model

The @model directive specifies the type of the model passed to a view or page:

@model TypeNameOfModel

The class generated inherits from DynamicComponentBase:

public class Template : DynamicComponentBase<TypeNameOfModel>

Razor exposes a Model property for accessing the model passed to the view:

<div>The Login Email: @Model.Email</div>

The @model directive specifies the type of the Model property. The directive specifies the T in RazorPage that the generated class that the view derives from. If the @model directive isn't specified, the Model property is of type dynamic. For more information, see C# Strongly typed models and the @model keyword.

@namespace

The @namespace directive:

Sets the namespace of the class of the generated Razor page

@namespace Your.Namespace.Here

@using

The @using directive adds the C# using directive to the generated view:

@using System.IO
@{
    var dir = Directory.GetCurrentDirectory();
}
<p>@dir</p>

Templated Razor delegates

@<tag>...</tag>

The following example illustrates how to specify a templated Razor delegate as a Func<T,TResult>. The dynamic type is specified for the parameter of the method that the delegate encapsulates. An object type is specified as the return value of the delegate. The template is used with a List of Pet that has a Name property.

@using FenixAlliance.ABM.Models.Logistics.Stock.Item
@{
    Func<dynamic, object> itemTemplate = @<p>Item SKU: <strong>@item.SKU</strong>.</p>;

    var items = new List<Item>
    {
        new Item { SKU = "AAD_BASIC" },
        new Item { SKU = "RIGHTSMANAGEMENT" },
        new Item { SKU = "MCOPSTNC" }
    };
}

The template is rendered with items supplied by a foreach statement:

@foreach (var item in items)
{
    @itemTemplate(item)
}

Rendered output:

<p>Item SKU: <strong>AAD_BASIC</strong>.</p>
<p>Item SKU: <strong>RIGHTSMANAGEMENT</strong>.</p>
<p>Item SKU: <strong>MCOPSTNC</strong>.</p>

You can also supply an inline Razor template as an argument to a method. In the following example, the Repeat method receives a Razor template. The method uses the template to produce HTML content with repeats of items supplied from a list:

@using Microsoft.AspNetCore.Html

@functions {
    public static IHtmlContent Repeat(IEnumerable<dynamic> items, int times,
        Func<dynamic, IHtmlContent> template)
    {
        var html = new HtmlContentBuilder();

        foreach (var item in items)
        {
            for (var i = 0; i < times; i++)
            {
                html.AppendHtml(template(item));
            }
        }

        return html;
    }
}

Using the list of items from the prior example, the Repeat method is called with:

  • List of Items.
  • Number of times to repeat each item.
  • Inline template to use for the list items of an unordered list.
<ul>
    @Repeat(items, 3, @<li>@item.SKU</li>)
</ul>

Rendered output:

<p>Item SKU: <strong>AAD_BASIC</strong>.</p>
<p>Item SKU: <strong>AAD_BASIC</strong>.</p>
<p>Item SKU: <strong>AAD_BASIC</strong>.</p>
<p>Item SKU: <strong>RIGHTSMANAGEMENT</strong>.</p>
<p>Item SKU: <strong>RIGHTSMANAGEMENT</strong>.</p>
<p>Item SKU: <strong>RIGHTSMANAGEMENT</strong>.</p>
<p>Item SKU: <strong>MCOPSTNC</strong>.</p>
<p>Item SKU: <strong>MCOPSTNC</strong>.</p>
<p>Item SKU: <strong>MCOPSTNC</strong>.</p>

Razor reserved keywords

Razor keywords

  • namespace
  • functions
  • inherits
  • model
  • section

Razor keywords are escaped with @(Razor Keyword) (for example, @(functions)).

C# Razor keywords

  • case
  • do
  • default
  • for
  • foreach
  • if
  • else
  • lock
  • switch
  • try
  • catch
  • finally
  • using
  • while

C# Razor keywords must be double-escaped with @(@C# Razor Keyword) (for example, @(@case)). The first @ escapes the Razor parser. The second @ escapes the C# parser.

Reserved keywords not used by Razor

  • class

Getting started with ABS Blazor Pages

The Alliance Business Suite Portals include Blazor Support (Server-Side). ABS Blazor Pages are based on components. A component in Blazor is an element of UI, such as a page, dialog, or data entry form.

To the Alliance Business Suite, Blazor Components are .NET C# classes built into .NET assemblies that:

  • Define flexible UI rendering logic.
  • Handle user events.
  • Can be nested and reused.
  • Live scoped to a Web Portal, therefore, to a Business Tenant.
  • Are stored in the Alliance Business Model as Web Pages / Web Components.
  • Can be shared and distributed as Razor class libraries or NuGet packages.

Creating a Blazor Component inside the Alliance Business Suite requires some basic knowledge of how traditional Blazor Components work.

The component class is usually written in the form of a Razor markup page. Components in Blazor are formally referred to as Razor components and their only difference with ABS Components is the way they are compiled.

Razor is a syntax for combining HTML markup with C# code designed for developer productivity. Razor allows you to switch between HTML markup and C# in the same file with IntelliSense programming support in Visual Studio. Razor Pages and MVC also use Razor. Unlike Razor Pages and MVC, which are built around a request/response model, components are used specifically for client-side UI logic and composition.

Blazor uses natural HTML tags for UI composition. The following Razor markup demonstrates a Blazor Page that displays a list of Stock Items stored into the Alliance Business Model:

@page "/Pages/test"

@using Microsoft.EntityFrameworkCore
@inject FenixAlliance.ABM.Data.DataContext db

@foreach(var item in Model){
    <h1>@item.Title</h1>
}

<button class="btn btn-primary" @onclick="IncrementCount">Click me</button>


@code {
    List<FenixAlliance.ABM.Models.Logistics.Stock.Item.Item> Model {get;set;} = new();

    private void GetProducts()
    {
        Model = db.Item.ToList();
    }

}

In this example, GetProducts is a C# method triggered by the button's onclick event. This method queries the Alliance Business Model for Stock items and then projects the results onto a List of Stock Items.

Fundamentals

Enabling Blazor Support

Enabling Blazor Support is a process that's done at the Template/Page Level. This means that to enable Blazor Support, both Web Page and Web Template should meet certain conditions.

Initializing Blazor at the Template level:

To enable Blazor support on a Web Template, you should add at least these two tags to it, as following:

<!DOCTYPE html>

<html class="no-js" lang="en">

<head>
    <!-- This tag is required to enable blazor support -->
    <base href="/" />
    ....
</head>
<body>
    ....

    @Body

    ....

    <!-- This tag is required to enable blazor support -->
    <script src="_framework/blazor.server.js"></script>

</body>

</html>


Initialize Blazor when the document is ready

The following example starts Blazor when the document is ready:

<body>
    ....

    @Body

    ....

    <script src="_framework/blazor.server.js" autostart="false"></script>
    <script>
      document.addEventListener("DOMContentLoaded", function() {
        Blazor.start();
      });
    </script>
</body>

Initializing Blazor at the Page/Component level:

To enable Blazor for a page or component, you just need to select .razor as the Code Type for any WebPage/WebComponent. If .razor Code Type is selected, the Templating Engine will compile that Web Content as a Blazor Component, enabling syntaxis and diagnostics.

Difference between ABS Blazor Pages and ABS Blazor Components.

At a fundamental level, pages and components differ in that pages contain the @page directive. The Templating Engine will enforce this directive on WebPages marked as .razor Code Type and disallow components containing this directive.

Web Pages/Components marked as .razor Code Type provides data binding features with the @bind Razor directive attribute with a field, property, or Razor expression value.

The following example component binds:

  • An <input> element value to the C# inputValue field.
  • A second <input> element value to the C# InputValue property.

When an <input> element loses focus, its bound field or property is updated.


<p>
    <input @bind="inputValue" />
</p>

<p>
    <label>
        Demonstration of equivalent HTML binding: 
        <input value="@InputValue"
            @onchange="@((ChangeEventArgs __e) => InputValue = __e.Value.ToString())" />
    </label>
</p>


<ul>
    <li><code>inputValue</code>: @inputValue</li>
    <li><code>InputValue</code>: @InputValue</li>
</ul>

@code {
    private string inputValue;

    private string InputValue { get; set; }
}

The text box is updated in the UI only when the component is rendered, not in response to changing the field's or property's value. Since components render themselves after event handler code executes, field and property updates are usually reflected in the UI immediately after an event handler is triggered.

As a demonstration of how data binding composes in HTML, the following example binds the InputValue property to the second <input> element's value and onchange attributes. The second <input> element in the following example is a concept demonstration and isn't meant to suggest how you should bind data in Razor components.


@using Microsoft.AspNetCore.Components.Web


<p>
    <label>
        Normal Blazor binding: 
        <input @bind="InputValue" />
    </label>
</p>

<p>
    <label>
        Demonstration of equivalent HTML binding: 
        <input value="@InputValue"
            @onchange="@((ChangeEventArgs __e) => InputValue = __e.Value.ToString())" />
    </label>
</p>

<p>
    <code>InputValue</code>: @InputValue
</p>

@code {
    private string InputValue { get; set; }
}

When the previous component is rendered, the value of the HTML <input> element comes from the InputValue property. When the user enters a value in the text box and changes element focus, the onchange event is fired and the InputValue property is set to the changed value. In reality, code execution is more complex because @bind handles cases where type conversions are performed. In general, @bind associates the current value of an expression with a value attribute and handles changes using the registered handler.

Bind a property or field on other Document Object Model (DOM) events by including an @bind:event="{EVENT}" attribute with a DOM event for the {EVENT} placeholder. The following example binds the InputValue property to the <input> element's value when the element's oninput event is triggered. Unlike the onchange event, which fires when the element loses focus, oninput fires when the value of the text box changes.


<p>
    <input @bind="InputValue" @bind:event="oninput" />
</p>

<p>
    <code>InputValue</code>: @InputValue
</p>

@code {
    private string InputValue { get; set; }
}

Razor attribute binding is case sensitive:

  • @bind and @bind:event are valid.
  • @Bind/@Bind:Event (capital letters B and E) or @BIND/@BIND:EVENT (all capital letters) are invalid.

Unparsable values

When a user provides an unparsable value to a data-bound element, the unparsable value is automatically reverted to its previous value when the binding event is triggered.

Consider the following component, where an <input> element is bound to an int type with an initial value of 123.

@using Microsoft.AspNetCore.Components.Web

<p>
    <input @bind="inputValue" />
</p>

<p>
    <code>inputValue</code>: @inputValue
</p>

@code {
    private int inputValue = 123;
}

By default, data binding applies to the element's onchange event. If the user updates the value of the text box's entry to 123.45 and changes the focus, the element's value is reverted to 123 when onchange fires. When the value 123.45 is rejected in favor of the original value of 123, the user understands that their value wasn't accepted.

For the oninput event (@bind:event="oninput"), a value reversion occurs after any keystroke that introduces an unparsable value. When targeting the oninput event with an int-bound type, a user is prevented from typing a dot (.) character. A dot (.) character is immediately removed, so the user receives immediate feedback that only whole numbers are permitted. There are scenarios where reverting the value on the oninput event isn't ideal, such as when the user should be allowed to clear an unparsable <input> value. Alternatives include:

  • Don't use the oninput event. Use the default onchange event, where an invalid value isn't reverted until the element loses focus.
  • Bind to a nullable type, such as int? or string and provide custom get and set accessor logic to handle invalid entries.
  • Use a form validation component, such as InputNumber or InputDate. Form validation components provide built-in support to manage invalid inputs. Form validation components:
    • Permit the user to provide invalid input and receive validation errors on the associated EditContext.
    • Display validation errors in the UI without interfering with the user entering additional webform data.

Format strings

Data binding works with a single DateTime format string using @bind:format="{FORMAT STRING}", where the {FORMAT STRING} placeholder is the format string. Other format expressions, such as currency or number formats, aren't available at this time but might be added in a future release.

@using Microsoft.AspNetCore.Components.Web

<p>
    <label>
        <code>yyyy-MM-dd</code> format:
        <input @bind="startDate" @bind:format="yyyy-MM-dd" />
    </label>
</p>

<p>
    <code>startDate</code>: @startDate
</p>

@code {
    private DateTime startDate = new(2020, 1, 1);
}

In the preceding code, the <input> element's field type (type attribute) defaults to text.

Nullable System.DateTime and System.DateTimeOffset are supported:

private DateTime? date;
private DateTimeOffset? dateOffset;

Specifying a format for the date field type isn't recommended because Blazor has built-in support to format dates. In spite of the recommendation, only use the yyyy-MM-dd date format for binding to function correctly if a format is supplied with the date field type:

<input type="date" @bind="startDate" @bind:format="yyyy-MM-dd">

Custom binding formats

C# get and set accessors can be used to create custom binding format behavior, as the following DecimalBinding component demonstrates. The component binds a positive or negative decimal with up to three decimal places to an <input> element by way of a string property (DecimalValue).

@using System.Globalization

<p>
    <label>
        Decimal value (&plusmn;0.000 format):
        <input @bind="DecimalValue" />
    </label>
</p>

<p>
    <code>decimalValue</code>: @decimalValue
</p>

@code {
    private decimal decimalValue = 1.1M;
    private NumberStyles style = 
        NumberStyles.AllowDecimalPoint | NumberStyles.AllowLeadingSign;
    private CultureInfo culture = CultureInfo.CreateSpecificCulture("en-US");

    private string DecimalValue
    {
        get => decimalValue.ToString("0.000", culture);
        set
        {
            if (Decimal.TryParse(value, style, culture, out var number))
            {
                decimalValue = Math.Round(number, 3);
            }
        }
    }
}

Additional resources

Blazor Data Binding

ABS Web event handling

Specify delegate event handlers in Razor component markup with @on{DOM EVENT}="{DELEGATE}" Razor syntax:

For event handling:

  • Asynchronous delegate event handlers that return a Task are supported.
  • Delegate event handlers automatically trigger a UI render, so there's no need to manually call StateHasChanged.
  • Exceptions are logged.

The following code:

  • Calls the UpdateHeading method when the button is selected in the UI.
  • Calls the CheckChanged method when the checkbox is changed in the UI.
<h1>@currentHeading</h1>

<p>
    <label>
        New title
        <input @bind="newHeading" />
    </label>
    <button @onclick="UpdateHeading">
        Update heading
    </button>
</p>

<p>
    <label>
        <input type="checkbox" @onchange="CheckChanged" />
        @checkedMessage
    </label>
</p>

@code {
    private string currentHeading = "Initial heading";
    private string newHeading;
    private string checkedMessage = "Not changed yet";

    private void UpdateHeading()
    {
        currentHeading = $"{newHeading}!!!";
    }

    private void CheckChanged()
    {
        checkedMessage = $"Last changed at {DateTime.Now}";
    }
}

In the following example, UpdateHeading:

  • Is called asynchronously when the button is selected.
  • Waits two seconds before updating the heading.
<h1>@currentHeading</h1>

<p>
    <label>
        New title
        <input @bind="newHeading" />
    </label>
    <button @onclick="UpdateHeading">
        Update heading
    </button>
</p>

@code {
    private string currentHeading = "Initial heading";
    private string newHeading;

    private async Task UpdateHeading()
    {
        await Task.Delay(2000);

        currentHeading = $"{newHeading}!!!";
    }
}

Event Arguments

For events that support an event argument type, specifying an event parameter in the event method definition is only necessary if the event type is used in the method. In the following example, MouseEventArgs is used in the ReportPointerLocation method to set message text that reports the mouse coordinates when the user selects a button in the UI.


@for (var i = 0; i < 4; i++)
{
    <p>
        <button @onclick="ReportPointerLocation">
            Where's my mouse pointer for this button?
        </button>
    </p>
}

<p>@mousePointerMessage</p>

@code {
    private string mousePointerMessage;

    private void ReportPointerLocation(MouseEventArgs e)
    {
        mousePointerMessage = $"Mouse coordinates: {e.ScreenX}:{e.ScreenY}";
    }
}


Supported EventArgs are shown in the following table.

Lambda expressions

Lambda expressions are supported as the delegate event handler.


@page "/Pages/EventHandlerExample4"

<h1>@heading</h1>

<p>
    <button @onclick="@(e => heading = "New heading!!!")">
        Update heading
    </button>
</p>

@code {
    private string heading = "Initial heading";
}

It's often convenient to close over additional values using C# method parameters, such as when iterating over a set of elements. The following example creates three buttons, each of which calls UpdateHeading and passes the following data:

  • An event argument (MouseEventArgs) in e.
  • The button number in buttonNumber.

@page "/event-handler-example-5"

<h1>@heading</h1>

@for (var i = 1; i < 4; i++)
{
    var buttonNumber = i;

    <p>
        <button @onclick="@(e => UpdateHeading(e, buttonNumber))">
            Button #@i
        </button>
    </p>
}

@code {
    private string heading = "Select a button to learn its position";

    private void UpdateHeading(MouseEventArgs e, int buttonNumber)
    {
        heading = $"Selected #{buttonNumber} at {e.ClientX}:{e.ClientY}";
    }
}

EventCallback

A common scenario with nested components executes a parent component's method when a child component event occurs. An onclick event occurring in the child component is a common use case. To expose events across components, use an EventCallback. A parent component can assign a callback method to a child component's EventCallback.

The following Child component demonstrates how a button's onclick handler is set up to receive an EventCallback delegate from the sample's ParentComponent. The EventCallback is typed with MouseEventArgs, which is appropriate for an onclick event from a peripheral device.

<p>
    <button @onclick="OnClickCallback">
        Trigger a Parent component method
    </button>
</p>

@code {
    [Parameter]
    public string Title { get; set; }

    [Parameter]
    public RenderFragment ChildContent { get; set; }

    [Parameter]
    public EventCallback<MouseEventArgs> OnClickCallback { get; set; }
}

The Parent component sets the child's EventCallback (OnClickCallback) to its ShowMessage method.

@page "/Pages/parent"

<h1>Parent-child example</h1>

<Child Title="Panel Title from Parent" OnClickCallback="@ShowMessage">
    Content of the child component is supplied by the parent component.
</Child>

<p>@message</p>

@code {
    private string message;

    private void ShowMessage(MouseEventArgs e)
    {
        message = $"Blaze a new trail with Blazor! ({e.ScreenX}:{e.ScreenY})";
    }
}

When the button is selected in the ChildComponent:

  • The Parent component's ShowMessage method is called. the message is updated and displayed in the Parent component.

  • A call to StateHasChanged isn't required in the callback's method (ShowMessage). StateHasChanged is called automatically to rerender the Parent component, just as child events trigger component rerendering in event handlers that execute within the child.

EventCallback and EventCallback<TValue> permit asynchronous delegates. EventCallback is weakly typed and allows passing any type of argument in InvokeAsync(Object). EventCallback<TValue> is strongly typed and requires passing a T argument in InvokeAsync(T) that's assignable to TValue.

<ChildComponent 
    OnClickCallback="@(async () => { await Task.Yield(); messageText = "Blaze It!"; })" />

Invoke an EventCallback or EventCallback with InvokeAsync and await the Task:

await OnClickCallback.InvokeAsync(arg);

Use EventCallback and EventCallback<TValue> for event handling and binding component parameters.

Prefer the strongly typed EventCallback<TValue> over EventCallback. EventCallback<TValue> provides enhanced error feedback to users of the component. Similar to other UI event handlers, specifying the event parameter is optional. Use EventCallback when there's no value passed to the callback.

Prevent default actions

Use the @on{DOM EVENT}:preventDefault directive attribute to prevent the default action for an event, where the {DOM EVENT} placeholder is a Document Object Model (DOM) event.

When a key is selected on an input device and the element focus is on a text box, a browser normally displays the key's character in the text box. In the following example, the default behavior is prevented by specifying the @onkeydown:preventDefault directive attribute. When the focus is on the <input> element, the counter increments with the key sequence Shift + +. The + character isn't assigned to the <input> element's value. For more information on keydown, see MDN Web Docs: Document: keydown event.

<p>
    <input value="@count" @onkeydown="KeyHandler" @onkeydown:preventDefault />
</p>

@code {
    private int count = 0;

    private void KeyHandler(KeyboardEventArgs e)
    {
        if (e.Key == "+")
        {
            count++;
        }
    }
}

Specifying the @on{DOM EVENT}:preventDefault attribute without a value is equivalent to @on{DOM EVENT}:preventDefault="true".

An expression is also a permitted value of the attribute. In the following example, shouldPreventDefault is a bool field set to either true or false:

<input @onkeydown:preventDefault="shouldPreventDefault" />

...

@code {
    private bool shouldPreventDefault = true;
}

Stop event propagation

Use the @on{DOM EVENT}:stopPropagation directive attribute to stop event propagation, where the {DOM EVENT} placeholder is a Document Object Model (DOM) event.

In the following example, selecting the checkbox prevents click events from the second child <div> from propagating to the parent <div>.

Since propagated click events normally fire the OnSelectParentDiv method, selecting the second child <div> results in the parent <div>message appearing unless the checkbox is selected.

@page "/Pages/EventHandlerExample7"

<label>
    <input @bind="stopPropagation" type="checkbox" />
    Stop Propagation
</label>

<div class="m-1 p-1 border border-primary" @onclick="OnSelectParentDiv">
    <h3>Parent div</h3>

    <div class="m-1 p-1 border" @onclick="OnSelectChildDiv">
        Child div that doesn't stop propagation when selected.
    </div>

    <div class="m-1 p-1 border" @onclick="OnSelectChildDiv" 
            @onclick:stopPropagation="stopPropagation">
        Child div that stops propagation when selected.
    </div>
</div>

<p>
    @message
</p>

@code {
    private bool stopPropagation = false;
    private string message; 

    private void OnSelectParentDiv() =>
        message = $"The parent div was selected. {DateTime.Now}";

    private void OnSelectChildDiv() =>
        message = $"A child div was selected. {DateTime.Now}";
}

Focus an element

Call FocusAsync on an element reference to focus an element in code. In the following example, select the button to focus the <input> element.

razor

Copy
@page "/Pages/EventHandlerExample8"

<p>
    <input @ref="exampleInput" />
</p>

<button @onclick="ChangeFocus">
    Focus the Input Element
</button>

@code {
    private ElementReference exampleInput;

    private async Task ChangeFocus()
    {
        await exampleInput?.FocusAsync();
    }
}

Forms and validation

The Blazor framework supports web forms with validation using the EditForm component bound to a model that uses data annotations.

To demonstrate how an EditForm component works with data annotations validation, consider the following ExampleModel type. The Name property is marked required with the RequiredAttribute and specifies a StringLengthAttribute maximum string length limit and error message.


using System.ComponentModel.DataAnnotations;

public class ExampleModel
{
    [Required]
    [StringLength(10, ErrorMessage = "Name is too long.")]
    public string Name { get; set; }
}

A form is defined using the Blazor framework's EditForm component. The following Razor component demonstrates typical elements, components, and Razor code to render a webform using an EditForm component, which is bound to the preceding ExampleModel type.


<EditForm Model="@exampleModel" OnValidSubmit="@HandleValidSubmit">
    <DataAnnotationsValidator />
    <ValidationSummary />

    <InputText id="name" @bind-Value="exampleModel.Name" />

    <button type="submit">Submit</button>
</EditForm>

@code {
    private ExampleModel exampleModel = new();

    private void HandleValidSubmit()
    {
        Console.WriteLine("HandleValidSubmit called");

        // Process the valid form
    }
}

In the preceding component:

  • The EditForm component is rendered where the element appears.
  • The model is created in the component's @code block and held in a private field (exampleModel). The field is assigned to EditForm.Model's attribute (Model) of the element.
  • The InputText component (id="name") is an <input> component for editing string values. The @bind-Value directive attribute binds the exampleModel.Name model property to the InputText component's Value property.
  • The HandleValidSubmit method is assigned to OnValidSubmit. The handler is called if the form passes validation.
  • The data annotations validator (DataAnnotationsValidator component†) attaches validation support using data annotations:
    • If the <input> form field is left blank when the Submit button is selected, an error appears in the validation summary (ValidationSummary component‡) ("The Name field is required.") and HandleValidSubmit is not called.
    • If the <input> form field contains more than ten characters when the Submit button is selected, an error appears in the validation summary ("Name is too long.") and HandleValidSubmit is not called.
    • If the <input> form field contains a valid value when the Submit button is selected, HandleValidSubmit is called.

†The DataAnnotationsValidator component is covered in the Validator component section. ‡The ValidationSummary component is covered in the Validation Summary and Validation Message components section. For more information on property binding, see data binding.

Theming Engine

This article contains information about developing themes for the Alliance Business Suite. The product includes a powerful theming engine that allows customers to customize every portal's look and feel.

Introduction

Alliance Business Suite Themes are groups of files that work together to create the design and functionality of an Alliance Business Suite portal. Each Theme may be different, offering many choices for site owners to instantly change their portal look.

We're building the theme engine to allow customers to create themes for their own use, for a client project or to submit to the ABS Theme Directory.

Capabilities

The ABS Theming Engine is built on top of the ABS Razor Templating Engine, which allows themes to use a combination of C# + HTML, CSS, and JavaScript to build amazing experiences.

  • Use a powerful component architecture to avoid code repetition and improve maintainability
  • Provide alternative templates for fixed platform functionalities such as the Store & Dashboard.
  • Themes can be updated through a mirror URL (which can perform things like license validation and much more).

Benefits

  • Themes can keep your Business Logic separated from your UI.
  • Themes are easily portable to other Alliance Business Suite instances.
  • Themes can be enabled on many portals running on the same instance.
  • Theme files can be overridden by child theme files and Dynamic Web Content (pulled from the database).

Anatomy of a Theme

Alliance Business Suite themes are just files living on a specific folder inside your instance's file system (/AppData/Themes/{ThemeName}). Each Theme Folder contains static files (such as JavaScript, CSS, Images, SVGs...) as well as a collection of C#, Razor, and Cshtml files.

The Alliance Business Suite includes a default theme in each new installation. Examine the files in the default theme carefully to get a better idea of how to build your own Theme files.

Child Themes

A child theme allows you to change small aspects of each theme's appearance while still preserving your theme’s look and functionality. To understand how child themes work it is first important to understand the relationship between parent and child themes.

A parent theme is a regular theme that includes every needed file the theme needs to properly work. This includes static files and business logic (dependencies should be installed through a Module).

Therefore, a Child Theme is just a subset of the parent's files which overrides a small subset of the parent's theme style and/or functionality.

Benefits of using a Child Theme

  • make your modifications portable and replicable;
  • keep customization separate from parent theme functions.
  • allow parent themes to be updated without destroying your modifications.
  • allow you to take advantage of the effort and testing put into the parent theme.
  • save on development time as you are not reinventing the wheel; and
  • are a great way to start learning about theme development.

The anatomy of a Theme

Themes contain a specific folder structure used to override the content defaults

- /Pages/
- /Components/
- /Public/
- /Templates/

Using these template files you can poll dynamic web content within the Main.cshtml master file to include these other files where you want them to appear in the final generated page.

  • To include the body, use @Body.
  • To include the header, use @await ViewService.InvokeAsync("Header").
  • To include the sidebar, use @await ViewService.InvokeAsync("Sidebar").
  • To include the footer, use @await ViewService.InvokeAsync("Footer").
  • To include the search bar, use @await ViewService.InvokeAsync("Search").

Here is an example of a basic Template File:

@{Name = "Turing Main Template";}

@await ViewService.InvokeAsync("Header")
@Body
@await ViewService.InvokeAsync("Footer")

For more on how these various Templates work and how to generate different information within themes, read the Templates documentation.

Theme Configuration File

In addition to your theme, the theme.json file provides details about the Theme in the form of a JSON Object. The file MUST exist and provide details about the Theme in a specific format. No two Themes are allowed to have the same details listed in the properties, as this will lead to problems in the Theme selection process. If you make your own Theme by copying an existing one, make sure you change this information first.

{
    "ID": "Turing",
    "Name": "Turing",
    "Domain": "Turing",
    "Version": "0.0.1",
    "AuthorName": "Fenix Alliance Inc.",
    "AuthorUrl": "https://fenix-alliance.com",
    "ThemeUrl": "https://fenix-alliance.com",
    "Tags": "mega-menu, translation-ready",
    "License": "GNU General Public License v2 or later",
    "LicenseUrl": "http://www.gnu.org/licenses/gpl-2.0.html",
    "Description": "Default theme for the Alliance Business Suite Portal."
}

NB: The name used for the Author is suggested to be the same as the Theme Author's github.com username, in which case it should start with an "@", although it can be the author's real or business name as well.

Template Files

Templates are ABS Razor source files used to generate the pages requested by visitors and are output as HTML. Template files are made up of HTML, C# and are rendered through ABS Templating Engine.

The Alliance Business Suite defines several template files that control the look and feel of certain parts of each portal.

Templates are rendered based upon the Web Component Hierarchy, which depends on the files that are present on the portal's enabled theme.

Template files should exist inside the Templates folder on your theme.

At the very minimum, an Alliance Business Suite Theme consists of two files:

  • theme.json
  • /Public/style.css

Both of these files go into the Theme directory. The Main.cshtml template file is very flexible. It can be used to include references to the header, sidebar, footer, body, categories, archives, search, error, and any other components both present in the theme's filesystem or pulled from the Alliance Business Model as Dynamic Web Content.

Or, it can be divided into several template files, each one taking on part of the workload. If you do not provide other template files, the Alliance Business Suite may have default files or functions to perform their jobs. For example, if you do not provide a SearchForm.cshtml template file, the Alliance Business Suite has a default View Component to display the search form.

Core Templates

  • Main.cshtml: The main template. If your Theme provides its own template, Main.cshtml must be present.

  • Blog.cshtml: The Blog template.

  • Forum.cshtml: The Forum template.

  • Store.cshtml: The Store template.

  • Dashboard.cshtml: The Dashboard template.

Core Pages

  • Page.cshtml: The page template. Used when an individual Page is queried.

  • Home.cshtml: The home page template, which is the front page by default. If you use a static front page this is the template for the page with the latest posts.

  • ForumHome.cshtml: The home page template, which is the front page by default. If you use a static front page this is the template for the page with the latest posts.

  • BlogHome.cshtml: The home page template, which is the front page by default. If you use a static front page this is the template for the page with the latest posts.

  • StoreHome.cshtml: The home page template, which is the store front page by default. If you use a static store front page this is the template for the page with the latest posts.

  • {PluralizedEntityType}.cshtml: The content template used when the records from any given Entity type are queried. For example, Courses.cshtml used for displaying posts from the Entity named "Course". Archive.cshtml is used if the query template for the custom post type is not present.

  • Single{EntityType}.cshtml: The single post template used when a single post from a custom post type is queried. For example, SingleItemCategory.cshtml used for displaying single records from the "ItemCategory" Entity. Single.cshtml is used if the query template for the custom post type is not present.

  • Category.cshtml: The category template. Used when a category is queried.

  • Tag.cshtml: The tag template. Used when a tag is queried.

  • Currencies.cshtml: The currency selector page template. Used to change the default currency is queried.

  • User.cshtml: The account page template. Used on the User Profile Page.

  • Login.cshtml: The login page template. Used on the User Login Page.

  • Register.cshtml: The register page template. Used on the User Registration Page.

  • Taxonomy.cshtml: The taxonomy template. Used when a taxonomy is queried.

  • SocialProfile.cshtml: The Social Profile template page. Used when a social profile is queried.

  • Date.cshtml: The date/time template. Used when a date or time is queried. Year, month, day, hour, minute, second.

  • Archive.cshtml: The archive template. Used when a category, author, or date is queried. Note that this template will be overridden by Category.cshtml, SocialProfile.cshtml, and Date.cshtml for their respective query types.

  • Search.cshtml: The search results template. Used when a search is performed.

  • Attachment.cshtml: Attachment template. Used when viewing a single attachment.

  • Image.cshtml: Image attachment template. Used when viewing a single image attachment. If not present, attachment.php will be used.

  • E404.cshtml: The 404 Not Found template. Used when the ABS cannot find a post or page that matches the query.

  • E401.cshtml: The 404 Not Authorized template. Used when the ABS cannot allow a user to query some endpoint.

  • E500.cshtml: The 500 Error template. Used when the ABS cannot perform some action due to some internal error.

Core Components

  • Head.cshtml: The head component.

  • Footer.cshtml: The footer component.

  • Header.cshtml: The header component.

  • StoreFooter.cshtml: The store footer component.

  • StoreHeader.cshtml: The store header component.

Layout Pages on the Alliance Business Suite

Pages and views frequently share visual and programmatic elements. This article demonstrates how to:

  • Use common layouts.
  • Share directives.
  • Run common code before rendering pages or views.

This document discusses layouts for the two different approaches to building Alliance Business Suite Apps: Razor Pages and controllers with views. For this topic, the differences are minimal:

Razor Pages are database records according to the Alliance Business Model Schema. Controllers with views are sets of precompiled code living on the Alliance Business Model.

What is a Layout

Most web apps have a common layout that provides the user with a consistent experience as they navigate from page to page. The layout typically includes common user interface elements such as the app header, navigation or menu elements, and footer.

Page Layout example

Common HTML structures such as scripts and stylesheets are also frequently used by many pages within an app. All of these shared elements may be defined in a layout file, which can then be referenced by any view used within the app. Layouts reduce duplicate code in views.

page-layout.png

Common HTML structures such as scripts and stylesheets are also frequently used by many pages within an app. All of these shared elements may be defined in a layout file, which can then be referenced by any view used within the app. Layouts reduce duplicate code in views.

By convention, the default layout for an Alliance Business Suite app is named MainLayout.

The layout defines a top-level template for views in the app. Apps don't require a layout. Apps can define more than one layout, with different views specifying different layouts.

The following code shows the layout file for a template created a project with a controller and views:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>@ViewData["Title"] - WebApplication1</title>

    <link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.css" />
    <link rel="stylesheet" href="~/css/site.css" />

</head>
<body>
    <nav class="navbar navbar-inverse navbar-fixed-top">
        <div class="container">
            <div class="navbar-header">
                <button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
                    <span class="sr-only">Toggle navigation</span>
                    <span class="icon-bar"></span>
                    <span class="icon-bar"></span>
                    <span class="icon-bar"></span>
                </button>
                <a asp-page="/Index" class="navbar-brand">WebApplication1</a>
            </div>
            <div class="navbar-collapse collapse">
                <ul class="nav navbar-nav">
                    <li><a href="/Index">Home</a></li>
                    <li><a href="/About">About</a></li>
                    <li><a href="/Contact">Contact</a></li>
                </ul>
            </div>
        </div>
    </nav>

    <partial name="_CookieConsentPartial" />

    <div class="container body-content">
        @Body
        <hr />
        <footer>
            <p>&copy; 2020 - WebApplication1</p>
        </footer>
    </div>


        <script src="https://ajax.aspnetcdn.com/ajax/jquery/jquery-3.3.1.min.js"
                crossorigin="anonymous"
                integrity="sha384-tsQFqpEReu7ZLhBV2VZlAu7zcOV+rXbYlF2cqB8txI/8aZajjp4Bqd+V6D5IgvKT">
        </script>
        <script src="https://ajax.aspnetcdn.com/ajax/bootstrap/3.3.7/bootstrap.min.js"
                crossorigin="anonymous"
                integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa">
        </script>

        <script src="~/js/site.min.js" ></script>

</body>
</html>

Specifying a Layout

Razor views have a Layout property. Individual views specify a layout by setting this property:

LayoutOptionShowcase.png

View components are similar to page views, but they're much more powerful. View components don't use model binding and only depend on the data provided when calling into it.

A view component:

  • Renders a chunk rather than a whole response.
  • Includes the same separation-of-concerns and testability benefits found between a controller and view.
  • Can have parameters and business logic.
  • Is typically invoked from a layout page.

View components are intended anywhere you have reusable rendering logic that's too complex for a partial view, such as:

  • Dynamic navigation menus
  • Tag cloud (where it queries the database)
  • Login panel
  • Shopping cart
  • Recently published articles
  • Sidebar content on a typical blog
  • A login panel that would be rendered on every page and show either the links to log out or log in, depending on the login state of the user

A view component consists of two parts: the class (typically derived from ViewComponent) and the result it returns (typically a view). Like controllers, a view component can be a POCO, but most developers will want to take advantage of the methods and properties available by deriving from ViewComponent.

Creating a view component

A view component class can be created on your ABS Instance administration dashboard, under Appearance > Components.

View component methods

A view component defines its logic in an InvokeAsync method that returns a Task<IViewComponentResult> or in a synchronous Invoke method that returns an IViewComponentResult. Parameters come directly from the invocation of the view component, not from model binding. A view component never directly handles a request. Typically, a view component initializes a model and passes it to it's corresponding view by calling the View method. In summary, view component methods:

  • Define an InvokeAsync method that returns a Task<IViewComponentResult> or a synchronous Invoke method that returns an IViewComponentResult.
  • Typically initializes a model and passes it to a view by calling the ViewComponent View method.
  • Parameters come from the calling method, not HTTP. There's no model binding.
  • Are not reachable directly as an HTTP endpoint. They're invoked from your code (usually in view). A view component never handles a request.
  • Are overloaded on the signature rather than any details from the current HTTP request.

View search path

The Alliance Business Suite searches for ViewComponents using the Alliance Business Model Schema. It will use case insensitive search by Name and Id for the ViewComponent.

Note: If the View Component is not rendered, no errors will be thrown and only an empty markup string will be rendered.

Perform synchronous work

The framework handles invoking a synchronous Invoke method if you don't need to perform asynchronous work. The following method creates a synchronous Invoke view component:

public class Template : DynamicComponentBase
{
    public dynamic Invoke(int maxPriority, bool isDone)
    {
        var items = new List<string> { $"maxPriority: {maxPriority}", $"isDone: {isDone}" };
        return items;
    }
}

A view component class:

  • Fully supports constructor dependency injection

  • Doesn't take part in the controller lifecycle, which means you can't use filters in a view component

@model List<string>

<h3>Priority Items</h3>
<ul>
    @foreach (var item in Model)
    {
        <li>@item</li>
    }
</ul>

Invoking a Web Component

To use a component inside a Page, template, or another component, call ViewService.InvokeAsync from anywhere in your view:

@await ViewService.InvokeAsync("Component Name or Id", {Anonymous Type Containing Parameters}, (optional) recompile = false)
@await ViewService.InvokeAsync("Component Name or Id", new { maxPriority = 1, isDone = false  })

All view component parameters are required

Each parameter in a view component is a required attribute. See this GitHub issue. If any parameter is omitted:

  • The InvokeAsync method signature won't match, therefore the method won't execute.
  • The ViewComponent won't render any markup.
  • No errors will be thrown.

[[TOC]]

The Alliance Business Suite contains a simple, yet powerful engine for enabling seamless Client-Side Single Page Application development using Angular or React/React+Redux, or really any Client-Side framework.

The ABS SPA Service provides a convenient template to act as a starting point for Client-Side Applications both using Angular or React/React+Redux to implement a rich, client-side user interface (UI) while still taking advantage of the tremendous power of the Alliance Business Suite without the hustle of creating and connecting independent application components, managing authentication and more.

ABS SPA applications offer the convenience of hosting several custom applications inside a single Alliance Business Suite instance, Consequently, your business applications can be perceived, managed, and operated as a single unit.

There are slight differences between the Angular/React/React+Redux app created for the Alliance Business Suite and the one traditionally created by each respective SPA framework tool (via ng new or npx create-react-app ); however, the app's capabilities are unchanged. The app created by each template contains a Bootstrap-based layout and a basic routing example.

Each ABS SPA template is configured to use the Alliance Business Platform as an API backend and the SPA project to act as a UI.

Creating a Single Page Application.

To create a new Client-Side application for the Alliance Business Suite, head over to your ABS Studio, click on integrations from the top right-hand side corner of your state bar. Select Alliance Business Suite > Applications > Create Application.

There, fill out the form, select a name for your application and mark your new application as a Single Page Application. There, you will be prompted with additional required properties for your application.

image.png You can customize things like:

  • The Application Name
  • The NPM Publish Script
  • The NPM Start Script
  • The SPA Engine

Managing your Angular Application

Managing your React Application

The template is equivalent to creating both an ASP.NET Core project to act as an API backend, and a standard CRA React project to act as a UI, but with the convenience of hosting both in a single app project that can be built and published as a single unit.

Managing your React + Redux Application

Add pages, images, styles, modules, etc.

The Alliance Business Suite offers an in-app code editor and file manager to allow you to add static files and code changes to your SPA application. However, sometimes customers do prefer to realize extension development using tools like Visual Studio and VS Code on their development desktops.

This is why the Alliance Business Suite allows customers to connect a public/private git repo to each SPA and pull/push updates with the click of a button.

To enable Git Management for your SPA application, head to your application page and Enable Git Repo Management. Provide a Git Repo URL and a personal access token if the repo is private.

image.png

Install npm packages

To install third-party npm packages, use a command prompt on the application page and run the following command:

spa -id packages install --save <package_name> or just add it to your package.json and request the application to execute the publish script, (which will execute npm install first) by clicking on the Re-Publish Files button.

image.png

Publish and deploy

In development, ABS SPAs run in a mode optimized for developer convenience. For example, JavaScript bundles include source maps (so that when debugging, you can see your original TypeScript code). The app watches for TypeScript, HTML, and CSS file changes on the SPA Root Files Path and automatically recompiles and reloads when it sees those files change.

In production, the Alliance Business Suite serves the version of your app that's optimized for performance. This is configured to happen automatically. When you publish, the build configuration emits a minified, ahead-of-time (AoT) compiled build of your client-side code. Unlike the development build, the production build doesn't require Node.js to be installed on the server (unless you have enabled server-side rendering (SSR)).

Run the SPA independently

The project is configured to start its own instance of the SPA in the background when the Alliance Business Suite starts in development mode. This is convenient because you don't have to run a separate server manually.

There's a drawback to this default setup. Each time you modify your C# code and your Alliance Business Suite instance needs to restart, the SPA server restarts. Around 10 seconds is required to start back up. If you're making frequent updates to your Alliance Business Suite instance (Like installing new applications or modules) and don't want to wait for each SPA process to restart, run the Angular CLI server externally, independently of the ASP.NET Core process. To do so:

image.png

Provide a URL for the running ABS SPA and the Alliance Business Suite will establish a proxy To the SPA Development Server.

Current limitations

The React project template isn't meant for server-side rendering (SSR). For SSR with React and Node.js, consider Next.js or Razzle.

Session and state management in the Alliance Business Suite

HTTP is a stateless protocol. By default, HTTP requests are independent messages that don't retain user values. This article describes several approaches to preserve user data between requests.

State management

State for the Alliance Business Suite can be stored using several approaches. Each approach is described later in this topic.

Storage approachStorage mechanism
CookiesHTTP cookies. May include data stored using server-side app code.
Session stateHTTP cookies and server-side app code
TempDataHTTP cookies or session state
Query stringsHTTP query strings
Hidden fieldsHTTP form fields
HttpContext.ItemsServer-side app code
CacheServer-side app code

Cookies

Cookies store data across requests. Because cookies are sent with every request, their size should be kept to a minimum. Ideally, only an identifier should be stored in a cookie with the data stored by the ABS Instance. Most browsers restrict cookie size to 4096 bytes. Only a limited number of cookies are available for each domain.

Because cookies are subject to tampering, they must be validated by the app. Cookies can be deleted by users and expire on clients. However, cookies are generally the most durable form of data persistence on the client.

Cookies are often used for personalization, where content is customized for a known user. The user is only identified and not authenticated in most cases. The cookie can store the user's name, account name, or unique user ID such as a GUID. The cookie can be used to access the user's personalized settings, such as their preferred website background color.

See the European Union General Data Protection Regulations (GDPR) when issuing cookies and dealing with privacy concerns. For more information, see General Data Protection Regulation (GDPR) support for the Alliance Business Suite.

Session state

Session state is an Alliance Business Suite Instance scenario for the storage of user data while the user browses a web app. Session state uses a store maintained by the app to persist data across requests from a client. The session data is backed by a cache and considered ephemeral data. The site should continue to function without the session data. Critical application data should be stored in the Account Holder database entity and cached in session only as a performance optimization.

The session isn't supported in SignalR functionalities because a SignalR Hub may execute independently of an HTTP context. For example, this can occur when a long polling request is held open by a hub beyond the lifetime of the request's HTTP context.

The Alliance Business Suite maintains the session state by providing a cookie to the client that contains a session ID. The cookie session ID:

  • Is sent to the app with each request.
  • Is used by the app to fetch the session data.

Session state exhibits the following behaviors:

  • The session cookie is specific to the browser. Sessions aren't shared across browsers.
  • Session cookies are deleted when the browser session ends.
  • If a cookie is received for an expired session, a new session is created that uses the same session cookie.
  • Empty sessions aren't retained. The session must have at least one value set to persist the session across requests. When a session isn't retained, a new session ID is generated for each new request.
  • The app retains a session for a limited time after the last request. The app either sets the session timeout or uses the default value of 20 minutes. Session state is ideal for storing user data:
  • That's specific to a particular session.
  • Where the data doesn't require permanent storage across sessions.
  • Session data is deleted either when the ISession.Clear implementation is called or when the session expires.
  • There's no default mechanism to inform app code that a client browser has been closed or when the session cookie is deleted or expired on the client.
  • Session state cookies aren't marked essential by default. Session state isn't functional unless tracking is permitted by the site visitor. For more information, see General Data Protection Regulation (GDPR) support across the Alliance Business Suite

Don't store sensitive data in session state. The user might not close the browser and clear the session cookie. Some browsers maintain valid session cookies across browser windows. A session might not be restricted to a single user. The next user might continue to browse the app with the same session cookie.

The in-memory cache provider stores session data in the memory of the server where the app resides. In a server farm scenario:

Use sticky sessions to tie each session to a specific app instance on an individual server. Azure App Service uses Application Request Routing (ARR) to enforce sticky sessions by default. However, sticky sessions can affect scalability and complicate web app updates. A better approach is to configure the Alliance Business Suite to a Redis or SQL Server by enabling distributed cache, which doesn't require sticky sessions. For more information, see Distributed caching in the Alliance Business Suite.

The session cookie is encrypted via IDataProtector. Data Protection must be properly configured to read session cookies on each machine. For more information, see Alliance Business Suite Data Protection and Key storage providers.

Warning

Don't store sensitive data in session state. The user might not close the browser and clear the session cookie. Some browsers maintain valid session cookies across browser windows. A session might not be restricted to a single user. The next user might continue to browse the app with the same session cookie.

The in-memory cache provider stores session data in the memory of the server where the app resides. In a server farm scenario:

Use sticky sessions to tie each session to a specific app instance on an individual server. Alliance Business Cloud uses Application Request Routing (ARR) to enforce sticky sessions by default. However, sticky sessions can affect scalability and complicate web app updates. A better approach is to enable Redis or SQL Server distributed cache, which doesn't require sticky sessions. For more information, see Distributed caching in the Alliance Business Suite.

Configure session state

To configure session state you'll need to visit your portal's configuration dashboard. The Alliance Business Suite handles the configuration required to add session management through the in-memory session provider with a default in-memory implementation of a Distributed Cache.

You can set the timeout in both development and production environments to simplify testing.

  • HttpContext.Session is available after session state is configured.
  • HttpContext.Session can't be accessed before UseSession has been called.

A new session with a new session cookie can't be created after the Alliance Business Suite has begun writing to the response stream. The exception is recorded in the web server log and not displayed in the browser.

Load session state asynchronously

The default session provider in the Alliance Business Suite loads session records from the underlying IDistributedCache backing store asynchronously only if the ISession.LoadAsync method is explicitly called before the TryGetValue, Set, or Remove methods. If LoadAsync isn't called first, the underlying session record is loaded synchronously, which can incur a performance penalty at scale.

To have apps enforce this pattern, wrap the DistributedSessionStore and DistributedSession implementations with versions that throw an exception if the LoadAsync method isn't called before TryGetValue, Set, or Remove. Register the wrapped versions in the services container.

Session options

To override session defaults, visit your Portal Administration Dashboard.

Query strings

A limited amount of data can be passed from one request to another by adding it to the new request's query string. This is useful for capturing the state in a persistent manner that allows links with the embedded states to be shared through email or social networks. Because URL query strings are public, never use query strings for sensitive data.

In addition to unintended sharing, including data in query strings can expose the app to Cross-Site Request Forgery (CSRF) attacks. Any preserved session state must protect against CSRF attacks. For more information, see Prevent Cross-Site Request Forgery (XSRF/CSRF) attacks in the Alliance Business Suite.

Hidden fields

Data can be saved in hidden form fields and posted back on the next request. This is common in multi-page forms. Because the client can potentially tamper with the data, the app must always revalidate the data stored in hidden fields.

HttpContext.Items

The HttpContext.Items collection is used to store data while processing a single request. The collection's contents are discarded after a request is processed. The Items collection is often used to allow components or middleware to communicate when they operate at different points in time during a request and have no direct way to pass parameters.

Cache

Caching is an efficient way to store and retrieve data. The app can control the lifetime of cached items. For more information, see Response caching in the Alliance Business Suite.

Cached data isn't associated with a specific request, user, or session. Do not cache user-specific data that may be retrieved by other user requests.

To cache application-wide data, see Cache in-memory in the Alliance Business Suite.

The Alliance Business Suite supports creating RESTful services, also known as web APIs, using C#. To handle requests, a web API uses controllers. Controllers in the Alliance Business Suite can be added from several approaches, some of which will allow you to access every Alliance Business Suite feature that's available. Controllers are classes that derive from ControllerBase and can be added as Modules to the Alliance Business Suite by installing them as a Nuget Package or uploading them through your instance or File System.

This article shows how to use controllers for handling web API requests.

ControllerBase class

The Alliance Business Suite is written in C# using .NET, and several interfaces have been set in place to make it as extensible as it can be.

The Alliance Business Suite allows customers to develop their own API Sets (which consists of one or more controller classes that derive from ControllerBase) just as if they were building a .NET API, with one main difference. You don't need to worry about wiring features and managing complicated stuff such as authentication processes, dependency injection, and application startup. Also, you can use the ABS SDK to build amazing custom functionalities with just a few lines of code.

Please consider the following class as an example of the most basic custom API Controller for the Alliance Business Suite:


[ApiController]
[Route("api/v2/[controller]")]
public class LicensesController : ControllerBase {

        // Constructor
        public LicensesController(){
        }

        [HttpGet("validate/{LicenceID}")]
        public async Task<ActionResult> Get(string LicenceID)
        {
            await Task.Delay(1000);
            return Ok(LicenceID);
        }

}

The previous controller will be available at /api/v2/licenses and the Get method can be invoked by making an HTTP GET request to /api/v2/licenses/validate/{LicenseID}

Also, it is worth pointing out that the Alliance Business Suite DOES have support for the MVC Pattern, so you should not create a web API controller by deriving from the Controller class. Controller derives from ControllerBase and adds support for views, so it's for handling web pages, not web API requests. There's an exception to this rule: if you plan to use the same controller for both views and web APIs, derive it from Controller."

In essence, creating an Alliance Business Suite compatible Controller is just as straightforward as creating a .NET API Controller with a few additions:

  • You can inject, through dependency injection, any registered Alliance Business Suite Service. This includes every interface provided with the following schema: I{ServiceName}Service (e.g: IAuthService, IHolderService, IViewRenderingService, ICodeCompilationService, and other 100+).

Please consider the following class as an example of a Custom Complex Controller for the Alliance Business Suite:


using FenixAlliance.ABM.Data;
using FenixAlliance.ABM.Data.Interfaces.Services;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Hosting;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;

namespace FenixAlliance.Areas.Licensing.Controllers
{
    [ApiController]
    [Route("api/v2/CustomMe")]
    [ApiExplorerSettings(IgnoreApi = true)]
    public class HolderController : ControllerBase {

        public DataContext DataContext { get; set; }
        public IAuthService AuthService { get; set; }
        public IStoreService StoreService { get; set; }
        public IConfiguration Configuration { get; set; }
        public IHostEnvironment Environment { get; set; }
        public IHolderService HolderService { get; set; }
        public ITenantService TenantService { get; set; }
        public IStorageService StorageService { get; set; }

        public LicensesController(
            DataContext DataContext,
            IConfiguration Configuration,
            IHostEnvironment Environment,
            IStoreService StoreService,
            ITenantService TenantService,
            IHolderService HolderService,
            IAuthService AuthService,
            IStorageService StorageService
        )
        {
            this.AuthService = AuthService;
            this.DataContext = DataContext;
            this.Environment = Environment;
            this.StoreService = StoreService;
            this.Configuration = Configuration;
            this.HolderService = HolderService;
            this.TenantService = TenantService;
            this.StorageService = StorageService;
        }

        /// <summary>
        /// Get the current user profile
        /// </summary>
        /// <returns></returns>
        [HttpGet]
        [Produces("application/json")]
        [ProducesResponseType(StatusCodes.Status200OK)]
        [ProducesResponseType(typeof(Holder), StatusCodes.Status200OK)]
        [ProducesResponseType(typeof(ResponseStatus), StatusCodes.Status401Unauthorized)]
        public async Task<ActionResult<APIResponse>> GetMe()
        {
            var apiResponse = JsonConvert.DeserializeObject<APIResponse>(
                JsonConvert.SerializeObject(
                    await AuthService.BindAPIBaseResponse(
                        DataContext,
                        HttpContext,
                        Request,
                        HolderService,
                        User
                        )
                    )
                );

            if (apiResponse == null || !apiResponse.Status.Success || apiResponse.Holder == null)
            {
                return Unauthorized(apiResponse?.Status);
            }

            return Ok(apiResponse.Holder);
        }
    }
}

Installing a Custom Controller

To install a custom controller you just need to build the Razor Class Library containing your custom Controllers as a NuGet Package and then upload it into your Alliance Business Suite instance.

If your RCL depends on other Nuget Packages, those DLLs will need to be copied into your Module's NuGet Package for your custom functionality to work.

To do this, you can extract the .nupkg file using something like 7-Zip (NuGet Packages are just Zipped files with a different extension), and then copy into the lib/ folder every non-ABS Dll required for your RCL to work properly. Then, re-compress the files, and change the re-compressed file extension to .nupkg to be uploaded into your Alliance Business Suite Instance as a Module. (The actual path of the dlls into the lib folder makes no difference whatsoever on the discovery process, so feel free to set up your own structure.)

To install a module into your Alliance Business Suite:

  • Upload your NuGet Package to the Alliance Business Suite Gallery and then install it through the Modules Manager. (This method will make your Module available to every Alliance Business Suite installation out there, and is best suited for those who create commercial modules and integrations)

  • Upload the NuGet package right into your Alliance Business Suite instance using your instance's Modules Manager.

  • Copy the NuGet Package into the Modules folder at the root of your Alliance Business Suite installation. (If the folder does not exist yet, you can confidently create it) and then enable it through your instance's admin portal.

Developing Modules for the Alliance Business Suite

The Alliance Business Suite is a modular application platform. This means that you can create custom functionalities in the form of modules and add them to your ABS instance.

Modules are pieces of software that are designed to perform a specific set of functions or add a specific kind of feature, to any Alliance Business Suite instance. ABS Modules work only with self-hosted ABS instances. Hosted versions such as absuite.net typically offer theme options for customizing portals, but it isn’t possible to install plugins freely to customize portals on this platform.

ABS Modules are written in C#, the programming language for the Alliance Business Suite itself. When using ABS Modules, you can easily install or “plugin” the one you want to an existing ABS instance with no coding knowledge required. The power of ABS Modules makes it possible to extend the functionality of the Alliance Business Suite sites while creating customer experiences that are completely unique.

The Alliance Business Platform provides an essential framework for building a basic website. Some specialized functions can be added to each module and integrated with every theme but those features usually relate to customizing the structure of the site itself. For example, a theme designed for photographers might include options for a gallery or slideshow, and an eCommerce theme might have basic functionality for setting up product pages. Plugins incorporate a fully developed set of functions into your Alliance Business Suite instance site and can include options for customization and configuration.

Creating Modules

To create a Module for the Alliance Business Suite, you'll need to create a new Razor Class Library with DotNet. Then add a reference to the FenixAlliance.ABP.SDK Nuget package to your project and implement the IModule interface.

This will give you access to the entire dependency tree of the Alliance Business Suite, which includes things like Internal Services, Database Access, and Initialization Middleware Entrypoints (to register your own custom services or InternalServices implementations). From there, is just like developing any other ASP.NET Class Library, but without having to worry about things like StartUp processes or complex application dependency wiring.

Once your Module is ready for production, you can build it as a Nuget Package and install it into any ABS instance by uploading the .nupkg file to the Modules folder on the Root content path of your ABS instance or by uploading it to the ABS Public Modules Gallery and install it through your Admin Portal..

What Can Modules Do?

Modules make it easy to convert a basic Alliance Business Suite instance into a fully functioning online storefront, a membership site, a blog, or a website capable of handling the complex professional needs of a multinational corporation. Generally, Modules can add essential functions that are useful for any Alliance Business Suite instance, as well as features for specific needs.

Modules can enhance your Alliance Business Suite instance by:

  • Adding Custom Functionalities. Modules are extremely powerful when it comes to building custom functionalities on top of the Alliance Business Suite. Even when it is super easy to static assets and server-side logic to the Alliance Business Suite through Pages, Components, and Templates, and even SPA applications can be added with the click of a button, Modules allow customers to add fully functional sets of components for the ABS instance. Modules can contain Static Assets, MVC sets, Blazor Components, Tag Helpers, API Controllers, Bot Dialogs, Middlewares, and more.
  • Improving user experience. Modules can add features to help users navigate through a portal, find content, leave comments, subscribe for updates, and contact site administrators.
  • Adding essential security features. The core Alliance Business Suite install comes with a great set of security features, but Modules can add sophisticated firewalls, alerts, user verifications, authentication providers, and spam blockers for greater site security.
  • Speeding up site loading time. Modules can speed up an Alliance Business Suite portal by enabling caching and optimizing static files such as images and even videos.
  • Streamlining your workflow. Modules can help optimize your site for searchability, add server-side logic and API endpoints.
  • Improving the site’s appearance. Modules can add designer fonts, galleries, sliders, and media players to your site. Some themes require certain Modules to perform properly.
  • Adding needed features for your site’s goals. Modules can add features like product pages and shopping carts to eCommerce sites, landing pages, paywalls, and a long list of other features to support the site’s intended purpose.

Best practices for ABS Module Development

  • To reduce possible incompatibilities, it is recommended to create all your functionality inside an ASP.NET Area named after your Module. This will reduce the possibility to collide with other module namespaces and routes.
  • Whenever possible, use the default provided service interfaces under the FenixAlliance.ABM.Data.Interfaces.Services namespace.
  • If you need to add a custom implementation for any service, it is recommended not to do so and instead create a new service; but in cases when there is no other choice, please consider inheriting from the Internal implementation and overriding the required virtual methods.

Security Considerations

Due to the power of Modules, they can be used to add incredible functionalities to your ABS instance, but they can also result in breaking functionalities and even security breaches.

Keep in mind some general ideas while considering security for each aspect of your system:

Reduce exposure

First of all, make sure your Modules are always updated. Also, if you are not using a specific Module, delete it from the system.

Limit access

Making smart Instance/Module/Theme configurations can drastically reduce possible entry points available to a malicious person.

Containment

Your system should be configured to minimize the amount of damage that can be done in the event that it is compromised.

Preparation and knowledge

Keeping backups and knowing the state of your Alliance Business Suite instance at regular intervals. Having a plan to backup and recover your installation in the case of catastrophe can help you get back online faster in the case of a problem.

Trusted Sources

Do not get plugins/themes from untrusted sources. Restrict yourself to the Alliance Business Suite Gallery repository or well-known companies. Trying to get modules/themes from the outside may lead to issues.

Internationalization in the Alliance Business Suite

A multilingual website allows the site to reach a wider audience. The Alliance Business Suite provides convenient, easy-to-use solutions for localizing portals into different languages and cultures.

Internationalization involves Globalization and Localization. Globalization is the process of designing apps that support different cultures. Globalization adds support for the input, display, and output of a defined set of language scripts that relate to specific geographic areas.

Localization is the process of adapting a globalized app, which you have already processed for localizability, to a particular culture/locale. For more information see Globalization and localization terms near the end of this document.

How to make the app's content localizable

The Alliance Business Suite was architected to allow customers to obtain this functionality right out of the box. Through simple front-end settings for each portal, customers can select a default language for each portal and localize strings and HTML fragments by just calling the _() method available through code on every web content entry. (e.g: _("Hello World"))

Once your localizable strings have been placed in code using the String Localizer function. you can create localization resources using your instance's admin portal.

Implement a strategy to select the language/culture for each request

Localization is already set up using the ACL. Additional supported languages, as well as the primary content language for each portal, can be selected on each's portal configuration manager.

QueryStringRequestCultureProvider

Portals can use a query string to set the Culture Info. For apps that use the cookie or Accept-Language header approach, adding a query string to the URL is useful for debugging and testing code. By default, the QueryStringRequestCultureProvider is registered as the first localization provider in the RequestCultureProvider list. You pass the query string parameters culture and UI-culture. The following example sets the specific culture (language and region) to Spanish/Mexico:

http://yourdomain/?culture=es-MX&ui-culture=es-MX

If you only pass in one of the two (culture or ui-culture), the query string provider will set both values using the one you passed in. For example, setting just the culture will set both the Culture and the UICulture:

http://localhost:5000/?culture=es-MX

CookieRequestCultureProvider

Production apps will often provide a mechanism to set the culture with the ASP.NET Core culture cookie. Use the MakeCookieValue method to create a cookie.

The CookieRequestCultureProvider DefaultCookieName returns the default cookie name used to track the user's preferred culture information. The default cookie name is .AspNetCore.Culture.

The cookie format is c=%LANGCODE%|uic=%LANGCODE%, where c is Culture and uic is UICulture, for example:

c=en-UK|uic=en-US

If you only specify one of culture info and UI culture, the specified culture will be used for both culture info and UI culture.

The Accept-Language HTTP header

The Accept-Language header is settable in most browsers and was originally intended to specify the user's language. This setting indicates what the browser has been set to send or has inherited from the underlying operating system. The Accept-Language HTTP header from a browser request isn't an infallible way to detect the user's preferred language (see Setting language preferences in a browser). A production app should include a way for a user to customize their choice of culture.

Set the Accept-Language HTTP header in IE

  1. From the gear icon, tap Internet Options.

  2. Tap Languages.

  3. Internet Options

  4. Tap Set Language Preferences.

  5. Tap Add a language.

  6. Add the language.

  7. Tap the language, then tap Move Up.

Set the culture programmatically

You can easily create a component to allow your users to select their preferred culture from the list of supported cultures:

This sample, present on the Header Component for the Turing Theme shows you how to do so:

@{
	var requestCulture = Context.Features.Get<IRequestCultureFeature>();
	var cultureItems = RequestLocalizationOptions.Value.SupportedUICultures
		.Select(c => new SelectListItem { Value = c.Name, Text = c.DisplayName })
		.ToList();
	var returnUrl = string.IsNullOrEmpty(Context.Request.Path) ? "~/" : $"~{Context.Request.Path.Value}";
}

<li class="nav-item dropdown">
	<div class="dropdown-menu" aria-labelledby="SelectLang">
		<!-- Current Language -->
		<h6 class="dropdown-header">
			<b>  <i class="fas fa-globe-americas"></i>&nbsp;  @_("Current Language"): </b>
			<b id="CurrencyTip">
				@requestCulture.RequestCulture.Culture.TwoLetterISOLanguageName
			</b>
		</h6>
		<div class="dropdown-divider"></div>
		@foreach (var item in cultureItems)
		{
			var value = @item.Value;
			<a href="#" onclick="SelectLang('@(value.Replace(" ", ""))')" class="dropdown-item">
				<i class="fas fa-language"></i>&nbsp; @item.Text
			</a>
		}
	</div>

	<script>
		//Select Language
		function SelectLang(value) {
			cookie = "c=" + value.trim() + "|uic=" + value.trim();
			Cookies.set('.AspNetCore.Culture', cookie);
			window.location.reload();
		}
	</script>
</li>

Globalization and localization terms

The process of localizing your portals also requires a basic understanding of relevant character sets commonly used in modern software development and an understanding of the issues associated with them. Although all computers store text as numbers (1's and 0's), different systems store the same text using different numbers. The localization process refers to translating the portal user interface (UI) for a specific culture/locale.

Localizability is an intermediate process for verifying that a globalized app is ready for localization.

The RFC 4646 format for the culture name is {languagecode2}-{country/regioncode2}, where {languagecode2} is the language code and {country/regioncode2} is the subculture code. For example, es-CO for Spanish (Colombia), en-US for English (United States), and en-AU for English (Australia). RFC 4646 is a combination of an ISO 639 two-letter lowercase culture code associated with a language and an ISO 3166 two-letter uppercase subculture code associated with a country or region.

Internationalization is often abbreviated to "I18N". The abbreviation takes the first and last letters and the number of letters between them, so 18 stands for the number of letters between the first "I" and the last "N". The same applies to Globalization (G11N), and Localization (L10N).

Terms:

  • Globalization (G11N): The process of making a piece of software to support different languages and regions.
  • Localization (L10N): The process of customizing an app for a given language and region.
  • Internationalization (I18N): Describes both globalization and localization.
  • Culture: It's a language and, optionally, a region.
  • Neutral culture: A culture that has a specified language, but not a region. (for example "en", "es")
  • Specific culture: A culture that has a specified language and region. (for example "en-US", "en-GB", "es-CL")
  • Parent Culture: The neutral culture that contains a specific culture. (for example, "en" is the parent culture of "en-US" and "en-GB")
  • Locale: A locale is the same as a culture.

A multilingual portal allows the site to reach a wider audience. The Alliance Business Suite provides services and middleware for localizing into different languages and cultures.

Internationalization involves Globalization and Localization. Globalization is the process of designing apps that support different cultures. Globalization adds support for input, display, and output of a defined set of language scripts that relate to specific geographic areas.

Localization is the process of adapting a globalized app, which you have already processed for localizability, to a particular culture/locale. For more information see Globalization and localization terms near the end of this document.

App localization involves the following:

  1. Make the app's content localizable
  2. Provide localized resources for the languages and cultures you support
  3. Implement a strategy to select the language/culture for each request

Make the app's content localizable

The ABS Razor Engine was architected to improve productivity when developing localized apps. DynamicComponentBase uses the ResourceManager and ResourceReader to provide culture-specific resources at run time. The interface has an easy-to-use method and an IEnumerable for returning localized strings. DynamicComponentBase retrieves the portal default language from the suite configuration file and then loads localized resources from the Alliance Business Model provider. You can develop an app targeted for localization right out of the box by adding LocalizationStrings and LocalizedStrings through the portal admin center. The code below shows how to wrap the string "About Title" for localization.

@{ 
    var localizedString = _("Hello World!");
}
@localizedString 
@_("Hello World!")

Creating Localizable/Localized Strings

The Alliance Business Suite offers a convenient way to create localizable resources like strings or HTML fragments. Localizable/Localized Strings are retrieved and formatted if you need to insert the value of an object, variable, or expression into the localized resource. For example, you can insert the value of a Decimal value into a paragraph to display it to the user as a single string:

@{
    var pricePerOunce = 17.36m;
    var localizedString = _("The current price is {0} per ounce.", pricePerOunce); 
}
<!-- Result: The current price is 17.36 per ounce. -->
@localizedString 

To create a Localization Resource:

  1. Go to your Suite Admin Center,
  2. Select Internationalization > Strings from the left-hand menu.
  3. Select your base language and target language.
  4. Create or select a new Localization String by selecting the base language variation, providing a Base Value, and optionally leaving a comment for future reference.
  5. With your Localization String selected, refer to the Translations panel and there create a new translation by selecting the target language variation, providing a Target Value, and optionally leaving a comment for future reference.

image.png

@{ 
 var localizedString = __["Hello World!"];
}
@localizedString 

Alliance Business Suite Components

The Alliance Business Suite is composed out of 5 Components.

The Alliance Business Suite was architected as a modular Application Framework. This means that components are able to work without their higher-level components. The lowest Component is the Alliance Core Libraries Component and the highest Component is the Alliance Business Studio Component.

ABS Components.jpg

Alliance Core Libraries

The Alliance Core Libraries contains the core abstractions and default implementations required by the Alliance Business Model and dependent components. It is also the external dependency source for the entire Alliance Business Suite, which means that external dependencies, which are dependencies outside the FenixAlliance.* namespace are referred to by the FenixAlliance.ACL.Deps Package, which is the base ACL Package and, therefore, it could be referred to as the Core Package.

For more information on the dependency tree, design overview and external dependencies, please refer to Advanced Topics.

Alliance Business Model

The Alliance Business Model is a declarative specification and definition of standard entities that represent commonly used concepts and activities across business and productivity applications and is being extended to observational and analytical data as well. ABM provides well-defined, modular, and extensible business entities such as Account, Business Unit, Case, Contact, Lead, Opportunity, and Items (Products/Services), as well as interactions with vendors, workers, and customers, such as activities and service level agreements. that serve as the dynamic data layer for the entire Alliance Business Suite.

Anyone can build on and extend ABM definitions to capture additional business-specific scenarios.

Alliance Passport Service

The Alliance Passport Service enables developers and non-developers alike The Alliance Passport Service is an Authentication/Authorization Engine designed to enable customers to easily configure and manage businesses identity scenarios by assigning (or connecting) a digital identity to their contacts, whether they are customers, employees, partners, guests, and more.

It also provides common features for managing authentication, authorization, data protection, HTTPS enforcement, app secrets, XSRF/CSRF prevention, and CORS management. These security features allow you to build robust, yet secure Alliance Business Suite apps.

Alliance Business Platform

The Alliance Business Platform is a Modular API Framework. It leverages .NET 5.0 with the best of REST, SignalR, GraphQl y gRPCto transact with the Alliance Business Model Schema (AMB). The Alliance Business Platform is an open-source and cross-platform framework for integrating next-generation functionalities into your applications. It allows you to build spectacular single-page apps using .NET and C# with or without JavaScript. ABP apps can connect and transact to the data layer (The Alliance Business Modal Schema) using any language through standard requests through the various GrPC, HTTP, and GraphQL Endpoints.

Anyone can build on and extend The Alliance Business Platform through ASP.NET + Angular / React (And pretty much any Framework), to capture additional business-specific scenarios.

Alliance Business Studio

The Alliance Business Studio is the Graphical Administration Engine for the Alliance Business Suite. It allows users to manage their implementations, transact data through the Alliance Business Platform, generate and consume views, reports, customize and extend the system, and much more.

Anyone can build on and extend The Alliance Business Studio to capture additional business-specific scenarios.

Alliance Business Cloud

The Alliance Business Cloud is an HTTP-based service for hosting Alliance Business Suite Instances and other kinds of applications. These can be developed in your favorite language, be it .NET, .NET Core, Java, Ruby, Node.js, PHP, or Python. Applications run and scale with ease on both Windows-based environments.

The Alliance Business Cloud not only adds the power of Microsoft Azure to your Alliance Business Suite instance, such as security, load balancing, autoscaling, and automated management features; You can also take advantage of its DevOps capabilities, such as continuous deployment from Azure DevOps, GitHub, Docker Hub, and other sources, package management, staging environments, custom domain, and free/paid TLS/SSL certificates.

With Alliance Business Cloud, you pay for the compute resources you use. The compute resources you use are determined by the Service plan that you run your Alliance Business Suite instance on.

Understanding the Alliance Core Libraries.

The Alliance Core Libraries contains the core abstractions and default implementations required by the Alliance Business Model and dependent components. It is also the external dependency source for the entire Alliance Business Suite, which means that external dependencies, which are dependencies outside the FenixAlliance.* namespace are referred to by the FenixAlliance.ACL.Deps Package, which is the base ACL Package and, therefore, it could be referred to as the Core Package.

Dependant components of the Alliance Core Libraries can make use of external dependencies referred by the Core Package thanks to .NET's Waterfall dependency resolution mechanism.

For more information on the dependency tree, design overview, and external dependencies, please refer to Advanced Topics.

Referred External Dependencies

PackageVersion
Amazon.AspNetCore.Identity.Cognito3.0.0
Amazon.Extensions.CognitoAuthentication2.2.2
AngleSharp0.16.0
AspNetCore.HealthChecks.SqlServer5.0.3
AspNetCore.HealthChecks.UI.Client5.0.1
AspNetCore.HealthChecks.UI.InMemory.Storage5.0.1
AspNetCore.HealthChecks.UI5.0.1
AspNetCore.Proxy4.2.0
AspNetCoreRateLimit4.0.1
Autofac.Extensions.DependencyInjection7.1.0
Autofac6.2.0
AutoMapper.Collection.EntityFrameworkCore7.0.1
AutoMapper.Extensions.Microsoft.DependencyInjection8.1.1
AutoMapper10.1.1
Azure.Storage.Blobs12.9.1
Blazor.Extensions.Canvas1.1.1
Blazor.Extensions.SignalR1.0.0
Blazor.Extensions.Storage1.0.0
Blazor.Extensions.WebUSB1.0.0
Blazor.Extensions.XTerm0.1.0
BlazorFluentUI.ListComponents5.5.3
BotSharp.Core0.4.0
ByteSize2.0.0
Catalyst.Models.English1.0.18055
Catalyst1.0.19323
ChartJs.Blazor.Fork2.0.2
CsvHelper27.1.1
Dapper2.0.90
DnsClient1.5.0
DotLiquid2.2.541
Elsa.Activities.UserTask2.2.1
Elsa2.2.1
Emitter1.0.41
FlexLabs.EntityFrameworkCore.Upsert5.0.0
FluentEmail.Core3.0.0
FluentEmail.Smtp3.0.0
FluentValidation.AspNetCore10.3.1
FluentValidation10.3.1
Fluid.Core2.0.13
Flurl.Http3.2.0
GraphQL.Server.Transports.AspNetCore5.0.2
GraphQL.Server.Transports.WebSockets4.4.1
GraphQL.Server.Ui.GraphiQL5.0.2
GraphQL.Server.Ui.Playground5.0.2
GraphQL.Server.Ui.Voyager5.0.2
GraphQL4.6.0
HtmlAgilityPack1.11.36
Humanizer2.11.10
IdentityServer4.EntityFramework.Storage4.1.2
IdentityServer4.EntityFramework4.1.2
IdentityServer44.1.2
JWT8.2.3
LiteDB5.0.11
MailKit2.15.0
MassTransit7.2.2
MatBlazor2.8.0
MediatR.Extensions.Autofac.DependencyInjection7.3.0
MediatR.Extensions.Microsoft.DependencyInjection9.0.0
MediatR9.0.0
MetadataExtractor2.7.0
Microsoft.ApplicationInsights.AspNetCore2.18.0
Microsoft.AspNet.WebApi.Client5.2.7
Microsoft.AspNetCore.Authentication.Abstractions2.2.0
Microsoft.AspNetCore.Authentication.AzureAD.UI5.0.9
Microsoft.AspNetCore.Authentication.AzureADB2C.UI5.0.9
Microsoft.AspNetCore.Authentication.Facebook5.0.9
Microsoft.AspNetCore.Authentication.Google5.0.9
Microsoft.AspNetCore.Authentication.JwtBearer5.0.9
Microsoft.AspNetCore.Authentication.MicrosoftAccount5.0.9
Microsoft.AspNetCore.Authentication.OpenIdConnect5.0.9
Microsoft.AspNetCore.Authentication.Twitter5.0.9
Microsoft.AspNetCore.Authentication2.2.0
Microsoft.AspNetCore.Blazor0.7.0
Microsoft.AspNetCore.Components.Web5.0.9
Microsoft.AspNetCore.Components5.0.9
Microsoft.AspNetCore.DataProtection5.0.9
Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore5.0.9
Microsoft.AspNetCore.Hosting.Server.Abstractions2.2.0
Microsoft.AspNetCore.Hosting2.2.7
Microsoft.AspNetCore.Http.Abstractions2.2.0
Microsoft.AspNetCore.Http.Features5.0.9
Microsoft.AspNetCore.Http2.2.2
Microsoft.AspNetCore.Identity.EntityFrameworkCore5.0.9
Microsoft.AspNetCore.Identity.UI5.0.9
Microsoft.AspNetCore.Mvc.Core2.2.5
Microsoft.AspNetCore.Mvc.NewtonsoftJson5.0.9
Microsoft.AspNetCore.Mvc.Razor.Extensions5.0.9
Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation5.0.9
Microsoft.AspNetCore.Mvc.WebApiCompatShim2.2.0
Microsoft.AspNetCore.Mvc2.2.0
Microsoft.AspNetCore.Razor.Language5.0.9
Microsoft.AspNetCore.SignalR.Core1.1.0
Microsoft.AspNetCore.SpaServices.Extensions5.0.9
Microsoft.Azure.KeyVault.Core3.0.5
Microsoft.Bot.Builder.AI.Luis4.14.1
Microsoft.Bot.Builder.Dialogs4.14.1
Microsoft.Bot.Builder.integration.AspNet.Core4.14.1
Microsoft.CSharp4.7.0
Microsoft.EntityFrameworkCore.Design5.0.9
Microsoft.EntityFrameworkCore.Proxies5.0.9
Microsoft.EntityFrameworkCore.Relational5.0.9
Microsoft.EntityFrameworkCore.Sqlite5.0.9
Microsoft.EntityFrameworkCore.SqlServer5.0.9
Microsoft.EntityFrameworkCore.Tools5.0.9
Microsoft.EntityFrameworkCore5.0.9
Microsoft.Extensions.Caching.Abstractions5.0.0
Microsoft.Extensions.Caching.Memory5.0.0
Microsoft.Extensions.Caching.SqlServer5.0.1
Microsoft.Extensions.Configuration.Abstractions5.0.0
Microsoft.Extensions.DependencyInjection.Abstractions5.0.0
Microsoft.Extensions.DependencyInjection5.0.2
Microsoft.Extensions.Diagnostics.HealthChecks.Abstractions5.0.9
Microsoft.Extensions.Diagnostics.HealthChecks.EntityFrameworkCore5.0.9
Microsoft.Extensions.Hosting.Abstractions5.0.0
Microsoft.Extensions.Hosting5.0.0
Microsoft.Extensions.Http5.0.0
Microsoft.Extensions.Localization.Abstractions5.0.9
Microsoft.Extensions.Localization5.0.9
Microsoft.Extensions.Logging.Abstractions5.0.0
Microsoft.Extensions.Logging.Console5.0.0
Microsoft.Extensions.Logging.Debug5.0.0
Microsoft.Extensions.Logging5.0.0
Microsoft.Extensions.Primitives5.0.1
Microsoft.Graph4.3.0
Microsoft.Identity.Client4.35.1
Microsoft.Identity.Web.UI1.16.0
Microsoft.Identity.Web1.16.0
Microsoft.IdentityModel.Tokens6.12.2
Microsoft.ML.AutoML0.18.0
Microsoft.ML.CpuMath1.6.0
Microsoft.ML.DataView1.6.0
Microsoft.ML.EntryPoints0.18.0
Microsoft.ML.Recommender0.18.0
Microsoft.ML1.6.0
Microsoft.OpenApi1.2.3
Microsoft.Rest.ClientRuntime.Azure.Authentication2.4.1
Microsoft.TestPlatform16.11.0
Microsoft.VisualBasic10.3.0
Microsoft.VisualStudio.Web.BrowserLink2.2.0
Microsoft.VisualStudio.Web.CodeGeneration.Design5.0.2
Mobsites.Blazor.SignaturePad1.1.7
MongoDB.Bson2.13.1
MongoDB.Driver2.13.1
MudBlazor.ThemeManager1.0.5
MudBlazor5.1.1
Newtonsoft.Json13.0.1
NodaTime.Serialization.JsonNet3.0.0
NodaTime3.0.5
NReco.LambdaParser1.0.12
NuGet.Packaging5.11.0
NuGet.Protocol5.11.0
Okta.AspNetCore3.5.0
Polly.Caching.Memory3.0.2
Polly7.2.2
Pomelo.EntityFrameworkCore.MySql5.0.1
QRCoder1.4.1
RabbitMQ.Client6.2.2
Radzen.Blazor3.9.2
Razor.Templating.Core1.5.0
RazorLight1.1.0
ReactiveUI.Blazor15.1.1
reCAPTCHA.AspNetCore3.0.10
RestSharp106.12.0
Sendgrid9.24.2
Seq.Extensions.Logging6.0.0
Serilog.AspNetCore4.1.0
Serilog.Enrichers.Environment2.2.0
Serilog.Enrichers.Process2.0.2
Serilog.Enrichers.Thread3.1.0
Serilog.Settings.Configuration3.2.0
Serilog.Sinks.AzureBlobStorage3.0.2
Serilog2.10.0
SixLabors.ImageSharp.Web1.0.3
SixLabors.ImageSharp1.0.3
StackifyMiddleware3.0.5.2
Standard.Licensing1.1.5
Swashbuckle.AspNetCore.SwaggerGen6.1.5
Swashbuckle.AspNetCore.SwaggerUI6.1.5
Swashbuckle.AspNetCore.Swagger6.1.5
System.ComponentModel.Annotations5.0.0
System.IdentityModel.Tokens.Jwt6.12.2
System.IO.FileSystem.AccessControl5.0.0
System.Reactive5.0.0
System.Security.Permissions5.0.0
System.ServiceModel.Duplex4.8.1
System.ServiceModel.Http4.8.1
System.ServiceModel.NetTcp4.8.1
System.ServiceModel.Primitives4.8.1
System.ServiceModel.Security4.8.1
System.Text.Json5.0.2
Toolbelt.Blazor.HotKeys10.0.1
UnitConversion1.0.41
Unity5.11.10
Z.EntityFramework.Plus.EFCore5.2.7
ZXing.Net0.16.6
ZXingBlazor0.1.6

Alliance Business Model (ABM) Schema

In a nutshell, the Alliance Business Model serves as the main dynamic data layer for the entire Alliance Business Suite.

The Alliance Business Model is a declarative schema definition of standard entities representing commonly used concepts and activities across business and productivity applications and is being extended to observational and analytical data.

The Alliance Business Model provides well-defined, modular, and extensible business entities such as Account, Deal Unit, Case, Contact, Lead, Opportunity, and Product, as well as interactions with suppliers, employees, and customers, such as activities and service level agreements.

Configurations

When installing the Alliance Business Suite on a given server, you'll be required to provide the Connection Strings to the Database that will host the Alliance Business Model Schema.

You can change several configurations using these connections strings too, for example, increase/decrease certain default values or even to point to another database (when migrating, for example) and, Although not recommended, you can even change the Database Engine that's providing SQL services to your running instance.

Providers

The Alliance Business Model was designed to work with several SQL Database providers such as Oracle SQL, Microsoft SQL Server, MySQL, MariaDB, PostgreSQL.

The SQL engine that your Alliance Business Suite's instance is going to use can be selected on the installation process.

Extensions

We're currently working to let anyone extend the Alliance Business Model definitions to capture additional business-specific scenarios.

As of 1.2.0, Custom engines can be supported by generating the appropriate migrations required for the Alliance Business platform in order to work properly.

When building custom engines, you'll be required to manage these migrations yourself, which is kind of a pain, so we're experimenting on in-Database-Database Engine as well as NoSQL interoperability to allow customers to easily extend the Alliance Business Model Schema Specification. Also, we're working on providing Per-Record SQL File-Databases with Distributed File System Support.

We're also currently working on providing even more convenient interfaces for customers extending the Alliance Business Model procedurally or through the Alliance Business Studio.

Entities

Use the Alliance Business Suite's API reference to explore and learn about all the available Alliance Business Model entity definitions, their attributes, and purposes. These entities span several business domains and describe data in different applications and solutions. For example, you can find entity definitions related to Accounting, Learning, Human Resources, and more.

We also maintain a Visual Reference Diagram on GitHub to allow customers to easily identify entities on the Alliance Business Model.

Understanding Alliance Business Model Records

In a nutshell, Alliance Business Records are records stored into the Alliance Business Model Schema. These records contain the structured, relational data scoped to a Business Tenant and might be composed of one or more related database registries.

Work with data using web services

There are two different access methods, each using a different protocol, to manage the Alliance Business Model: a set of Web and Code APIs. Your code can access the Alliance Business Model through either the Web Service endpoints or using the SDK API.

Alliance Passport Services Overview

Overview

The Alliance Business Suite contains a powerful and extensible Authentication and Authorization engine called the Alliance Passport Service ("APS").

How to get started?

The Alliance Passport Service enables developers and non-developers alike to easily configure and manage identity scenarios. The Alliance Passport Service Engine contains features for managing authentication, authorization, data protection, HTTPS enforcement, app secrets, XSRF/CSRF prevention, and CORS management. These security features allow you to build robust, yet secure Alliance Business Suite apps.

Common Terms

Learn more about APS + IAM terms.

  • Permission Sets: refer to the ABM record objects that are used to grant access to resources. You can attach Permission Sets to Identities. These include BusinessProfileRecord, BusinessPermission, SecurityGroup, and SecurityRole.

  • Identities: The ABM record objects that APS uses to authenticate and group. These include AccountHolder, BusinessTenant, BusinessApplication and BusinessDomain.

  • Users A person or application that uses an Identity. Although AccountHolder is the most common type of Identity, BusinessApplication can also be used to sign in and make requests to the Alliance Business Platform's APIs within the scope of a BusinessTenant or a BusinessDomain.

Managing Identity

With the Alliance Business Suite, you can easily manage Authentication and Authorization flows.

Understanding how APS works

Before you create Account Holders or Business Tenants, you should understand how APS enables IAM workflows.

Alliance Passport Services (commonly known as "APS") is an Identity Engine that provides the infrastructure necessary to control authentication and authorization for the Alliance Business Suite.

The Identity and Access Management Module ("IAM") is an extension built on top of the Alliance Passport Services Framework to allow users and applications to connect to certain Alliance Business Suite instances.

Authentication vs. Authorization

Authentication is a process in which a user provides credentials that are then compared to those stored by an operating system, database, app, or resource. If they match, users are authenticated successfully, and can then perform actions that they're authorized for, during an authorization process. The authorization refers to the process that determines what a user is allowed to do.

Another way to think of authentication is to consider it as a way to enter a space, such as a server, database, app, or resource, while authorization is which actions the user can perform to which objects inside that space (server, database, or app).

Authentication fundamentals

An Account Holder must be authenticated (signed in to the Alliance Business Suite) using their credentials to send a request to any Alliance Business Platform API. Some modules, such as Media Portals, ICX Stores, and ABS Workplace, allow a few requests from anonymous users. However, they are the exception to the rule.

Users

A User is a person or application that can make a request for an action or operation on an ABM resource. The User is authenticated as a Security Identity to make requests to allowed resources through the Alliance Business Platform set of APIs.

Note: As a best practice, do not use your root user credentials for your daily work. Instead, create an additional Account Holder with a more limited Permission Set. You can also support federated users or programmatic access by allowing a Business Application to access your ABS instance.

Root Users

To authenticate from the root user, you must sign in with the email address and password you provided when installing the instance. As any other regular IAM user, root users can set up multi-factor authentication through an authenticator app such as Google Authenticator, Microsoft Authenticator, or really any MFA TOTP (Time-based One-time Password Algorithm) application.

API Users

To authenticate from the API or ABS Commander CLI (Bash or Powershell), you must create and provide an access key and secret key. You can get these keys by installing and navigating to the ABS Self-integration.

Users might also be required to provide additional security information. For example, Fenix Alliance recommends that you use multi-factor authentication (MFA) to increase the security of your account and to enforce it on Privileged Account Holders. To learn more about the IAM entities that the Alliance Passport Service can authenticate, see APS Identity Holders and APS Security Roles.

Authentication Middleware

The Alliance Business Suite uses two primary middlewares for authentication. A Cookie-based authentication engine and standard Token-based authentication.

When a user authenticates into an Alliance Business Suite instance using their username and password (or any other authentication provider, for that matter), they're issued a cookie, containing an authentication token that can be used for authentication and authorization. The token is stored in the browser as a cookie that accompanies every request the client makes to the application. Generating and validating this cookie is performed by the APS Cookie Authentication Middleware. The middleware serializes a user principal into an encrypted cookie. On subsequent requests, the middleware validates the cookie, recreates the principal, and assigns the principal to the User property present on controllers, views, components, and more.

Token-based authentication

When a user is authenticated, they're issued a token (not an anti-forgery token). The token contains user information in the form of claims or a reference token that points the app to the user state maintained in the app. When a user attempts to access a resource requiring authentication, the token is sent to the app with an additional authorization header in form of a "Bearer token".

"Bearer tokens" make the app stateless. In each subsequent request, the token is passed in the request for server-side validation. This token isn't encrypted; it's encoded. On the server, the token is decoded to access its information. To send the token on subsequent requests, the token is saved in the browser's local storage. This design prevents CSRF vulnerability as the token is stored in the browser's local storage. CSRF is a concern when the token is stored in a cookie.

Identity Providers:

Although but you can use third-party identity services such as Facebook, Twitter, and LinkedIn, or even enterprise services such as Azure AD, Azure AD B2C, AWS Cognito (preview), Okta (preview), and many more, the Alliance Business Suite provides many tools and libraries to secure your apps including built-in identity providers, TOTP MFA (Time-based One-time Password Algorithm Multi-Factor Authentication) support.

Authorization Fundamentals

Users must also be authorized (allowed) to complete any request. During authorization, the APS Engine uses values from the request context to check for policies that apply to the request. It then uses the policies to determine whether to allow or deny the request. Most policies are stored in the ABS as ABM Records and specify the permissions for principal entities. There are several types of policies that can affect whether a request is authorized. To provide your users with permissions to access any layer of the Alliance Business Suite, you need only identity-based ABM records. Resource-based policies are popular for granting cross-account access. The other policy types are advanced features and should be used carefully.

The APS Engine checks each policy that applies to the context of any given request. If a single permissions policy is missing, a denied action will be returned, APS denies the entire request and stops evaluating. This is called an explicit deny. Because requests are denied by default, APS authorizes your request only if every part of your request is allowed by the applicable permissions policies. The evaluation logic for a request within a single account follows these general rules:

  • By default, all requests are denied. (In general, requests made using the ABS root user credentials for resources in the instance are always allowed.)

  • An explicit allow in any permissions policy (identity-based or resource-based) overrides this default.

  • The existence of a Parent Tenant' IAM permissions boundary or a session policy overrides the allow. If one or more of these policy types exists, they must all allow the request. Otherwise, it is implicitly denied.

  • An explicit deny in any policy overrides any allows.

To learn more about how all types of policies are evaluated, please refer to Authorization evaluation logic. If you need to make a request in a different account, a policy in the other account must allow you to access the resource, and the Identity Entity that you use to make the request must have an identity-based policy that allows the request.

Security Permissions

After your request has been authenticated and authorized, the Alliance Passport Service approves the actions or operations in your request. Operations are defined by service and include things that you can do to a resource, such as reading, creating, editing, and deleting that resource. For example, APS supports several actions for each ABM Record, including the following actions:

  • Create
  • Read
  • Update
  • Delete

To allow an Identity to perform an operation, you must include the necessary actions in a role and then assign to the Identity the Role that grants action access to the affected resource type.

Resources

After the Alliance Passport Service Engine approves the operations in your request, it can be performed on the related ABM Records within the Alliance Business Model. A resource is an object that exists within an Alliance Business Suite instance. Examples include a Financial Account Record in the ABM, an IAM user, and a Storage File. The service defines a set of actions that can be performed on each resource through its exposed API Methods through either the REST Application Programming Interface or a GUI, like the Alliance Business Studio or a Portal. If you create a request to perform an unrelated action on a resource, that request is denied. For example, if you request to delete an IAM role but provide an IAM group resource, the request fails. Please refer to the BusinessPermission tables that identify which resources are affected by an action, see Actions, Resources, and Business Permissions for Alliance Business Suite Resources.

Introduction to Account Holder Entities

An Account Holder is a CredentialsPrincipal for the APS Engine. It represents a human user identified by a username/password. (Unless using some kind of federated identity service like Azure Active Directory, Google, Facebook, Microsoft Identity, etc...)

The "Credentials" aspect of APS Identity and Access Management (IAM) helps you with the question "Who is that user?", often referred to as authentication. Instead of sharing your root user credentials with others, you can create individual Account Holders within your instance that correspond to users in your organization.

In the following figure, the users Sebastien, Fernando, Camila, Alejandro, Ana, and Julianna have been added to a single ABS Instance. Each Account Holder will have their own credentials.

First-time access only: Your root user credentials

When you create an ABS Instance, you create an APS Account Holder root identity, which you will use to sign in to the instance. You can sign in to the ABS Studio and the ABS Portal Admin using this root user identity; that is, the email address and password that you provided when installing the instance. This combination of your email address and password is also called your root user credentials.

When you use your root user credentials, you have complete, unrestricted access to all resources in your ABS instance, including access to your billing and licensing information and the ability to change your password and set multi-factor authentication. This level of access is necessary when you first set up your account. However, we recommend that you don't use root user credentials for everyday access. We especially recommend that you do not share your root user credentials with anyone because doing so gives them unrestricted access to your instance. Only service control policies (SCPs) in tenants can restrict the permissions that are granted to the root user.

We recommend that you create an Account Holder for yourself and then assign yourself administrative permissions for your account. You can then sign in as the new user to add more users and transact over resources as needed.

The following sections explain how you can use APS to create and manage user identity and permissions to provide secure, limited access to your ABS instance, both for yourself and for others who need to work with your ABS instance.

Create an Account Holder

Creating an Account through a local account.


Account Holders are not unrelated records; they are users within your ABS Portals, Contacts within your CRM, Students within your LMS, Account Owners within your Accounting Management Engine, Business Employees within a given Business Tenant, and much more.

Each Account Holder can have their own password for access to the ABS. You can also create an individual access key for each user so that the user can make programmatic requests to work with resources in your account.

By default, ABS Portals are configured to allow Guest Users and Customer Users. These Guest Users are unauthenticated portal visitors granted with a limited set of permissions, like store_read, cart_view, cart_update, while Customer Accounts are allowed for more extensive permissions such as account_read, account_delete, account_update, wallet_read, and others.

If the Enable New User Option is marked to true, Guest Users can quickly create and manage their Account Holder credentials by themselves. The APS Engine is configured to allow local or federated accounts by enabling and configuring additional identity providers such as Google, Facebook, Microsoft, LinkedIn, Twitter, and more.

When creating a local account, you will be asked to verify your email address through a code.

The IAM module contains all the access logic to the Alliance ID account, It is composed of roles capable of assuming a certain set of permissions to act on behalf of a Business Tenant.

image.png

Federating existing users

If the users in your organization already have a way to be authenticated, such as by signing in to your corporate network, you don't have to create separate IAM users for them. Instead, you can federate those user identities into the APS Engine.

Federation is particularly useful in these cases:

Your users already have identities in a corporate directory: If your corporate directory is compatible with Security Assertion Markup Language 2.0 (SAML 2.0), you can configure your corporate directory to provide single-sign-on (SSO) access to the APS Engine for your users. For more information, refer to Common scenarios for temporary credentials.

If your corporate directory is not compatible with SAML 2.0, you can create an identity broker extension to provide single-sign-on (SSO) access to the APS Engine for your users. For more information, see Enabling custom identity broker access into an ABS Instance.

If your corporate directory is Microsoft Active Directory, you can use Azure Active Directory to establish trust between your corporate directory and your ABS instance.

Your users already have Internet identities: If you are creating a mobile app or web-based app that can let users identify themselves through an Internet identity provider like Login with Amazon, Facebook, Google, or any OpenID Connect (OIDC) compatible identity provider, the app can use federation to access ABS resources. For more information, see About web identity federation.

Enabling supported identity providers

To enable an external identity provider into your Alliance Business Suite instance you'll need to use the following topics to configure your instance to use the respective providers:

image.png

Optionally set password

When you register with an external login provider, you don't have a password registered with the app. This alleviates you from creating and remembering a password for the site, but it also makes you dependent on the external login provider. If the external login provider is unavailable, you won't be able to sign in to the website.

To create a password and sign in using your email that you set during the sign-in process with external providers: Select the Hello link at the top-right corner to navigate to the Manage view.

Creating your Alliance ID through an identity provider: (e.g. Amazon, Facebook, LinkedIn, Google...)


If you don’t already have an Alliance ID account, you can get it for free by using those accounts that you already own and use (like your social media accounts). For this matter, you will need to select the identity provider of your choice when you create your Account Holder.

You will need to log in to your Alliance ID account through your chosen identity provider to get access to your account and resources.

Enabled Identity Providers


description: >- To create a new business you will need to be legally authorized to act on the name of that business, as you will need to sign the terms and conditions for our business network on its behalf.

Business Tenant Accounts

Once a user has an Alliance ID account, they will be able to create one or more Business Tenants. There is currently a creation limit of 5 Business Tenants per Alliance ID Holder.

An Alliance ID Holder can request the Alliance support service to raise the tenant quota given the need.

Create a new business account

Prerequisites: In order for you to follow this tutorial, you need to make sure you already own an Alliance ID Account.

How to create a business tenant?

To create a business tenant, login to your Alliance ID Account. Make click on your name and select "My Alliance ID Profile" from the dropdown list. This will take you to you Accounts Principal Page.

Place your mouse on the right-hand side corner of your screen, over your name and you will see a dropdown list containing your authorized businesses. Then, select "Create a business".

This step will take you to the Business Creation Form. Fill the form and make sure that you are legally authorized to act on the name of that business, as you will need to provide documentation to support that claim.

Business creation form. v1.0.0

Note that creating a business can sometimes take a few seconds.

Once your form has been correctly filled, your business' information will be submitted for review, but your business tenant account will be created successfully and your Alliance ID Holder will be added as the root account for that business.

You have now successfully created a business tenant account and only your current Alliance ID Account will be able to select it as root.

Security Roles


When an identity is created it may belong to one or more roles. For example, Daniel may belong to the Administrator and User roles, while Ana may only belong to the User role.

How these roles are created and managed depends on the backing store of the authorization process. Roles are exposed to the developer through the IsInRole method on the IAuthService class.

You can use roles to delegate access to APS Identities like Account Holders, applications, or services that don't normally have access to your ABS resources. For example, you might want to grant users in your Alliance Business Suite instance access to resources they don't usually have, or grant users in one server instance access to resources in another instance. Or you might want to allow a mobile app to use Alliance Business Suite resources, but not want to embed access keys within the app (where they can be difficult to rotate and where users can potentially extract them). Sometimes you want to give access to users who already have identities defined outside of your server instance, such as in your corporate directory. Or, you might want to grant access to your account to third parties so that they can perform an audit on your resources.

For these scenarios, you assign them a Security Role that provides the permissions they need. For example, you can assign roles to allow adding or changing users, resetting user passwords, managing user licenses or managing domain names.

Default Account Holder permissions

In Alliance Passport Services , every Account Holder is granted a set of default permissions. An Account Holder’s access consists of the type of user, their role assignments, and their ownership of individual records. This article describes those default permissions and contains a comparison of the member and guest user defaults. The default user permissions can be changed only in user settings in Alliance Business Studio.

Member and Guest Account Holders

The set of default permissions received depends on whether the user is a native member of the tenant (member user) or if the user is unrelated to the acting tenant or brought over from another tenant as a guest (guest user).

  • Member Account Holders can access the Alliance Business Studio, create and update owned Alliance Business Model records, register applications, manage their own profile photo and mobile phone number, change their own password, and invite guests.

  • Guest users have restricted permissions. They can manage their own profile, view related records, change their own password and retrieve some information about other users, products, groups, and apps, however, they cannot read Alliance Business Model records. For example, guest users cannot enumerate the list of all users, groups, and other directory objects. Guests can be added to administrator roles, which grant them full read and write permissions contained in the role. Guests can also invite other guests.

Security Groups

There are two forms of common security identities in Alliance Passport Services: Account Holders and Business Tenants. These accounts represent an entity (a person or an organization).

Account Holders can also be used as dedicated service accounts for some applications. Security groups are used to collect user accounts, service accounts, and other groups into manageable units.

Security groups can provide an efficient way to assign access to resources on your Alliance Business Suite. By using security groups, you can:

Assign Business Permissions to security groups.

Business Permissions can be assigned to a security group to determine what members of that group can do within the scope of a Business Tenant. Business Permissions are automatically assigned to some security groups when the Alliance Business Suite is installed to help administrators define a person’s administrative role.

For example, a user who is added to the Global Administrators group in Alliance Passport Services has the ability to access the Alliance Business Studio Manager. This is possible because, by default, the Business Permission studio_access is automatically assigned to the Global Administrators group through the "Admin" Security Role being assigned to that group. Therefore, members of this group inherit the Business Permissions that are assigned to that Security Group.

You can use Group Policy to assign user rights to security groups to delegate specific tasks. For more information about using Group Policy, see User Rights Assignment.

Assign Roles to security groups.

Like Business Permissions, Security Roles are assigned to Identities to grant access to certain resources. Business Permissions determine who can access the resource and the level of access, such as Full Control.

A Security Role is a group of permissions that grant access to various levels of access, such as the Account Operators Role or the Domain Admins group. When assigning permissions for resources to a Security Role, administrators assign those permissions to a Security Role rather than to individual users.

The permissions are assigned once to the Security Role, instead of several times to each individual user. Each account that is added to a Security Role receives the Business Permissions that are assigned to that Security Role in Alliance passport Services, and the user receives the permissions that are defined for that group.

Security groups can be assigned with an Email Address so that sending an email message to the group forwards the message to all the members of the group.

Working with Business Permissions

After your request has been authenticated and authorized, the Alliance Passport Service approves the actions or operations in your request. Operations are defined by service and include things that you can do to a resource, such as reading, creating, editing, and deleting that resource. For example, APS supports several actions for each ABM Record, including the following actions:

  • Create
  • Read
  • Update
  • Delete

To allow an Identity to perform an operation, you must include the necessary actions in a role and then assign to the Identity the Role that grants action access to the affected resource type.

Granting Business Permissions

Business Permissions can be assigned to any APS Identity either as a single permission or through a role that contains the specified permission.

Business Permissions can be granted through the Alliance Business Studio on the Security Trail Module.

Alliance Business Platform (ABP)


The Alliance Business Platform is a Modular Application Framework built on .NET with the best of REST, SignalR, GraphQl y gRPC capabilities and it's built on top of the the Alliance Business Model Schema (ABM).

The Alliance Business Platform is also a Mobile Backend framework for integrating next-generation functionalities into your mobile applications.

It allows you to build spectacular single-page apps using .NET and C# with or without JavaScript. ABP apps can connect and transact to the data layer (The Alliance Business Modal Schema) using any language through standard requests through the various GrPC, HTTP, and GraphQL Endpoints.

The Alliance Business Platform provides a unified programmability model that you can use to build apps for organizations and consumers that interact with the data on the Alliance Business Model.

You can use the Alliance Business Platform APIs to access data stored on your Alliance Business Model, scoped to any given Business Tenants; Explore our documentation to learn more about how to use Fenix Alliance's ABP APIs.

Anyone can build on and extend The Alliance Business Platform through ASP.NET + Angular / React (And pretty much any Framework), to capture additional business-specific scenarios.

Explorers

The Alliance Business Platform integrates a comprehensive API Specification for every HTTP, GrapghQL or gRPC request that's available on every Alliance Business Suite instance. These specifications follow well stablished standards to give customers the flexibility and support required to extend the system with their own custom functionalities to easily build breathtaking business applications.

API Explorers

HTTP

  • https://{yourinstancedomain}/api/v2/documentation

GraphQL

  • https://{yourinstancedomain}/api/v3/playground
  • https://{yourinstancedomain}/api/v3/voyager
  • https://{yourinstancedomain}/api/v3/GraphiQL

Security

The Alliance Business Platform provides many tools and solutions to secure your apps including built-in identity providers, third-party identity services interoperability (such as Facebook, Twitter, LinkedIn, Google and More).

With Alliance Business Platform, you can easily manage app secrets, which are a way to store and use confidential information and it also provides protection against common vulnerabilities in software to help you secure your apps and prevent security breaches. The following list of techniques are forecefuly prevented to avoid the most common security vulnerabilities in web apps:

  • Cross-Site Scripting (XSS) attacks
  • SQL injection attacks
  • Cross-Site Request Forgery (XSRF/CSRF) attacks
  • Open redirect attacks

You should be aware there are more vulnerabilities that you should be aware of. For more information on tooling and further considerations, see the other articles in the Security and Identity sections of the table of contents.

Extensibility

You can extend the Alliance Business platform through Modules, which are nothing more than Razor Class Libraries built with or without the use of the Alliance Business Suite's SDK.

Welcome to the Alliance Business Platform REST API reference for the v2.0 endpoint.

[[TOC]]

API sets on the ABS v2.0 endpoint are in general availability (GA) status, and have gone through a review-and-feedback process with customers to meet practical, production needs. Updates to APIs on this endpoint are additive in nature and do not break existing app scenarios.

Representational State Transfer (REST) APIs are service endpoints that support sets of HTTP operations (methods), which provide create, retrieve, update, or delete access to the service's resources. This section will give you an overall overview of processes like:

  • How to call ABP REST APIs with Postman, CURL and the Powershell SDK.
  • Common use cases for the ABP REST API.
  • The basic components of a REST API request/response pair.
  • How to register your client application with ABP Identity and access management (IAM) to secure your REST requests.
  • Overviews of creating and sending a REST request, and handling the response.
  • Additional resources about versioning and support contact information.

How to call the ABP REST APIs with Postman

The following video will show you how to quickly authenticate with the ABP REST API Authentication Endpoints via the client id/secret method. We encourage you to continue reading below to learn about what constitutes a REST operation, but if you need to quickly call the APIs, this video is for you.

// TODO: ADD Video explaining Postman process.
// TODO: ADD Video explaining CURL process.
// TODO: ADD Video explaining Powershell SDK process.

Available Endpoint Sets - REST API Reference Browser

The Alliance Business Platform REST API has been decoupled into modular, consumable REST Endpoint Sets as follows:

The ABP REST API Browser – is a tool to allow internal and external developers to get the most out of the REST APIs from Fenix Alliance. If you have any feedback, create a new issue in the FenixAlliance/feedback repo on GitHub.

Common use cases

The power of the Alliance ID API lies in easy navigation of entities and relationships across different services exposed on a single Microsoft Graph REST endpoint.

A number of these services are designed to enable rich scenarios around Alliance ID Tenants and around Business Contexts.

User-centric use cases in v2.0

  1. Get the profile and photo of Anna, an Alliance ID Holder.
  2. Get the profile information about Anna's Business Enrollments (BPRs) and IDs of her direct relations.
  3. Access Anna's files on Alliance ID User Storage, find the identity of the last person who modified a file on Anna's enrolled businesses, and navigate to that person's social profile.
  4. Access Anna's follows and followers on the Alliance ID Network, get information and manage their relationships and navigate to their profile endpoint.
  5. Manage Subscriptions and communication options and track changes in Anna's change-log.
  6. Set automatic replies and social statuses when Lisa is away from the office.
  7. Get the people who are most relevant to Lisa, based on communication, collaboration, social activity, and business relationships.
  8. Get Anna's projects and assigned tasks.
  9. Get Anna's cart status, place and manage products, services, and cloud resource orders.
  10. Navigate through Anna's wallet endpoints, which allow developers to extend their Anna's experience and easily conduct transactions directly trough their Alliance ID Wallet's secure federated payment capabilities.
  11. Get Anna's notifications and filter the output through query parameters.
  12. Set automatic reminder's on Anna's calendar. (Soon at Winter Update)

Business use cases in v2.0

  1. Run a report on an organization Anna belongs to and identify the group with the most communication among group members.

Other API versions

There are currently 2 versions of the Alliance ID REST APIs - v2.0 and v2.1 (still in beta). Be aware that APIs in beta status is subject to change, and may break existing scenarios without notice. Don't take a production dependency on APIs in the beta endpoint. Be aware that V1.x endpoints and SDKs were deprecated as of 31/12/2015 and are no longer functional.

Find more information about versioning and support.

Connect with us

Are there additional APIs or features you'd like to see in the AiD API? Post new feature requests on UserVoice.

Have feedback for existing Fenix Alliance API Endpoints? Connect with us on Github.

Working with the Alliance Business Suite SDK

This topic provides information about where you can download the developer tools, assemblies, and code samples that are shipped as part of the Software Development Kit (SDK) for the Alliance Business Suite.

SDK assemblies

The SDK assemblies are available as NuGet packages that you can directly use in your Visual Studio projects. For information about using a NuGet package in Visual Studio, see Install and use a package in Visual Studio

The following SDK assemblies are available:

Package NameTop AssemblyPackage Location
FenixAllaince.ABS.SDKFenixAllaince.ABS.SDK.dllhttps://www.nuget.org/packages/FenixAlliance.ABS.SDK/
FenixAllaince.ABP.SDKFenixAllaince.ABP.SDK.dllhttps://www.nuget.org/packages/FenixAlliance.ABP.SDK/
FenixAllaince.APS.SDKFenixAllaince.APS.SDK.dllhttps://www.nuget.org/packages/FenixAlliance.APS.SDK/
FenixAllaince.ABM.SDKFenixAllaince.ABM.SDK.dllhttps://www.nuget.org/packages/FenixAlliance.ABM.SDK/

Using the Alliance Business Suite SDK.

The Alliance Business Suite SDK provides several interfaces and default implementations designed to speed up business application development. By leveraging the SDK, developers can create outstanding personalized experiences for their customers, employees, providers, and more.

Although it is possible to combine programming models, the first step towards developing Alliance Business Suite Applications/Extensions is to decide the Programming Model to use.

Note: Alliance business Suite Applications/Extensions can be created using .NET or Node.js. This article focuses on the ABS SDK for .NET. As of version 1.2.x, the ABS SDK for Node.js hasn't been published, and requests have to be performed against the Alliance Business Platform Web APIs.

By using .NET and Visual Studio and the ABS SDK for .NET, developers can easily create extensions either by using ASP.NET MVC or Blazor to cover specific business needs while leveraging the power of C# and the Alliance Business Suite.

Overriding Default Service Implementations.

Customers can also use the Alliance Business Suite to override the default Interface Implementations present on every Alliance Business Suite instance. To do so, just implement the desired interface and register it as a Service Override on the ConfigureServices method present on the IModule Interface.

Alliance Business Studio (ABS Studio)


The Alliance Business Studio is the Graphical Administration Engine for the Alliance Business Suite. It allows users to manage their instances, transact data, generate and consume views, reports, customize and extend the system, and much more.

We're building the Alliance Business Studio to help you manage your entire Alliance Business Suite trough an intuitive, user-friendly interface designed to increase your productivity by using cutting-edge technologies such as Blazor on .NET, allowing us to deliver bazing-fast functionalities.

Accessing the Studio

The Alliance Business Studio can be used by navigating to the /Studio route on an existing Alliance Business Suite installation. To access the Alliance Business Studio, Account Holders are required to, at least, have the studio_access permission.

By default, business tenant administrators can access the studio independently of whether or not they have the studio_access permission.

We recommend customers to enforce Multi-Factor Authentication on Administrator Accounts to increase security on privileged account holders.

Extending the Studio

The Alliance Business Studio is built on top of the Alliance Business platform and extends it's functionality through pluggable modules and integrations. In fact, the Alliance Business Studio itself is an Alliance Business Platform Module.

Modules can be hooked to the Alliance Business Studio to allow instance owners to interact with data and functionalities exposed by such module. This is convenient for developers looking to extend the Alliance Business Platform as it provides a clean interface and thousands of ready to use UI components and tools to create data-driven business applications.

Use the Alliance Business Pocket as a Mobile Application Framework (Experimental)

Alliance Business Suite Mobile Apps is a set of client and server libraries aimed to create mobile/desktop applications that integrate to the Alliance Business Suite using Blazor on .NET MAUI.

Currently, we support:

  • .NET + Blazor on the server-side (for security)
  • .NET MAUI + Blazor Client-side (Access to Native APIs)

Alliance Business Cloud Overview

The Alliance Business Cloud is an HTTP-based service for hosting Alliance Business Suite Instances and other kinds of applications. These can be developed in your favorite language, be it .NET, .NET Core, Java, Ruby, Node.js, PHP, or Python. Applications run and scale with ease on both Windows-based environments.

The Alliance Business Cloud not only adds the power of Microsoft Azure to your Alliance Business Suite instance, such as security, load balancing, autoscaling, and automated management features; You can also take advantages of its DevOps capabilities, such as continuous deployment from Azure DevOps, GitHub, Docker Hub, and other sources, package management, staging environments, custom domain, and free/paid TLS/SSL certificates.

With Alliance Business Cloud, you pay for the Azure compute resources you use. The compute resources you use are determined by the App Service plan that you run your instance on.

Why use Alliance Business Cloud?

  • Centralized Control Panel: Build and manage multiple sites from a single dashboard. You can also run updates, monitor performance, and onboard new portals and applications all from the same place.

  • Certified to hyperscale into the cloud: Certified to run on the largest cloud players such as Amazon AWS, Microsoft Azure, Google Cloud, and all major virtualization & container platforms. Deploy, automate and manage ABS servers in just a few clicks with a selection of virtual machine images with the most popular configurations.

  • Robust Site & Server Security: Broad security levels across OS, network, and instances. Built into the Plesk hosting control panel core and enhanced through our class-leading security partners.

  • Compatible across all platforms and hyper-scale options: You get full root access via SSH on every ABC-powered ABS and dedicated server options are available so you can install any third-party, open-source, or customized application you need.

  • Optimized for the Alliance Business Suite: The Alliance Business Cloud helps customers to be more productive by allowing them to develop, debug, and monitor Alliance Business Suite instances and Alliance Business Cloud Apps locally, and deploy to production using powerful integration tools. Use the range of features and capabilities to quickly and efficiently create highly secure applications optimized for the cloud.

  • API and mobile features: Alliance Business Cloud provides turn-key CORS support for RESTful API scenarios, and simplifies mobile app scenarios by enabling authentication, offline data sync, push notifications, and more.

Limitations

  • Alliance Bussiness Suite on Linux is not supported on Alliance Business Cloud. Please check Computeworks Hosting for an alternative solution.

  • The Alliance Business Cloud shows only features that currently work for Windows apps. As features are enabled, they're activated on the portal.

  • When deployed to built-in images, your code and content are allocated a storage volume for web content, backed by Azure Storage. The disk latency of this volume is higher and more variable than the latency of the container filesystem. Apps that require heavy read-only access to content files may benefit from the custom container option, which places files in the container filesystem instead of on the content volume.

The Alliance Business Cloud is designed to help IT specialists manage Alliance Business Suite instances and their required services such as web, DNS, mail, and other services through a comprehensive and user-friendly GUI called the ABC Portal. The ABC Portal is a hosting control panel built on top of Plesk, an intermediary between system services and ABS instances. For example, when a user creates a website through the ABC Portal GUI, Plesk propagates this request to a web server running IIS, and the latter adds a new virtual host to the system. This method of administering all system services from a single web interface reduces maintenance costs and gives administrators more flexibility and control.

How can I use the ABC Portal?

The ABC Portal is an essential instrument for customers, businesses, Alliance Trusted Advisors. Once an instance is provisioned on a server, the ABC Portal enables customers to organize and quickly provision resources and monitor consumption. The customers are companies and individuals who need a strong suite of LOB applications to support their operations in a digital society but do not have the necessary IT infrastructure.

Quick Start with the Alliance Business Cloud

This chapter is intended for people new to the Alliance Business Cloud and has the need to provision an Alliance Business Suite instance, but don´t wanna have to worry about server and database provisioning, dependency configuration & licensing fees. If this is your first time installing an ABS on the Alliance Business Cloud, start here.

Taking your business online through the Alliance Business Cloud has the following benefits (to name just a few):

  • Reduced IT costs.
  • Increases Scalability.
  • Ensures business continuity
  • Increases Collaboration efficiency
  • Flexibility of work & DevOps and SecOps practices
  • Access to automatic updates
  • Makes it easy for customers to find your business.
  • Advertises your business and provides important information.
  • Acts as a convenient feedback form.
  • Get's you up and running in no time.
  • (New) Free SSL Certificates (Let's Encrypt)

There are a number of ways you can quickly get your company on the Alliance Business Cloud. The Alliance Business Suite can then get your web presence up and running. The Alliance Business Suite may be as simple as a contacts page, or as complex as a large company website with access to an eCommerce+CMS+ERP system on steroids and with superpowers. Getting your business online is as easy as following these three steps:

  • Register a domain name.
  • Get your free ABS license from https://fenix-alliance.com/licensing.
  • Create your ABC Subscription and set your credentials.

These steps are explained in more detail below.

Registering a Domain Name

Think of the domain name as your business digital address. Your customers will use it to find you online, so make sure that it is a good one. The best domain names are short, easy to type, and easy to remember. An example of a domain name is www.example.com. Registering a domain name can be done through one of the many organizations called domain registrars. Your hosting provider will usually be able to assist you in registering a domain name as well. Web hosting services are often bundled with domain name registration offers and vice versa.

Get your free ABS license from https://fenix-alliance.com/licensing.

Create your ABC Subscription and set your credentials.

Viewing Statistics

To view the reports on disk space and traffic usage by your account:

1. Select your subscription.

If you have several subscriptions associated with your account, select the required subscription in the Subscription menu at the top of the screen.

2. Go to Statistics.

The following information is presented in charts:

Disk space used by the following files and directories in the subscription:

  • Websites
  • Mail accounts
  • Databases
  • Logs
  • Backups
  • Chroot directories
  • Configuration files
  • Anonymous FTP directory
  • Traffic used by FTP, web, and mail services during the current month.

FTP field shows the information about the total size of files transferred to and from the subscription over the file transfer protocol.

HTTP field shows the information about the total amount of data transferred from all of your websites over HTTP protocol, that is, retrieved by web browsers.

POP3/IMAP field shows the total amount of data received by all mail accounts under your domains.

SMTP field shows the total amount of data sent by all mail accounts under your domains.

3. Do any of the following:

  • To view a report on the amount of data transferred to and from your sites over FTP, click FTP Statistics.
  • To view a report on the amount of data transferred to and from your FTP directory, which is accessed without authorization, click Anonymous FTP statistics.
  • To view a report on the amount of traffic used by services during a certain month, click Data Transfer Statistics, and select the required month from the menu.

Remember that your subscription can be suspended automatically if you overuse disk space depending on the Provider's policy. Here are some tips that can help you free up some space:

  • Remove any unnecessary and/or obsolete files that are stored in the httpdocs folder.
  • Configure log rotation as described in the Log Files section.
  • Delete outdated emails, or configure your mail client to download email messages from the server by switching to POP3. See the Access Your Mailbox section for more information.
  • Remove outdated backup files as described in the Uploading and Downloading Backup Files section.
  • Remove unnecessary databases. See the Website Databases section for more information.

The Disk space usage by services chart displays how much space is taken up by website content, emails, backups, logs, and databases. It makes sense to pay attention to the services that use the most disk space. If none of the steps above helped, contact your provider to increase the amount of disk space available to your subscription.

view-statistics.png

Depending on your service plan, the following hosting features may be available for your websites (listed at the Account > Hosting Options tab):

SSL/TLS support.

This allows you to secure connections to websites with SSL/TLS encryption.

For information about securing sites with SSL/TLS, refer to the section Securing Connections with SSL/TLS Certificates.

Web statistics.

This allows you to view website visit statistics presented in diagrams and charts.

For information about viewing website visit statistics, refer to the section Viewing Statistics.

Custom error documents.

This allows you to create custom HTML pages and configure a webserver to show them instead of typical error messages, such as 404 Not Found.

For information about setting up custom error documents, refer to the section Setting Up Custom Error Pages.

Support for programming and scripting languages, such as PHP, CGI, Perl, Python, Microsoft ASP, ASP.NET, SSI.

Dedicated IIS application pool.

This option provides isolation and improved stability for web applications working on sites.

Additional write/modify permissions.

This option allows web applications to use a file-based database (like Jet) located in the root of the httpdocs or httpsdocs folder.

Allow web users to use scripts.

This allows scripting at web pages available at URLs like http://example.com/~ /, where refers to a web user. Web users are individuals who do not need their own domain names. This service is popular with educational institutions that host non-commercial personal pages of their students and staff.

Allocated and Consumed Resources

If you are subscribed to a number of service plans at once, then you have several subscriptions. For each subscription, the following types of allocated resources are listed in Plesk at the Account section > Resources:

Disk space.

This is the total amount of disk space allocated to your account with a subscription. This amount includes all data related to your websites, email accounts, applications, backups, and log files.

Traffic.

This is the total amount of data in megabytes that can be transferred monthly from all your websites.

Domains.

This is the number of websites that can have separate second-level domain names, such as, for example, example.com.

For information about setting up websites, refer to the sections Set Up Your First Website and Adding Domains.

Subdomains.

This is the number of additional websites that can have third-level domain names, such as, for example, news.example.com.

For information about setting up subdomains, refer to the section Adding Subdomains.

Domain aliases.

This is the number of additional domain names that can be set up to point to one of your sites. For example, example.fr and example.de can both point to example.com.

For information about setting up domain aliases, refer to the section Adding Domain Aliases.

Mailboxes.

This is the number of mailboxes that can be created under all your websites.

For information about creating mailboxes, refer to the chapter Mail.

Mailbox size.

This is the amount of disk space that can be occupied by a mailbox.

Total mailboxes quota.

This is the total amount of disk space that can be used by all mailboxes under all your domains. This option is available only on Windows-based customer accounts.

Mailing lists.

This is the total number of mailing lists that can be set up under all your websites. Note that there are mailing lists and mail groups, which serve the same purpose, but are slightly different in functionality. Mailing lists support archiving and pre-moderation of messages, while mail groups can only be used for sending one message to a number of recipients at once.

For information about setting up and using mailing lists, refer to the section Using Mailing Lists.

Additional FTP accounts.

This is the number of FTP accounts that can be set up for accessing the subscription, in addition to the main FTP account that was created when your subscription was activated.

For information about setting up FTP accounts, refer to the sections Changing FTP Access Credentials and Adding FTP Accounts.

MySQL databases and MS SQL Server databases.

This is the maximum number of MySQL and Microsoft SQL Server databases respectively that can be created on the Plesk database servers and used by the subscription’s websites.

MySQL databases quota and MS SQL databases quota.

This is the maximum amount of disk space that MySQL and Microsoft SQL Server databases respectively can occupy on a subscription.

MS SQL database file size.

The maximum size of a Microsoft SQL Server database file. Note that if a database consists of more than one file, more disk space might be used than you specify here.

MS SQL database log file size.

The maximum size of a Microsoft SQL Server log file. Note that if a database has more than one log file, more disk space might be used than you specify here.

Java applications.

This is the number of Java applications packaged in WAR format that you can install on your sites.

Sites published with Presence Builder.

This is the number of sites that you can create and publish using Presence Builder if the Presence Builder option is included in your hosting package.

Web users.

This is the number of user accounts that you can create for hosting web pages for other users under your domains.

ODBC DSN connections.

This is the number of connections to external databases that you can create for web applications running on your customer account. This option is available only for Windows-based customer accounts.

Descripción:

Identity and Access Manager

The ABP Identity and Access Manager (IAM) enables you to manage access to Business Tenant services and resources securely. Using IAM, you can create and manage ABP users and groups, and use permissions to allow and deny their access to Tenant owned resources.

IAM is a feature of the Alliance Passport Service offered at no additional charge. You will be charged only for use of other ABS services consumed by your users or ABP Services consumed by your applications.

To get started using IAM you will need to have administrator access over a Business Tenant. If you have already registered a Business Tenant, go to the Alliance Business Studio and get started with these IAM Best Practices.

ABP IAM has a list of best practices to help Alliance ID Holders to manage access to Business Tenant resources.

  • Users – Create individual users.
  • Groups – Manage permissions with groups.
  • Permissions – Grant least privilege.
  • Auditing – Turn on ABS SecTrail.
  • Password – Configure a strong password policy.
  • MFA – Enable MFA for privileged users.
  • Roles – Use IAM roles for custom integrations.
  • Sharing – Use IAM roles to share access.
  • Rotate – Rotate security credentials regularly.
  • Conditions – Restrict privileged access further with conditions.
  • Rooting – Reduce or remove the use of overprivileged users.

Use cases

Fine-grained access control to ABP resources

IAM enables your users to control access to ABP service APIs and to specific resources. IAM also enables you to add specific conditions such as time of day to control how a user can use ABP, their originating IP address, whether they are using SSL, or whether they have authenticated with a multi-factor authentication device.

Multi-factor authentication for highly privileged users

Protect your ABP environment by using ABP MFA, a security feature available at no extra cost that augments user name and password credentials. MFA requires users to prove physical possession of a hardware MFA token or MFA-enabled mobile device by providing a valid MFA code.

Analyze access

IAM helps you analyze access across your ABP environment. Your security teams and administrators can quickly validate that your policies only provide the intended public and cross-account access to your resources. You can also easily identify and refine your policies to allow access to only the services being used. This helps you to better adhere to the principle of least privilege.

Integrate with your corporate directory

IAM can be used to grant your employees and applications federated access to the ABP Management Console and ABP service APIs, using your existing identity systems such as Microsoft Active Directory. You can use any identity management solution that supports SAML 2.0, or feel free to use one of our federation samples (ABP Console SSO or API federation).

How it works

IAM assists in creating roles and permissions ABP IAM allows you to:

  • Manage IAM users and their access – You can create users in IAM, assign them individual security credentials (in other words, access keys, passwords, and multi-factor authentication devices), or request temporary security credentials to provide users access to ABP services and resources. You can manage permissions in order to control which operations a user can perform.

  • Manage IAM roles and their permissions – You can create roles in IAM and manage permissions to control which operations can be performed by the entity, or ABP service, that assumes the role. You can also define which entity is allowed to assume the role. In addition, you can use service-linked roles to delegate permissions to ABP services that create and manage ABP resources on your behalf.

  • Manage federated users and their permissions – You can enable identity federation to allow existing identities (users, groups, and roles) in your enterprise to access the ABP Management Console, call ABP APIs, and access resources, without the need to create an IAM user for each identity. Use any identity management solution that supports SAML 2.0, or use one of our federation samples (ABP Console SSO or API federation).

Get started with ABP IAM

Step 1 - Sign up for an Alliance ID account

Step 2 - Explore and learn with simple tutorials by instantly get access to the ABS Free Tier.

Step 3 - Accelerate, build and expand your business while taking advantage of being a part of our global Alliance Network.

Managing the Billing Process

The Alliance Business Model contains records to store sales and billing information. Billing records establish a cascading flow designed to suit the business process of any given business around the world.

The Alliance Business Suite | Accounting Module contains several tools built to help customers to harness the power of the Alliance Business Model by adding several Platform API Endpoints and Studio Views to the Alliance Business Suite, enabling customers to:

  • Outline Billing Records using Logistics and Sales Data.
  • Relate Billing Records to Holders, Accounts, Contacts, and more.
  • Expose Billing Records into Web Portals.
  • Interoperate with ABS E-Commerce stores.
  • Connect several payment gateways.

Note: Deal Units belong to the Sales Scope and can be managed on the Sales Manager Module.

SalesPlusBilling.jpg

What Is a Ledger Account?

The accounting ledger contains a listing of all general accounts in the accounting system’s chart of accounts.

Here are the primary general ledger accounts:

  • Asset accounts
  • Liability accounts
  • Stockholders’ equity accounts
  • Revenue accounts
  • Expense accounts
  • Revenue and loss accounts

Transactions are recorded throughout the year by debiting and crediting accounts in the ledger. The transactions are caused by normal business activities such as billing customers or through adjusting entries.

The ledger account may be in the form of a written record if accounting is done by hand or in the form of electronic records when accounting software packages are used.

How to write to a Ledger?

The Alliance Business Suite Accounting Module uses the double-entry bookkeeping method. So writing to a ledger means recording transactions into it. Each transaction is recorded into at least two ledger accounts. The entries have debit as well as credit transactions and are posted in two columns.

The Alliance Business Suite Accounting Module exposes a general ledger to each business tenant in the system. This ledger employs the double-entry bookkeeping method, which means that each financial transaction affects at least two general ledger accounts and each entry has a debit and a credit transaction. Double-entry transactions are posted in two columns, with debit postings on the left and credit entries on the right, and the total of all debit and credit entries must balance before recording the transaction.

Ledgers break up the financial information from the journals into specific accounts such as Cash, Accounts Receivable, and Sales, on their own sheets. This allows you to see the details of all your transactions.

What’s the Difference Between a Journal and a Ledger?

The journal and ledger both play an important role in the accounting process. The business transactions are primarily recorded in the journal and thereafter posted into the ledger under respective heads. While many financial transactions are posted in both the journal and ledger, there are significant differences in the purpose and function of each of these accounting books.

MEANING

The financial transactions are summarized and recorded as per the double-entry system in a journal. It’s also known as the primary book of accounting or the book of original entry.

The ledger, on the other hand, is known as the principal book of accounting. It records the information from the journal in the “T” format. It is used to create the trial balance which is also the source of the financial statements such as the income statement and the balance sheet

RECORDING TRANSACTIONS

The process of recording transactions in a journal is called journalizing while the process of transferring the entries from the journal to the ledger is known as posting.

The transactions in a journal are recorded in chronological order making it easy to identify the transactions are associated with a given business day, week, or another billing period. By contrast, the arrangement of entries within a ledger has more to do with grouping like transactions together into specific accounts for purposes of assessing the data for internal financial and accounting purposes.

FORMAT

The format of a journal is simple. It includes the transaction date, particulars of the transaction, folio number, debit amount, and credit amount. There is no scope for balancing in a journal.

The format of a journal:

DateParticularsL.F.DebitCredit
Transaction dateAccount title and detailsLedger folio numberAmt.Amt.

The ledger uses the “T” format where the date, particulars, and amount are recorded on each side.

The format of a ledger:

DateParticularsFolio NumberAmountDateParticularsFolio NumberAmount
Transaction dateAccount nameAmt.Transaction dateAccount nameAmt.

Unlike a journal, some ledger accounts start with an opening balance that is the closing balance of the previous year. Also, in the end, the ledger amounts should be balanced.

Preparing a ledger is important as it serves as a master document for all your financial transactions. Since it reports revenue and expenses in real-time, it can help you stay on top of your spending. The general ledger also helps you compile a trial balance, spot unusual transactions, and aids in the creation of financial statements.

Contact Sight Module (CRM)

Welcome to the Alliance Business Suite | Contact Sight Module Documentation. These articles will enable you to work with the module to get the most out of your Alliance Business Suite instance.

At the very core of the Alliance Business Suite, a wide range of CMS capabilities have been built to give you the greatest extent of flexibility while supporting your business core cases to enable your organization to manage every relationship it has, to exponentially increase the value you deliver to your customers.

Types of Records

Types of records

Contact Records: In ABS ContactSight, most of the information service requests are typically managed in relation to an existing contact record. These contacts can represent both an Individual or an Organization (company or group of people) and they are also used by other modules, like accounting, sales, and marketing.

Contacts are the heart of the Alliance Business Suite. ABS ContactSight's customer management capabilities are designed to help you grow your business and make it easy to have a strong contact management strategy embedded in your operations to help increase your business income and accelerate productivity.

Although these are the typical uses of Individuals and Organizations, different deployments might use these record types differently. But they're both typically referred to as Contacts.

This common root between individuals and organizations allows you to set the related contact on any record, to either an individual or an organization contact record.

Contact Profile Records: Contact Profiles are records designed to isolate contact capabilities that could be used by other modules. For example, a Student Profile will allow a Contact to own course enrollments, grades, homework deliveries, completion certificates, and everything that's related to this type of profile. Likewise, Supplier Profiles will allow Contact Records to have work orders and purchase requests/invoices, and so on.

Welcome to the iCommerce Engine Documentation

Infinity Comex Engine builds on top of the proven Alliance Business Suite Retail capabilities to help businesses to deliver a comprehensive omnichannel solution that unifies back-office, in-store, call center, and digital experiences. Infinity Comex Engine enables you to build brand loyalty through a white-labeled store built to deliver personalized customer engagements, increase revenue, boost employee productivity, optimize operations to reduce costs, and drive supply chain efficiencies, ultimately delivering better business outcomes.

The Infinity Comex engine is constantly evolving to harness the entire power of the Alliance Business Model by extending through modular and fully customizable capabilities the Alliance Business Suite to deliver:

  • Everything you need to build and operate your eCommerce business.

The Alliance Business Suite and the infinity Comex engine are meant to be together! They work side-by-side to help businesses optimize their operations by cutting off inefficiencies and helping them to deliver spectacular omnichannel experiences. The Alliance Business Suite enables seamless content management, assets, promotions, inventory, and pricing across all channels.

  • Everything you need to protect your customers and your business.

The Alliance Business Platform's and Alliance Passport Services' security features and standards are deeply integrated into the Infinity Comex Engine. Authentication and Authorization flows are defined at a platform level by configuring (or extending) the APS Engine. Then, also at a platform level, security features like HTTPS enforcement, Encryption, HSTS, CORS, and others can be enabled, disabled, or configured through the Alliance Business Suite - Admin Portal. Also, EU General Data Protection Regulation (GDPR) support is enabled for both ABP and ICX Engines.

To learn more about Data Protection across the Alliance Business Suite, please visit this link.

  • Everything you need to streamline your logistics and operations.

The Infinity Comex Engine is built on top of the Logistics module of the Alliance Business Suite. This allows the engine to read and write data directly from your logistic operations platform. The Infinity Comex engine also connects to several modules like ABS Subscriptions, ABS Marketing, ABS Accounting, and ABS Partners to help your business to deliver Amazon Quality-like Experiences to your customers.

  • Everything you need to build your brand and expose your business online.

Besides the fact that Infinity Comex Stores are fully customizable/white-label Customer-Facing solutions (which means your customers won't even know we're there), hundreds of external integrations allow users to connect and configure their favorite channels and applications through standard authentication protocols exposed by third-party developers.

Carts

Carts are a core part of our application. Carts allow guests, users, and businesses to navigate and customize our offers for their specific needs and preferences through Cart Registrations.

Overview

Carts define the currency and localization for the entire interface. This means that it will control the display currency for things like offers pricing, CRM, and accounting suite records, and personalize our offers based on your country.

Keep in mind that currency exchange rates are only for display purposes and you will be able to select the base price for every "Price Input". This will allow us to make conversions based on current and historical exchange rates, depending on the record type.

Products in your cart.

Adding products from Infinity Comex to your cart is as easy as clicking a button, but that's not the end of the story. we have designed a simple, yet powerful engine to help you select from a set of available options per product for things like Shipping, warranty, assurance, returns and refund policies and more.

Services in your cart.

When you register a service to your cart, it will be linked to your account through a Service Cart Registration. Service cart registrations let you pick from a set of available options like Project Management Methodology, Frontend Stacks, Framework, Programming Language (Based on the selected Framework), Operating System, and more.

Cloud Resources in your cart.

Once you have successfully created your Alliance ID, you will automatically get access to your Tenant Cart. Use it to store products before your checkout process.

Guest Carts

Guest carts are carts provisioned based on your current IP address. Its lifespan is 24 hours and is aimed to help you navigate your platform even when you are not logged in.

How is it different from my Guest Cart from my Tenant Cart?

The main difference is that your Tenant Shopping Cart has a slot for your Account ID, while your guest cart contains a slot for your IP address.

Another difference is that guest carts are just for instant navigation for our offerings, but they are actually not suited to place an order through your guest cart.

Also, Andy, our support bot, is programmed to empty every guest cart on our database ant midnight every two days.

In order to prevent cart deletion, you can log in to your Alliance ID Account to use your Tenant Cart for pre-order adjustments. Tenant carts have a time span of 31 days.

Guest Cart timespan policy.

Your guest cart will be deleted every 48 hours, which means that products on your guest cart might need to be added to your cart again if an old cart has already been deleted.

Tenant Carts

Have you had a chance to answer the previous question?

Yes, after a few months we finally found the answer. Sadly, Mike is on vacation right now so I'm afraid we are not able to provide the answer at this point.

Registrations Timespan Policy

When you add a product, a service, or a managed cloud resource to your cart, it will create a Cart Registration. These registrations will be available for you to customize your order preferences and place orders or provisioning requests with just a click. Cart registrations for your Alliance ID Tenant Cart won't be deleted until the first day of each month.

Business Carts

Business Carts get provisioned when you create a business account. They are intended for you to place Product Orders, Service Orders, and Cloud Resource Provisioning Requests.

Please note that access to business services depends on your granted capabilities and you will only be able to access our marketplaces if you are registered as a business owner or administrator, an acquisition manager or an advisor for your currently selected business.

What is the purpose of Business Carts?

Business' carts are aimed to provide the same functionality as a Tenant or Guest cart, with the difference that every order made from this chart will be processed using it's attached business Tax ID. This allows business owners/administrators and acquisition managers to quickly place orders on behalf of their business,

Welcome to the Alliance Business Suite | Logistics Manager

Supply Chain Management is at the core of every business. By delivering tools to effectively manage Stock, Warehouses, Suppliers, and a wide range of Logistics-Related Records, we're enabling businesses to achieve efficient Supply Chain Management without the hustle.

Inventory Management

The Logistics Manager Module was designed to help businesses to conduct effective inventory management while increasing ROI by making it easier to get a holistic view of your products through comprehensive views and tools, and valuable insights to make sure you're ordering the right inventory, at the right time and in right amounts,

Warehousing Management

The key to an efficient and profitable business is total visibility into the inventory process from start to finish and management tools to help you maintain optimal stock levels year-round. An effective inventory management system helps you streamline all the moving parts of your warehouse: From recommending optimal stock levels all the way to keeping your supply chain organized and running smoothly.

Shipping Management

We are making it easier than ever before to sell physical products by offering integrations and extensibility capabilities to connect your favorite shipping carriers, showing live rates, or adding custom solutions.

Logistics API

Through the Logistics Module API, developers can create custom solutions that extend its capabilities. Our goal is to create secure CRUD RESTfull Endpoints for almost every possible Record Type on the Logistics section of the Alliance Business Model.

Working with Stock Items in the Alliance Business Suite | Logistics Module

At the most basic level, Stock items are goods that you manufacture or trade (sell and purchase). Stock Items are highly inter-related ABM Records, they can be added to Carts, Quotes, Orders, Invoices, Wishlists, and more, as well as related to one or more Categories, Tags, Brands, Price Lists, Suppliers, Warehouses, and more.

Stock Items Manager

Some organizations have the need to manage hundreds or even thousands of Stock Items. This process is usually boring and time-consuming. For this reason, we're constantly investing our efforts in building efficient, automatable tools to help customers infuse efficiency into their operations.

The Stock Items Manager is an Alliance Business Studio view designed to make managing stock items as fast and efficient as possible.

Infused with inline and on-page editing tools, customers can create and manage Stock Items and related records without the need for page reloads.

To access the Stock Items Manager View, head to the Studio endpoint on any Web Portal, and navigate to Modules > Logistics > Stock Items.

Creating Stock Items

Stock Items can be created from the Stock Items Manager View. To do so, clock on the "Quick Create" button. This will open a panel containing the Stock Item Management Form, which contains all the fields available for Stock Items on the Alliance Business Model.

At the very least, Stock Items require a Title as well as a Stock Keeping Unit ("SKU").

qp9IJQI6Gy.gif

Updating Stock Items

Stock Items can be filtered and updated either by using the Stock Item Management Form or the In-Line Editing capabilities built into the Stock Items Grid. You can execute any of those through the Action Buttons on every Stock Item Record displayed on the Stock Items Grid.

Updating Stock Items is as straightforward as creating them. In fact, if you use the Stock Item Management Form to update a Stock Item, you'll be using exactly the same form you've used to create it.

Stock Item Identifiers

Stock Items are identified, at the lowest level, by a Globally Unique Identifier ("Guid") generated by the Alliance Business Model. Nevertheless, the Stock Item Record contains several fields to help customers to correlate this "Guid" with their own standards.

FieldDescription
BarcodeUPN, EAN or ISBN Barcode
SKUStock Keeping unit represents the code for a distinct type of item for sale. It must be unique for each Business Tenant
ISBN(ISBN-10 or ISBN-13) International Standard Book Number (ISBN)
UPCUniversal Product Code consists of 12 numeric digits that are uniquely assigned to each trade item.
EANInternational Article Number (also known as European Article Number or EAN) consists of a thirteen-digit code.
ASINAmazon Standard Identification Number (ASIN) is a ten-digit alphanumeric code that identifies products on Amazon.
UNSPSCUnited Nations Standard Products and Services Code is a taxonomy of products and services for use in eCommerce. It is a four-level hierarchy coded as an eight-digit number, with an optional fifth level adding two more digits.
GTINGlobal Trade Item Number (GTIN) GTINs consists of eight, 12, 13, or 14 digits
MPNManufacturer Part Number. It is a unique number that is issued by manufacturers to identify individual products.
Supplier CodeSupplier Code represents the Primary Supplier Code used to correlate each Stock Item with the Primary Supplier Standard.

Filtering

The Stock Items Grid contains powerful filtering capabilities.

Barcoding

The Stock Items Manager contains Barcoding Capabilities, meaning you can generate and update barcodes for Stock Items and then filter them out using their barcode.

To create or update a barcode, use the Stock Item Management Form and click on the "Scan Barcode" button. This will ask you permission to use your device's camera to start scanning. Once a valid barcode is recognized, the system will automatically fill out the proper fields on the Stock Item Management Form.

Barcoding in the Logistics module enables other Modules such as Sales, Accounting, POS, and even custom modules to filter out Stock Items using either a desktop or a smartphone camera.

Bulk Actions

The Stock Items Management View allows customers to perform bulk actions on Stock Items, such as adding or removing pricing policies (discounts, surcharges, price adjustments), Taxes, Relations, and more.

To perform a bulk action, select the Stock Items you want to update by ticking the checkbox on the left side of each Stock Item. You can check and filter stock items without losing your current selection state. Then click on the "Bulk Actions" button.

A Modal Prompt will appear. Select the bulk action you want to perform, configure your action and click on the Execute Button.

Bulk actions are blazing fast (executed in the order of seconds for hundreds of records), but performing bulk actions on thousands of records can take a little while.

ABS | Content Portals

Through ABS Content Portals, customers can now create a powerful new type of experience: external-facing websites that allow users outside their organizations to sign in with a wide variety of identities, create and view data in the Alliance Business Model, or even browse content anonymously. The full capabilities of the ABS Razor Engine for Content Portals, previously offered only as a Module, are now available right out of the box in every Alliance Business Suite instance.

Content Portals can extend the ABS Modules such as sales, customer service, marketing, service companion, project center, and ABS custom apps to external and internal audiences such as customers, suppliers, partners, and employees.

Customers can use Content Portals to set up an interactive, web-based sales, services, support, and social engagement application platform to connect with the customers, engage with communities, manage multimedia content, and empower your channel partners. Your imagination is the limit!

These capabilities feature a revamped end-to-end experience for technical and non-technical staff to quickly create a website and customize it with pages, layout, and content. Designers can reuse page designs through templates, add forms and views to display key data from the Alliance Business Model and publish it to users with the click of a button.

Content Portal's Tenancy

Content Portals are always owned by one Business Tenant. Interactions from audiences of this portal will always resolve to the scope of the Portal's Owner Tenant. For example, if a customer tries to log in to a portal, Authorization will be attempted against the Business Tenant that owns that portal.

This is incredibly powerful as it allows customers to have more than one portal hosted into the same Alliance Business Suite instance, creating like so a MultiPortal Network.

Workflow Designer Module

Welcome to the Alliance Business Suite | Workflow Designer Module Documentation.

These articles will enable you to work with the module to get the most out of your Alliance Business Suite instance.

The Alliance Business Suite | Workflow Designer is a workflows manager that enables workflow execution in any Alliance Business Suite instance. Workflows, business processes, and enterprise orchestrations can be defined by using code or the visual workflow designer, to integrate your Alliance Business Suite and your data on the Alliance Business Model across cloud and on-premises systems.

Features

  • Create workflows using the Workflow Builder API.
  • Create & manage workflows visually using the Alliance Business Studio Dashboard SPA.
  • Design long-running workflows.
  • REST API Endpoints to manage and integrate with Elsa from external applications.
  • Create higher-level activities using the Composite Activity API.
  • Rich set of activities such as SetVariable, For, ForEach, ParallelForEach, Fork, Join, HttpEndpoint, SendHttpRequest, SendEmail, MessageReceived, and much more.
  • Create custom activities.
  • Workflow Expressions allow you to configure activity properties with expressions that are evaluated at runtime. Supported syntaxes are JavaScript and Liquid.

Why Workflow Designer?

One of the main goals of the Workflow Designer Module is to enable workflows in any Alliance Business Suite instance with minimum effort and maximum extensibility. This means that your Alliance Business Suite is workflow-capable right out of the box.

Azure Logic Apps vs ABS | Workflow Designer?

  • As powerful and as complete as Azure Logic Apps are, it's available only as a managed service in Azure. The Alliance Business Suite, on the other hand, allows you to host it not only on Azure but on any cloud provider that supports .NET Core. And of course, you can host it on-premises.

  • Although you can implement long-running workflows with Logic Apps, you would typically do so by splitting your workflow with multiple Logic Apps where one workflow invokes the other. This can make the logic flow a bit hard to follow. with ABS | Workflow Designer, you simply add triggers anywhere in the workflow, making it easier to have a complete view of your application logic. And if you want, you can still invoke other workflows from one workflow.

ABS | Workflow Designer vs. Windows Workflow Foundation?

I've always liked Windows Workflow Foundation, but unfortunately development appears to have halted. Here are a few reasons to prefer the Workflow Designer Module:

  • The Workflow Designer Module intrinsically supports triggering events that start new workflows and resume halted workflow instances in an easy-to-use manner. E.g. workflow host.TriggerWorkflowAsync("HttpRequestTrigger");" will start and resume all workflows that either start with or are halted on the HttpRequestTrigger.

  • The Workflow Designer Module has an In-Studio (web-based) workflow designer and a REST-based API to manage everything you can manage through the Web Workflow Designer.

ABS | Workflow Designer vs. Orchard Workflows?

Both Orchard and Orchard Core ship with a powerful workflows module, and both are awesome. In fact, the Workflow Designer Module was inspired by Orchard Core's Workflows module.

Although Workflow Designer uses a similar model, here are some differences:

  • The Workflow Designer Module is completely decoupled from the web and relies on the Alliance Business Platform, whereas Orchard Core Workflows is coupled not only to the Orchard Core Framework but to the web itself.
  • The Workflow Designer Module is being built without taking a dependency on any Orchard Core packages.

Working with the Alliance Business Suite Connector (Formerly ABS Self).

The Alliance Business Suite contains several extensibility capabilities, including the ability to host Node.JS Applications, Angular and React interoperability, Workflow Definitions, and a tremendously powerful content management system, but without a doubt, its most extensible feature is the Alliance Business Platform API.

At its most basic level, the ABS Connect Integration is an extension of the Alliance Business Platform API designed to enable customers to set up and manage their integrations without complications. For example, by using the ABS Connector, you could set up Zapier in minutes!

The ABS Connector gives you the greatest extend of control over the integration capabilities of the Alliance Business Platform, enabling customers to create custom integrations that run on their own framework of choosing but still transact data with any given Alliance Business Suite instance.

ABS Connector makes it easy than ever before to configure both internal and external applications to connect to the Alliance Business Platform using industry-standard protocols and it provides an intuitive set of Studio Views to manage them.

Managing Application Credentials

Managing WebHooks

Upload Stock Items from the to a Facebook Commerce Catalog With a Data Feed

The Facebook Integration for the Alliance Business Suite allows you to maintain a data feed to bulk upload Published Stock Items (Store Products) to your catalog using an automatically generated spreadsheet file.

You will need to configure the data feed on the Facebook Commerce Manager by a file once or set up a schedule to update your catalog automatically on a regular basis. Your catalog can hold multiple data feeds, but each data feed must contain different items.

Note: These steps are to set up a new data feed. Depending on the feed configuration, Facebook will automatically retrieve and update published items on a schedule.

Configure a new data feed to a catalog

To upload a new data feed to your catalog:

  1. Go to Commerce Manager and select your catalog.
  2. Open the Catalog tab and go to Data Sources.
  3. Select Data Feed.
  4. Select Scheduled Feed.
  5. Enter the URL on the following form https://your-portal-domain.com/api/v2/Integrations/Facebook/Stores/Catalog ( You can test the URL in your browser to make sure it downloads your file.)
  6. Choose an hourly, daily, or weekly upload schedule for your data feed. Select Next.
  7. Review your data feed’s settings. Select to make any changes. The default currency will only be used if prices in your file don't include a currency code.

Review your data feed’s settings. Select to make any changes. The default currency will only be used if prices in your file don't include a currency code.

Select Save Feed and Upload.

You've uploaded a new data feed from a URL. Your data feed now appears in Data Sources. You can select it to see an overview or manage its settings. To update your items in the future, edit your file and save it again on your hosting website. We'll fetch it from its URL to update your catalog at your scheduled times. You can edit your schedule or request a single upload sooner in your data feed's settings.

Mantaining a Google Merchant Center Data Feed through the Alliance Business Suite

The Alliance Business Suite's Google Merchant Integration can help you upload your product data in Google Merchant Center, it automatically exposes the data to be submitted to your feeds.

To configure this capability, you will need to set up any new feed, and once a feed is registered, it will be updated on a regular basis without having to register it again.

Although feeds are multi-currency, they display the base amount without shipment nor tax data, but we're currently working on multi-country feeds. 🥳

The data endpoint to point Google Merchant Center to can be constructed using the following route:

https://your-portal-domain.com/api/v2/Integrations/Google/Merchant/Catalog?CurrencyID=USD

Configuring survey opt-in

To set up the Google Merchant Survey Opt-In, all you need to do is to plug your Google Merchant ID into the integration configuration page.

To set up your Merchant ID, navigate to the Studio on any Web Portal, head to Integration > Google > Merchant, and place your Google Merchant ID on the form field, then save changes.

Authorization

[[TOC]]

Security Features

If you own an Alliance Business Suite-powered infrastructure or are considering using the Alliance Business Suite as your CMS/CRM/ERP (or any other), you may be concerned about potential Alliance Business Suite security issues. In this post, we’ll outline a few of the most common ABS security vulnerabilities, along with steps you can take to secure and protect your Alliance Business Suite instance.

At Fenix Alliance, we are committed to helping our customers meet their privacy and personal data requirements, as well as General Data Protection Regulation (GDPR). On this page, you will find information and resources to help you understand how the Alliance Business Suite supports protecting and enabling the privacy rights of individuals, and how we provide the information and tools that our customers need in order to define and support their specific obligations. You can read more about the Fenix Alliance commitment to security at the Fenix Alliance Trust Center.

Is the Alliance Business Suite Secure?

The answer to the question “is the Alliance Business Suite secure?” is it depends. The Alliance Business Suite itself is very secure as long as security best practices are followed.

Encryption at rest

All files sent to our applications are automatically encrypted with a 256-bit Advanced Encryption Standard (AES) cipher. SSE automatically encrypts data when writing it to Storage. When you read your files, our storage decrypts the data before returning it. This process incurs no additional charges and doesn't degrade performance. This feature can't be disabled.

Encryption in transit

We keep your data secure by enabling transport-level security between our applications and the client. We ALWAYS use HTTPS to secure communication over the public internet. When you call the REST APIs to access objects in storage accounts or our databases, we enforce the use of HTTPS by requiring secure transfer, and connections that use HTTP will be refused and redirected.

CORS support

We store several website asset types in Storage. These types include images and videos. To secure browser apps, we lock GET requests down to specific domains.

Our storage supports cross-domain access through cross-origin resource sharing (CORS). CORS uses HTTP headers so that a web application at one domain can access resources from a server at a different domain. By using CORS, our web apps ensure that tenants load only authorized content from our sources.

When you create a business application. you will be able to specify your domains in order for us to verify your domains and set CORS flags.

Role-based access control

To access data in an Alliance ID Tenant account, the client makes a request over HTTP or HTTPS. Every request to a secure resource must be authorized. The service ensures that the client has the permissions required to access the data.

Our applications support role-based access control (RBAC) for both resource management and data operations.

White papers, security reports, penetration tests, and risk assessment tools

To find detailed information about privacy and personal data for the Alliance Business Suite applications and services, visit the Alliance Business Suite Website. This site provides white papers, FAQs, security reports, penetration tests, risk assessment tools, and other resources. In particular, the site provides sales/technical guidance about how you should consider enhancing your data protection capabilities and how you might want to think about compliance as a process that has four stages: discover, manage, protect, and report.

Data subject requests

The General Data Protection Regulation (GDPR) is fundamentally about protecting and enabling the privacy rights of individuals. The General Data Protection Regulation (GDPR) took effect on 25 May 2018. For information about the challenges and opportunities that GDPR brings for organizations in the context of their business applications, whether there are any specific risks and measures to be taken in the GDPR context, and any potential impact on how business applications need to be used.

The GDPR grants individuals (or data subjects) certain rights in connection with the processing of their personal data. These rights include the right to correct inaccurate data, erase their data or restrict its processing, receive their data, and fulfill a request to transmit their data to another controller. The resources in this section will help Alliance Business Suite customers respond to data subject requests (DSRs).To find information about what the GDPR requires of controllers (you) and processors (Fenix Alliance) when you respond to DSRs, and how Fenix Alliance enables you to do so, see DSRs on the Service Trust Portal.

Compliance Manager

Alliance Business Suite - Compliance Manager is a modular cloud service solution that is designed to help organizations meet complex compliance obligations like the GDPR. It does real-time risk assessment that reflects your compliance posture against data protection regulations when you use Fenix Alliance's cloud services. It also provides recommended actions and step-by-step guidance.

HTTPS Enforcement in the Alliance Business Suite.

Although no API can prevent a client from sending sensitive data on the first request. the Alliance Business Platform (which serves as a middleware for incoming/outgoing requests, as a rule of thumb, is designed to make sure that:

  • HTTPS is required for all requests.
  • All HTTP requests are redirected to HTTPS.

Note: The Alliance Business platform should not listen on HTTP and will close the connection with status code 400 (Bad Request) and not serve the request.

Preventing Cross-Site Request Forgery (XSRF/CSRF) attacks.

Cross-site request forgery (also known as XSRF or CSRF) is an attack against web-hosted apps whereby a malicious web app can influence the interaction between a client browser and a web app that trusts that browser. These attacks are possible because web browsers send some types of authentication tokens automatically with every request to a website. This form of exploit is also known as a one-click attack or session riding because the attack takes advantage of the user's previously authenticated session.

An example of a CSRF attack:

A user signs into www.good-banking-site.com using forms authentication. The server authenticates the user and issues a response that includes an authentication cookie. The site is vulnerable to attack because it trusts any request that it receives with a valid authentication cookie.

The user visits a malicious site, www.bad-crook-site.com.

The malicious site, www.bad-crook-site.com, contains an HTML form similar to the following:

HTML

<h1>Congratulations! You're a Winner!</h1>
<form action="https://your-abs-instance.com/api/v2/insecure-banking-module/wallet" method="post">
    <input type="hidden" name="Transaction" value="withdraw">
    <input type="hidden" name="Amount" value="1000000">
    <input type="submit" value="Click to collect your prize!">
</form>

Notice that the form's action posts to your Alliance Business Suite instance, not to the malicious site. This is the "cross-site" part of CSRF.

The user selects the submit button. The browser makes the request and automatically includes the authentication cookie for the requested domain, your-abs-instance.com.

Without CSFR protection, the request runs on the your-abs-instance.com server with the user's cookie authentication context and can perform any action that an authenticated user is allowed to perform.

In addition to the scenario where the user selects the button to submit the form, the malicious site could:

  • Run a script that automatically submits the form.
  • Send the form submission as an AJAX request.
  • Hide the form using CSS.

These alternative scenarios don't require any action or input from the user other than initially visiting the malicious site.

Using HTTPS doesn't prevent a CSRF attacks. The malicious site can send an https://your-abs-instance.com/ request just as easily as it can send an insecure request.

Some attacks target endpoints that respond to GET requests, in which case an image tag can be used to perform the action. This form of attack is common on forum sites that permit images but block JavaScript. Apps that change state on GET requests, where variables or resources are altered, are vulnerable to malicious attacks. GET requests that change state are insecure. A best practice is to never change state on a GET request.

CSRF attacks are possible against web apps that use cookies for authentication because:

Browsers store cookies issued by a web app. Stored cookies include session cookies for authenticated users. Browsers send all of the cookies associated with a domain to the web app every request regardless of how the request to app was generated within the browser. However, CSRF attacks aren't limited to exploiting cookies. For example, Basic and Digest authentication are also vulnerable. After a user signs in with Basic or Digest authentication, the browser automatically sends the credentials until the session† ends.

†In this context, session refers to the client-side session during which the user is authenticated. It's unrelated to server-side sessions or ASP.NET Core Session Middleware.

Users can guard against CSRF vulnerabilities by taking precautions:

  • Sign off of web apps when finished using them.
  • Clear browser cookies periodically.
  • However, CSRF vulnerabilities are fundamentally a problem with the web app, not the end user.
<form action="/api/v2/secure-banking-module/wallet" method="post">
    @Html.AntiForgeryToken()
</form>

In each of the preceding cases, ASP.NET Core adds a hidden form field similar to the following:

<input name="__RequestVerificationToken" type="hidden" value="CfDJ8NrAkS ... s2-m9Yw">

Multiple apps hosted at one domain

Shared hosting environments are vulnerable to session hijacking, login CSRF, and other attacks.

Although portal1.my-abs-instance.net and portal2.my-abs-instance.net are different hosts, there's an implicit trust relationship between hosts under the *.my-abs-instance.net domain. This implicit trust relationship allows potentially untrusted hosts to affect each other's cookies (the same-origin policies that govern AJAX requests don't necessarily apply to HTTP cookies).

Attacks that exploit trusted cookies between portals hosted on the same Alliance Business Suite instance can be prevented by not sharing domains. When each instance is hosted on its own domain, there is no implicit cookie trust relationship to exploit.

Require antiforgery validation (Modules only)

ValidateAntiForgeryToken is an action filter that can be applied to individual actions, and controllers. Requests made to actions that have this filter applied are blocked unless the request includes a valid antiforgery token.

[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> RemoveLogin(RemoveLoginViewModel account)
{
    ManageMessageId? message = ManageMessageId.Error;
    var user = await GetCurrentUserAsync();

    if (user != null)
    {
        var result = 
            await _userManager.RemoveLoginAsync(
                user, account.LoginProvider, account.ProviderKey);

        if (result.Succeeded)
        {
            await _signInManager.SignInAsync(user, isPersistent: false);
            message = ManageMessageId.RemoveLoginSuccess;
        }
    }

    return RedirectToAction(nameof(ManageLogins), new { Message = message });
}

Refresh tokens after authentication

Using JavaScript with AntiForgeryTokens

When you use JavaScript into Dynamic Pages, Components, Templates or any other kind of WebContent, you will be able to access the AntyForgeryToken in several ways. Here's one of them:

function getCookie(cname) {
    var name = cname + "=";
    var decodedCookie = decodeURIComponent(document.cookie);
    var ca = decodedCookie.split(';');
    for (var i = 0; i < ca.length; i++) {
        var c = ca[i];
        while (c.charAt(0) === ' ') {
            c = c.substring(1);
        }
        if (c.indexOf(name) === 0) {
            return c.substring(name.length, c.length);
        }
    }
    return "";
}

var csrfToken = getCookie("CSRF-TOKEN");

var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function () {
    if (xhttp.readyState === XMLHttpRequest.DONE) {
        if (xhttp.status === 204) {
            alert('Todo item is created successfully.');
        } else {
            alert('There was an error processing the AJAX request.');
        }
    }
};
xhttp.open('POST', '/api/items', true);
xhttp.setRequestHeader("Content-type", "application/json");
xhttp.setRequestHeader("X-CSRF-TOKEN", csrfToken);
xhttp.send(JSON.stringify({ "name": "Learn C#" }));

Reporting a Vulnerability

Security issues and bugs should be reported privately to Fenix Alliance either by emailing support@fenix-alliance.com or via the portal at https://fenix-alliance.com. You should receive a response within 24 hours. If for some reason you do not, please follow up via email to ensure we received your original message.

Please do not open issues for anything you think might have a security implication.

Understanding the Alliance Business Suite dependency tree

The Alliance Business Suite is designed as a set of Application Layers dependant upon their service predecessor. Each Layer constitutes a Component for the Alliance Business Suite.

Components can be provisioned as Standalone Applications or used as stand-alone libraries. This means that it is possible to bring the Alliance Business Platform (FenixAlliance.ABP.*) into a new/existing application without having to include any dependency from the Alliance Business Studio (FenixAlliance.ABS.*). The same is true for the Alliance Business Model (FenixAlliance.ABM.*), which can be included without any reference to the Alliance Business Platform namespace (FenixAlliance.ABP.*).

Components rely on their Service Predecessor through abstractions, allowing customers to override almost every functionality through custom implementations.

DependencyTree.1.2.0.jpg

Note: Because other services on the Alliance Business Suite instance might rely on default implementations performing some work, it is imperative for customers who bring their own implementations to make sure their implementations stay compliant with each specification.

Understanding external dependencies

External dependencies required by the Alliance Business Suite are bounded to the Alliance Core Libraries Component, which means that they are available to every dependant Component due to .NET's Waterfall Dependency Resolution mechanism.

This means that Web Contents can make use of already present libraries such as Radzen Blazor, MudBlazor, Newtonsoft.Json, and many more. For a more detailed list of dependencies, please refer to the Core Dependencies.

Changelog

All notable changes to this project will be documented in this file.

The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.

[1.2.1] - 2021-07-12

Added

  • [ABS] View Rendering Cache
  • [ABS] AppDomain Assembly Scoping

[1.2] - 2021-07-12

Added

  • [ABS] Razor Templating Engine
  • [ABS] Custom Options Manager (API)
  • [ABS] Portal Option Manager (UI)
  • [ABS] Custom Portal Option Definitions
  • [ABS] Virtual SPA Support (Angular/React)
  • [ABS] Custom Service Endpoint Definitions

[1.1.9] - 2021-06-30

Added

  • [ABS] Theme Precompilation

[1.1.8] - 2021-06-18

Added

  • [ABS] Workflows Capability

[1.1.7] - 2021-06-06

Added

  • [ABS] Log Viewer
  • [ABS] Template Views
  • [ABS] View Components
  • [ABS] Blog Post Editor
  • [ABS] Drag 'n Drop Live Editor. (Preview)
  • [ABS] Support for Angular and React+Redux SPAs
  • [ABS] Initial Web Content (Editable Pages, Components & Templates)
  • [ABS] Internal Web Content (Sys locked Pages, Components & Templates)
  • [ABS] Frontend Admin Bar
  • [ABS] Invoice Outliner
  • [ABS] Invoice Manager
  • [ABM] Marketing Module Models
  • [ABS] Project Service Models
  • [ABM] LMS Service Models
  • [ABS] Add support for Bootstrap CSS
  • [ABS] Add support for Foundation CSS
  • [ABS] Adds support for Fabric JS and Fluent UI.
  • [ABS] Ensure non-existence of viral licensed libraries. (e.g GNU)
  • [ABS] Adds IViewBuffer, Resx, and Model Resolver to Templating Engine
  • [ABS] Adds Localization String Manager. Initial Localization Capabilities.

Changed

  • [ABS] Fix HTTP context access on IIS making the installation process fail.
  • [ABS] Fix HTTP context access on IIS when trying to create a new view.
  • [ABS] Fix HTTP context access on IIS when trying to edit a new view.
  • [ABS] Fix HTTP context access on IIS when trying to create a new post.
  • [ABS] Fix HTTP context access on IIS when trying to edit a new post.
  • [ABM] Fiscalization document Models
  • [ABM] Project Service document Models
  • [ABM] Pricing engine Models
  • [ABM] Workflow engine Models
  • [ABM] Web Content Records now share a single base class
  • [ABM] ItemPriceList is now a PriceListRecord.
  • [ABS] Fix error when referencing scripts into a Web Content being malformed by templating engine.
  • [ABS] Fix page tree navigation on the live editor.

[1.1.6] - 2021-04-21

Added

  • [ABS] View Precompilation
  • [ABS] Internal Plugin Support+
  • [ABS] Dynamic Portal Metadata
  • [ABS] Google Meta Tags Integration
  • [ABS] Google Analytics Integration
  • [ABS] Google Verification Code Integration
  • [ABS] Bing Verification Code Integration
  • [ABS] Pinterest Verification Code Integration
  • [ABS] Facebook Pixel Verification Code Integration
  • [ABS] ICX Taxonomies Creation Blazor Pages.
  • [ACL] Store Configuration Objects.
  • [APS] External Authentication Provider configuration pages.

Changed

  • [ABP] Fix error while previewing files on File System Explorer.
  • [ICX] Fix error where new users got a 500 when visiting the store.
  • [ICX] Update Swiper to the latest version.
  • [ABS] Monaco editor now lives inside the project instead of as a node module.
  • [ICX] ICX Static Files audit, bundling & minification.
  • [ICX] Fix UI error on cart record addition/deletion.
  • [APS] Fix Auth Error: when users do not belong to any tenant, they used to get an E500 on nested File Retrieval.
  • [ABM] Model Modification to support DB-stored precompiled views.

Removed

  • [ICX] Taxonomies Creation Controllers/Views.

[1.1.4.x] - 2021-04-13

Added

  • [ABS] Extension Updates Page
  • [ABS] Razor Templating Engine
  • [APS] Google Authentication
  • [APS] Facebook Authentication
  • [APS] Microsoft Authentication
  • [APS] Twitter Authentication
  • [APS] LinkedIn Authentication
  • [APS] Instagram Authentication
  • [APS] Github Authentication
  • [SEO] Zift 123 Analytics Script Integration
  • [SEO] Facebook Pixel Integration
  • [SEO] Facebook Chat Widget Integration
  • [SEO] Google Analytics integration
  • [SEO] Google Merchant Center integration
  • [SEO] Google Verification Code Integration
  • [SEO] Google Tag Manager Integration
  • [SEO] Bing Verification code integration
  • [SEO] Pinterest verification code integration
  • [SEO] Dynamic Structured Metadata
  • [UI] Adds Off-Canvas Cart Slider
  • [UI] Dynamic Top Bar content
  • [UI] Logo size customization options
  • [UI] Footer Dynamic Content
  • [UI] Footer/Header Dynamic styling

[1.1.3.x] - 2021-04-09

Added

  • [ACL] Radzen.Blazor is now a project dependency.
  • [ACL] RabbitMQ.Client is now a project dependency.
  • [ACL] Fluid.Core is now a project dependency.
  • [ACL] FluentValidation is now a project dependency.
  • [ACL] NuGet.Packaging is now a project dependency.
  • [ACL] FluentEmail.Core is now a project dependency.
  • [ACL] Flurl.Http is now a project dependency.
  • [ACL] Standard.Licensing is now a project dependency.
  • [ACL] NodaTime is now a project dependency.
  • [ACL] Serilog is now a project dependency.
  • [ACL] Autofac is now a project dependency.
  • [ACL] CsvHelper is now a project dependency.
  • [ACL] Dapper is now a project dependency.
  • [ACL] AngleSharp is now a project dependency.
  • [ACL] IdentityServer4 is now a project dependency.
  • [ACL] DotLiquid is now a project dependency.
  • [ACL] Emitter is now a project dependency.
  • [ACL] MediatR is now a project dependency.
  • [ACL] SixLabors.ImageSharp.Web is now a project dependency.
  • [ACL] RazorLight is now a project dependency.
  • [ACL] MassTransit is now a project dependency.
  • [ACL] ZXing.Net is now a project dependency.
  • [ACL] Z.EntityFramework.Plus.EFCore is now a project dependency.

Changed

  • [ABP] Fix error where plugin assembly paths always returned null (IPluginManager Implementation)

[1.1.2.x] - 2021-02-23

Added

  • Adds ABP Proxy
  • Missing ACL configuration Types
  • ABS Extensions Gallery
  • ABS Extensions Installer
  • ABS Web Installer
  • ABS Admin Portal
  • Dynamic Web Page/Post creation
  • Assembly Explorer
  • Roles and Permissions Explorer
  • Admin Dashboard Initials
  • Added support for SixLabors.ImageSharp.Web
  • Forex service data is now scraped by Fenix Alliance.
  • Data Services are not coded to replaceable interface implementation.
  • ABS.Hub project now contains everything we need to create a new ABS Instance.
  • Added support for IdentityServer4 as a replacement for Alliance Passport Services.
  • ACL.Licensing is now a part of the Alliance Business Suite.

Changed

  • Extracts interface for ACL configuration Types
  • ACS is now ABP.BotEngine
  • Plugin Manager is now loosely coupled to IPluginManager
  • Adds File Manager and FileSystem Service
  • Adds antivirus scanning extension for FileSystem Service (Windows Defender)
  • AccountHolder is now the standard identity class.
  • Fix minor UI glitches and broken links.
  • Fix several bugs on application startup and related extensions.

Removed

  • Data Helpers marked for deprecation.
  • ABS.Nucleus was deprecated and is no longer a part of this project.

[1.1.1.x] - 2021-01-20

Added

  • Adds ABP Proxy
  • Adds Infinity Comex Support
  • Missing ACL configuration Types

Changed

  • Fix Namespaces
  • ABS.Portal.Paperbits is now ABS.Portal.Editor
  • Adds ABS.Portal.UI Components (20+ View Components)

Removed

[1.1.0.x] - 2021-01-12

Added

  • Nuget Packages @1.1.0
  • Initial Portal Admin Blazor Application at route /admin.

Changed

  • Standardize namespace at v1.1.0

Removed

[1.0.0.x] - 2020-12-31

Added

  • Authentication / User Management / Profile Management
  • Authorization / Roles Management / Granular Permissions
  • Blazor Support
  • Cross-Platform Database Support ( MySQL, MSSQL )
  • Dynamic CSS/Lazy Loading
  • Dynamic Page Compositing Model / Site & Page Management
  • Dynamic Routing
  • Dynamic Swagger Specs
  • EF Core Migrations for Database Installation / Upgrade
  • Enabled for Infinity Comex (eCommerce Extension)
  • Event Logging / Audit Trail
  • Extensibility via Custom Modules
  • Extensibility via Custom Themes
  • Folder / File Management (Azure Storage, File System)
  • GraphQl API with Voyager, GraphiQl y GraphQl Playground
  • Headless API with Swagger Support
  • HealthCheck Rules with UI Support
  • i18n Enabled (Based on GeoAPI and Custom Settings)
  • Improved JavaScript reference support
  • In-App CLI (Studio Commander)
  • Infinity Comex Support (ABS eCommerce Engine)
  • JavaScript Lazy Loading
  • Modular Architecture
  • Multi-Currency Support
  • Multi-Portal ( Monolith & Micro-Service Distributed )
  • Multi-Tenant ( Shared Database & Isolated Database )
  • Notifications / Email Delivery
  • Notifications / SMTP Delivery
  • Progressive Web Application Support
  • Recycle Bin
  • REST API with Swagger Support
  • Scheduled Flows ( Background Processing )
  • Scheduled Jobs ( Background Processing )
  • Seamless Upgrade Experience
  • Slack integration (OAuth)
  • Support For Additional Authentication Providers (OAuth)

Contributing to the Alliance Business Suite and/or its documentation

Woohoo! You've decided to contribute? That's amazing! We want to make contributions to the Alliance Business Suite as easy and frictionless as we can. Contributing requires a GitHub account. If you don't have an account, follow the instructions for the GitHub account setup.

Then, you just need to create an Issue to report bugs, propose APIs, request features and tooling, propose designs and improvements.

All of these contributions will be filled as Issues on the Alliance Business Suite Documentation Repository and they adhere to the following Issue Management Policy.

Issue Management Policy

Because we want to create a world-class product, we spend most of our time coding, designing, and architecting a well-designed solution, so we have adopted the .NET's Issue Management Policy to help us manage incoming Issues. This is a brief summary of some of the policies we have in place and the justification for them.

Commenting on closed issues In general, we recommend you open a new issue if you have a bug, feature request, or question to discuss. If you find a closed issue that is related, open a new issue and link to the closed issue rather than posting on the closed issue. Closed issues don't appear in our triage process, so only the people who have been active on the original thread will be notified of your comment. A new issue will get more attention from the team.

In general, we don't mind getting duplicate issues. It's easier for us to close duplicate issues than to discuss multiple root causes on a single issue! We may close your issue as a duplicate if we determine it has the same root cause as another. Don't worry! It's not a waste of our time!

Needs Author Feedback

If a contributor reviews an issue and determines that more information is needed from the author, they will post a comment requesting that information and apply the Needs: Author Feedback label. This label indicates that the author needs to post a response in order for us to continue investigating the issue.

If the author does not post a response within 7 days, the issue will be automatically closed. If the author responds within 7 days after the issue is closed, the issue will be automatically re-opened. We recognize that you may not be able to respond immediately to our requests, we're happy to hear from you whenever you're able to provide the new information.

PR: pending author input

Similar to the Needs Author Feedback process above, PRs also require author input from time to time. When a member of our team asks for some follow-up changes from the author, we mark these PRs with pr: pending author input label. After doing so, we expect the author to respond within 14 days. If the author does not post a response or updates the PR within 14 days, the issue will be automatically closed. If the author responds within 7 days after the issue is closed, the issue will be automatically re-opened. We recognize that you may not be able to respond immediately to our requests, we're happy to hear from you whenever you're able to provide the new information.

Duplicate issues

If we determine that the issue is a duplicate of another, we will label it with the Resolution: Duplicate label. The issue will be automatically closed in 1 day of inactivity.

Answered questions

If we determine that the issue is a question and have posted an answer, we will label it with the Resolution: Answered label. The issue will be automatically closed in 1 day of inactivity.

Locking closed issues

After an issue has been closed and had no activity for 30 days it will be automatically locked as resolved. This is done in order to reduce confusion as to where to post new comments. If you are still encountering the problem reported in an issue, or have a related question or bug report, feel free to open a new issue and link to the original (now locked) issue!

Reporting a Vulnerability

Security issues and bugs should be reported privately to Fenix Alliance either by emailing support@fenix-alliance.com or via the portal at https://fenix-alliance.com. You should receive a response within 24 hours. If for some reason you do not, please follow up via email to ensure we received your original message.

Please do not open issues for anything you think might have a security implication.

Fenix Alliance's Community & Open Source Code of Conduct.

This code of conduct outlines our expectations for participants within the community, as well as steps to reporting unacceptable behavior. We are committed to providing a welcoming and inspiring community for all and expect our code of conduct to be honored. Anyone who violates this code of conduct may be banned from the community. Our open source community strives to:

  • Be friendly and patient.
  • Be welcoming: We strive to be a community that welcomes and supports people of all backgrounds and identities. This includes, but is not limited to members of any race, ethnicity, culture, national origin, colour, immigration status, social and economic class, educational level, sex, sexual orientation, gender identity and expression, age, size, family status, political belief, religion, and mental and physical ability.
  • Be considerate: Your work will be used by other people, and you in turn will depend on the work of others. Any decision you take will affect users and colleagues, and you should take those consequences into account when making decisions. Remember that we're a world-wide community, so you might not be communicating in someone else's primary language.
  • Be respectful: Not all of us will agree all the time, but disagreement is no excuse for poor behavior and poor manners. We might all experience some frustration now and then, but we cannot allow that frustration to turn into a personal attack. It’s important to remember that a community where people feel uncomfortable or threatened is not a productive one.
  • Be careful in the words that we choose: we are a community of professionals, and we conduct ourselves professionally. Be kind to others. Do not insult or put down other participants. Harassment and other exclusionary behavior aren't acceptable.
  • Try to understand why we disagree: Disagreements, both social and technical, happen all the time. It is important that we resolve disagreements and differing views constructively. Remember that we’re different. The strength of our community comes from its diversity, people from a wide range of backgrounds. Different people have different perspectives on issues. Being unable to understand why someone holds a viewpoint doesn’t mean that they’re wrong. Don’t forget that it is human to err and blaming each other doesn’t get us anywhere. Instead, focus on helping to resolve issues and learning from mistakes.

Definitions

Harassment includes, but is not limited to:

  • Offensive comments related to gender, gender identity and expression, sexual orientation, disability, mental illness, neuro(a)typicality, physical appearance, body size, race, age, regional discrimination, political or religious affiliation
  • Unwelcome comments regarding a person’s lifestyle choices and practices, including those related to food, health, parenting, drugs, and employment
  • Deliberate misgendering. This includes deadnaming or persistently using a pronoun that does not correctly reflect a person's gender identity. You must address people by the name they give you when not addressing them by their username or handle
  • Physical contact and simulated physical contact (eg, textual descriptions like “hug” or “backrub”) without consent or after a request to stop
  • Threats of violence, both physical and psychological
  • Incitement of violence towards any individual, including encouraging a person to commit suicide or to engage in self-harm
  • Deliberate intimidation
  • Stalking or following
  • Harassing photography or recording, including logging online activity for harassment purposes
  • Sustained disruption of discussion
  • Unwelcome sexual attention, including gratuitous or off-topic sexual images or behaviour
  • Pattern of inappropriate social contact, such as requesting/assuming inappropriate levels of intimacy with others
  • Continued one-on-one communication after requests to cease
  • Deliberate “outing” of any aspect of a person’s identity without their consent except as necessary to protect others from intentional abuse
  • Publication of non-harassing private communication

Our open source community prioritizes marginalized people’s safety over privileged people’s comfort. We will not act on complaints regarding:

  • ‘Reverse’ -isms, including ‘reverse racism,’ ‘reverse sexism,’ and ‘cisphobia’
  • Reasonable communication of boundaries, such as “leave me alone,” “go away,” or “I’m not discussing this with you”
  • Refusal to explain or debate social justice concepts
  • Communicating in a ‘tone’ you don’t find congenial
  • Criticizing racist, sexist, cissexist, or otherwise oppressive behavior or assumptions

Diversity Statement

We encourage everyone to participate and are committed to building a community for all. Although we will fail at times, we seek to treat everyone both as fairly and equally as possible. Whenever a participant has made a mistake, we expect them to take responsibility for it. If someone has been harmed or offended, it is our responsibility to listen carefully and respectfully, and do our best to right the wrong. Although this list cannot be exhaustive, we explicitly honor diversity in age, gender, gender identity or expression, culture, ethnicity, language, national origin, political beliefs, profession, race, religion, sexual orientation, socioeconomic status, and technical ability. We will not tolerate discrimination based on any of the protected characteristics above, including participants with disabilities.

Reporting Issues

If you experience or witness unacceptable behavior—or have any other concerns—please report it by contacting us via support@fenix-alliance.com. All reports will be handled with discretion. In your report please include:

  • Your contact information.
  • Names (real, nicknames, or pseudonyms) of any individuals involved. If there are additional witnesses, please include them as well. Your account of what occurred, and if you believe the incident is ongoing. If there is a publicly available record (e.g. a mailing list archive or a public IRC logger), please include a link.
  • Any additional information that may be helpful.

After filing a report, a representative will contact you personally, review the incident, follow up with any additional questions, and make a decision as to how to respond. If the person who is harassing you is part of the response team, they will recuse themselves from handling your incident. If the complaint originates from a member of the response team, it will be handled by a different member of the response team. We will respect confidentiality requests for the purpose of protecting victims of abuse.

Attribution & Acknowledgements

We all stand on the shoulders of giants across many open source communities. We'd like to thank the communities and projects that established code of conducts and diversity statements as our inspiration:

Third Party Notices

Third-party notices are provided solely for your information and include the original copyright and license which Fenix Alliance received with the third-party software. While Fenix Alliance is not the original author of the third-party materials, Fenix Alliance licenses these third-party materials to you under the terms set forth in the EULA agreement, except that components licensed under open source licenses requiring that such components remain under their original licenses, such as the GNU General Public License (GPL) or the GNU Lesser General Public License (LGPL), are being made available to you by Fenix Alliance under their original licensing terms. Fenix Alliance reserves all rights not expressly granted herein, whether by implication, estoppel, or otherwise.

IdLicenseUrl
AspNetCore.HealthChecks.SqlServerhttps://licenses.nuget.org/Apache-2.0
AspNetCore.HealthChecks.UIhttps://licenses.nuget.org/Apache-2.0
AspNetCore.HealthChecks.UI.Clienthttps://licenses.nuget.org/Apache-2.0
AspNetCore.HealthChecks.UI.InMemory.Storagehttps://licenses.nuget.org/Apache-2.0
AspNetCoreRateLimit
Autofachttps://licenses.nuget.org/MIT
Autofac.Extensions.DependencyInjectionhttps://licenses.nuget.org/MIT
AutoMapperhttps://licenses.nuget.org/MIT
AutoMapper.Collection.EntityFrameworkCorehttps://licenses.nuget.org/MIT
AutoMapper.Extensions.Microsoft.DependencyInjectionhttps://licenses.nuget.org/MIT
Azure.Storage.Blobshttps://licenses.nuget.org/MIT
ByteSize
coverlet.collectorhttps://licenses.nuget.org/MIT
Dapperhttps://licenses.nuget.org/Apache-2.0
FluentEmail.Corehttps://licenses.nuget.org/MIT
FluentEmail.Smtphttps://licenses.nuget.org/MIT
FluentValidationhttps://licenses.nuget.org/Apache-2.0
FluentValidation.AspNetCorehttps://licenses.nuget.org/Apache-2.0
GraphQLhttps://licenses.nuget.org/MIT
GraphQL.Server.Transports.AspNetCorehttps://licenses.nuget.org/MIT
GraphQL.Server.Transports.WebSocketshttps://licenses.nuget.org/MIT
GraphQL.Server.Ui.GraphiQLhttps://licenses.nuget.org/MIT
GraphQL.Server.Ui.Playgroundhttps://licenses.nuget.org/MIT
GraphQL.Server.Ui.Voyagerhttps://licenses.nuget.org/MIT
Humanizerhttps://licenses.nuget.org/MIT
IdentityServer4https://licenses.nuget.org/Apache-2.0
JWT
MailKithttps://licenses.nuget.org/MIT
MassTransithttps://licenses.nuget.org/Apache-2.0
MediatRhttps://licenses.nuget.org/Apache-2.0
MediatR.Extensions.Microsoft.DependencyInjectionhttps://licenses.nuget.org/Apache-2.0
Microsoft.ApplicationInsights.AspNetCorehttps://licenses.nuget.org/MIT
Microsoft.AspNet.WebApi.Clienthttp://www.microsoft.com/web/webpi/eula/net_library_eula_ENU.htm
Microsoft.AspNetCore.Authentication
Microsoft.AspNetCore.Authentication.Abstractions
Microsoft.AspNetCore.Authentication.AzureAD.UIhttps://licenses.nuget.org/Apache-2.0
Microsoft.AspNetCore.Authentication.AzureADB2C.UIhttps://licenses.nuget.org/Apache-2.0
Microsoft.AspNetCore.Authentication.JwtBearerhttps://licenses.nuget.org/Apache-2.0
Microsoft.AspNetCore.Authentication.OpenIdConnecthttps://licenses.nuget.org/Apache-2.0
Microsoft.AspNetCore.Blazorhttps://raw.githubusercontent.com/aspnet/Home/2.0.0/LICENSE.txt
Microsoft.AspNetCore.Componentshttps://licenses.nuget.org/Apache-2.0
Microsoft.AspNetCore.Components.Webhttps://licenses.nuget.org/Apache-2.0
Microsoft.AspNetCore.DataProtectionhttps://licenses.nuget.org/Apache-2.0
Microsoft.AspNetCore.Diagnostics.EntityFrameworkCorehttps://licenses.nuget.org/Apache-2.0
Microsoft.AspNetCore.Hostinghttps://raw.githubusercontent.com/aspnet/AspNetCore/2.0.0/LICENSE.txt
Microsoft.AspNetCore.Hosting.Server.Abstractions
Microsoft.AspNetCore.Httphttps://raw.githubusercontent.com/aspnet/AspNetCore/2.0.0/LICENSE.txt
Microsoft.AspNetCore.Http.Abstractions
Microsoft.AspNetCore.Http.Featureshttps://licenses.nuget.org/Apache-2.0
Microsoft.AspNetCore.Identity.EntityFrameworkCorehttps://licenses.nuget.org/Apache-2.0
Microsoft.AspNetCore.Identity.UIhttps://licenses.nuget.org/Apache-2.0
Microsoft.AspNetCore.Mvc
Microsoft.AspNetCore.Mvc.Corehttps://raw.githubusercontent.com/aspnet/AspNetCore/2.0.0/LICENSE.txt
Microsoft.AspNetCore.Mvc.NewtonsoftJsonhttps://licenses.nuget.org/Apache-2.0
Microsoft.AspNetCore.Mvc.WebApiCompatShimhttps://raw.githubusercontent.com/aspnet/AspNetCore/2.0.0/LICENSE.txt
Microsoft.AspNetCore.SignalR.Core
Microsoft.Azure.KeyVault.Corehttps://licenses.nuget.org/MIT
Microsoft.Bot.Builder.AI.Luishttps://github.com/Microsoft/BotBuilder/blob/master/LICENSE
Microsoft.Bot.Builder.Dialogshttps://github.com/Microsoft/BotBuilder/blob/master/LICENSE
Microsoft.Bot.Builder.integration.AspNet.Corehttps://github.com/Microsoft/BotBuilder/blob/master/LICENSE
Microsoft.CSharphttps://licenses.nuget.org/MIT
Microsoft.EntityFrameworkCorehttps://licenses.nuget.org/Apache-2.0
Microsoft.EntityFrameworkCore.Designhttps://licenses.nuget.org/Apache-2.0
Microsoft.EntityFrameworkCore.Proxieshttps://licenses.nuget.org/Apache-2.0
Microsoft.EntityFrameworkCore.Relationalhttps://licenses.nuget.org/Apache-2.0
Microsoft.EntityFrameworkCore.SqlServerhttps://licenses.nuget.org/Apache-2.0
Microsoft.EntityFrameworkCore.Toolshttps://licenses.nuget.org/Apache-2.0
Microsoft.Extensions.Caching.Abstractionshttps://licenses.nuget.org/MIT
Microsoft.Extensions.Caching.Memoryhttps://licenses.nuget.org/MIT
Microsoft.Extensions.Caching.SqlServerhttps://licenses.nuget.org/MIT
Microsoft.Extensions.Configuration.Abstractionshttps://licenses.nuget.org/MIT
Microsoft.Extensions.DependencyInjectionhttps://licenses.nuget.org/MIT
Microsoft.Extensions.DependencyInjection.Abstractionshttps://licenses.nuget.org/MIT
Microsoft.Extensions.Diagnostics.HealthChecks.Abstractionshttps://licenses.nuget.org/Apache-2.0
Microsoft.Extensions.Diagnostics.HealthChecks.EntityFrameworkCorehttps://licenses.nuget.org/Apache-2.0
Microsoft.Extensions.Hostinghttps://licenses.nuget.org/MIT
Microsoft.Extensions.Hosting.Abstractionshttps://licenses.nuget.org/MIT
Microsoft.Extensions.Httphttps://licenses.nuget.org/MIT
Microsoft.Extensions.Localizationhttps://licenses.nuget.org/Apache-2.0
Microsoft.Extensions.Localization.Abstractionshttps://licenses.nuget.org/Apache-2.0
Microsoft.Extensions.Logginghttps://licenses.nuget.org/MIT
Microsoft.Extensions.Logging.Abstractionshttps://licenses.nuget.org/MIT
Microsoft.Extensions.Logging.Consolehttps://licenses.nuget.org/MIT
Microsoft.Extensions.Logging.Debughttps://licenses.nuget.org/MIT
Microsoft.Extensions.Primitiveshttps://licenses.nuget.org/MIT
Microsoft.Graphhttps://aka.ms/deprecateLicenseUrl
Microsoft.Identity.Clienthttps://licenses.nuget.org/MIT
Microsoft.IdentityModel.Tokenshttps://licenses.nuget.org/MIT
Microsoft.NET.Test.Sdkhttp://www.microsoft.com/web/webpi/eula/net_library_eula_enu.htm
Microsoft.OpenApihttps://raw.githubusercontent.com/Microsoft/OpenAPI.NET/master/LICENSE
Microsoft.Rest.ClientRuntime.Azure.Authenticationhttps://raw.githubusercontent.com/Microsoft/dotnet/master/LICENSE
Microsoft.TestPlatformhttps://www.visualstudio.com/microsoft-visual-studio-test-platform
Microsoft.VisualStudio.Web.BrowserLink
MongoDB.Bsonhttps://aka.ms/deprecateLicenseUrl
MongoDB.Driverhttps://aka.ms/deprecateLicenseUrl
MSTest.TestAdapterhttps://aka.ms/deprecateLicenseUrl
MSTest.TestFrameworkhttps://aka.ms/deprecateLicenseUrl
Newtonsoft.Jsonhttps://licenses.nuget.org/MIT
NodaTimehttps://licenses.nuget.org/Apache-2.0
NodaTime.Serialization.JsonNethttps://licenses.nuget.org/Apache-2.0
NUnit
NUnit3TestAdapterhttps://aka.ms/deprecateLicenseUrl
Pollyhttps://licenses.nuget.org/BSD-3-Clause
Polly.Caching.Memoryhttps://licenses.nuget.org/BSD-3-Clause
Pomelo.EntityFrameworkCore.MySqlhttps://licenses.nuget.org/MIT
reCAPTCHA.AspNetCorehttps://aka.ms/deprecateLicenseUrl
Sendgridhttps://licenses.nuget.org/MIT
Seq.Extensions.Logginghttps://licenses.nuget.org/Apache-2.0
Seriloghttps://licenses.nuget.org/Apache-2.0
Serilog.AspNetCorehttps://licenses.nuget.org/Apache-2.0
Serilog.Enrichers.Environmenthttp://www.apache.org/licenses/LICENSE-2.0
Serilog.Enrichers.Processhttp://www.apache.org/licenses/LICENSE-2.0
Serilog.Enrichers.Threadhttp://www.apache.org/licenses/LICENSE-2.0
Serilog.Settings.Configurationhttps://licenses.nuget.org/Apache-2.0
Serilog.Sinks.AzureBlobStoragehttps://aka.ms/deprecateLicenseUrl
StackifyMiddleware
Swashbuckle.AspNetCore.Swaggerhttps://licenses.nuget.org/MIT
Swashbuckle.AspNetCore.SwaggerGenhttps://licenses.nuget.org/MIT
Swashbuckle.AspNetCore.SwaggerUIhttps://licenses.nuget.org/MIT
System.ComponentModel.Annotationshttps://licenses.nuget.org/MIT
System.IdentityModel.Tokens.Jwthttps://licenses.nuget.org/MIT
WindowsAzure.Storagehttps://github.com/Azure/azure-storage-net/blob/master/LICENSE.txt
xunithttps://raw.githubusercontent.com/xunit/xunit/master/license.txt
xunit.runner.visualstudiohttps://licenses.nuget.org/MIT

About licensing

Our Community Edition was released to help you make your life easier while increasing your odds for success through the right tools and support required for your path for digitalization.

The Community Edition License is not a demo license. You’ll get access to the entire ABS. Either if you are an individual or an organization.

In a nutshell, You’ll only pay for core licensing fees if you use the ABS on behalf of an Enterprise, who’s an organization and its affiliates who collectively have either (a) more than 250 PCs or users or (b) more than one million U.S. dollars (or the equivalent in other currencies) in annual revenues.

Logo and Trademark

The brand name Alliance Business Suite and its logos are trademarks of Fenix Alliance S.A.S in Colombia and Fenix Alliance Inc in other countries ("Fenix Alliance").

Fenix Alliance owns and oversees the trademarks for the ABS name and logos. We have developed this trademark usage policy with the following goals in mind:

  • We’d like to make it easy for anyone to use the ABS name or logo for community-oriented efforts that help spread and improve ABS.
  • We’d like to make it clear how ABS-related businesses and projects can (and cannot) use the ABS name and logo.
  • We’d like to make it hard for anyone to use the ABS name and logo to unfairly profit from, trick, or confuse people who are looking for official ABS resources.

Licensing and Contributions

Your access to and use of the Alliance Business Suite's source code is governed by the Fenix Alliance's End User License Agreement "EULA". If you don't agree to those terms, as amended from time to time, you are not permitted to access or use the Alliance Business Suite.

We welcome any contributions to the Alliance Business Suite development through pull requests on GitHub. Most of our active development is in the develop branch, so we prefer to take pull requests there (particularly for new features). We try to make sure that all new code adheres to the Fenix Alliance coding standards. All contributions are governed by the terms of the EULA.

A note about your account and the privacy of your information.

The Alliance Passport Services engine is built on top of a highly compliant service to keep your identity private. This engine supports Facebook, Microsoft Accounts, Google+, LinkedIn, and many other identity providers, but you can also integrate your own.

We think that it's also worth pointing out that we DO NOT store any identity information into our databases; instead, that data is always encrypted and sent to the same systems that governments and enterprises worldwide are using to keep your data safe, and then we access that data by using industry-standard protocols so that you can rest assured that your sensitive information is protected through various security controls in addition to multi-factor authentication.

To learn more about our privacy policy, please visit: https://fenixalliance.com.co/legal/policies/privacypolicy