The file structure which is used in C#Bot applications
This article provides a summary of the client-side, server-side, and test target architecture, and briefly explains the organization, importance and usage of the key concepts for each framework.
Language + Framework
C#Bot uses an ASP.NET Core server-side framework which is a cross platform, open-source framework for building web applications. The testing target is also written in C#, and uses both xUnit and Specflow 3. C#Bot also uses React, a javascript library for developing client-side user interfaces.
Server-Side Directory Structure
src
├───Controllers API controllers to connect to the client-side
│ └───Entities
├───Exceptions Common exceptions that are used
├───Graphql All internal GraphQL functions
│ ├───Fields
│ ├───Helpers
│ └───Types
├───Helpers Helper classes
├───Migrations Database migration scripts
├───Models Entities as defined in the entity model
├───Properties Server launch properties
├───Security Rules defined in the security model
│ └───Acl
├───Services Services to be used in DI
│ ├───CertificateProvider Providers for fetching pfx certs
│ └───Scheduling Services for scheduled tasks
│ └───Tasks
└───Utility Utility classes, often helpers for the request pipeline
Controllers
Controllers are the HTTP/HTTPS endpoints for the application. They reside in the Controllers
directory.
A controller will typically follow this structure:
/// <summary>
/// Gets the logged in user
/// </summary>
/// <returns>The current logged in user</returns>
[HttpGet]
[HttpPost]
[Produces("application/json")]
[Route("me")]
[Authorize]
public async Task<UserResult> Get()
{
var user = await _userService.GetUser(User);
return user;
}
The [HttpGet]
and [HttpPost]
attributes specify that this endpoint will take requests from both GET
and POST
HTTP requests.
The [Produces("application/json")]
attribute specifies that any data returned by this endpoint will be serialized into JSON before returning to the client.
The [Route("me")]
attribute specifies that the endpoint is located at /me
in the URL. Please note that this is relative to the URL of the controller, so if the controller was specified to exist at /account
, the endpoint would be at /account/me
.
The [Authorize]
attribute requires the endpoint to have an authorized user, with authorization being enforced by the ‘default authorization policy’ found in Startup.cs
. By default, users are authenticated against either a Bearer
or Cookie
authentication scheme.
Server-Side Models
Server-Side models are defined as C# classes inside of the Models
directory. Each model is a plain C# class with all of the entities attributes, which are defined in the entity model. In addition, there is also a property called Acls
which implements security rules which are defined by the security model. These classes are coupled with both a configuration and a type file. The configuration file configures the entity in the database, whereas the type file defines type mappings for GraphQL.
GraphQL
The Graphql
folder contains the GraphQL queries, mutations and any helpers required to execute the various GraphQL functions. For each entity defined in the entity model there are functions created to provide the full CRUD functionality.
Security
The security folder contains the rules defined in the security model and helper classes associated with these security rules. It is important to note that the ACL
folder contains classes which can be altered to contain custom security logic.
Services
This folder contains the services added to the server-side via dependency injection. These services make the bulk of the application logic in a C#Bot project.
Client-Side Directory Structure
src
├───Assets Static assets that are needed in React (eg. images)
├───Models
│ ├───Entities The models that are defined in the entity model
│ └───Security The rules that are defined in the security model
│ └───Acl
├───scss
│ ├───abstracts Abstract styles (eg. colour variables)
│ ├───components Styles for individual components
│ ├───elements Styles for individual elements
│ └───pages Styles for specific pages in the application
├───Services Any services that are required in the application
├───Util A collection of utility functions
├───Validators Client-Side validators for validating models against
└───Views
├───Components All the components that are used by the client-side
├───Pages Pages that are placed on the UI model
│ └───Admin Admin pages for the backend views
└───Tiles Tiles that are placed on the UI model
Views
When writing a custom feature inside of a ReactBot view protected region, the first place to look at will be the src/Views/Pages
directory. Any pages placed on the UI model will be output here, with routing configured to render the page.
In ReactBot, all React components are class-based components by convention. This allows cleaner integration with MobX using the decorator syntax. However, there is no restriction on this and components can be function-based components if desired.
It is important when writing pages, or any other custom UI elements, that components are declared as MobX Observers. If this is not done, then there can be issues with elements not re-rendering on state changes.
Models
The client-side models are the javascript versions of the entities which were defined in the entity diagram. These contain observable attributes identical to those in the entity diagram. There are a series of helper methods on these models for fetching and persisting data to and from the server-side via the GraphQL API.
Test Target Directory Structure
testtarget
├───Selenium Includes the entirety of the selenium testing target
│ ├───Factories Selenium Based factories
│ ├───PageObjects Includes all page object models
│ │ ├───CRUDPageObject
│ │ │ └───PageDetails
│ │ ├───LoginPageObject
│ │ ├───LogoutPageObject
│ ├───Setup Startup configuration for Selenium tests
│ ├───Steps
│ │ ├───BotWritten Includes any bot written step definitions
│ ├───Tests
│ │ ├───BotWritten Includes any bot written tests
│ │ │ ├───Admin
│ │ │ ├───BulkOptions
│ │ │ ├───Checkbox
│ │ │ ├───Crud
│ │ │ │ ├───CreateTests
│ │ │ │ └───DeleteTests
│ │ │ ├───Login
│ │ │ ├───Navigation
│ │ │ ├───Pagination
│ │ │ ├───Search
│ │ │ ├───UnauthorizedLoginRedirect
│ │ │ └───Validator
│ └───Utils Selenium Utils
└───Serverside Includes the server-side API and unit tests
├───EntityObjects
│ ├───BaseChoice Includes all base choice invalid/valid helper methods
│ └───Models Includes entities for the test target
├───Properties
├───Settings
├───Setup Startup methods for server-side tests
├───Tests
│ └───botwritten Bot written server-side tests
└───Utils Helper methods for server-side tests
Selenium Test Target
The Selenium test target is composed entirely of Selenium tests, helper methods and page object models of the applications client-side.
Server-Side Test Target
The server-side test target includes all of the API and unit tests coupled with the C#Bot application. Any resources which are shared between the testing targets are included in this project. This includes BaseChoice, entity models, test configuration and several helper methods for creating and manipulating data.
Setup and Running
Build
In order to produce a production build of the application, first you must open a terminal in the serverside/src
directory of the application and run dotnet publish -c Release
.
This will create a release build of the server and client applications, and bundle them together. The output of the build is stored in serverside/src/bin/Release/netcoreapp2.2/publish
, which can be then deployed on any server.
It is important to note that even though there is a file called Properties/launchSettings.json
it will not configure the release build of the application, it is only used for configuration of IDE’s. When deploying a production build, any server settings must be configured using the specific tools provided by the web server of choice (eg. web.config for IIS or nginx.config NGINX).