In the Getting Started document, a new sample project is created named "Acme.PhoneBook". This document is a guide while developing your project. You should definitely read this document before starting your custom development. Since ASP.NET Zero is built on ASP.NET Boilerplate application framework, this document repeatedly refers ASP.NET Boilerplate's documentation.
Before reading this document, you should run the application and explore the user interface. This will help you to have a better understanding of concepts defined here.
The following tools are needed in order to use the ASP.NET Zero solution:
When you create and download your project, there will be a solution structure as shown below:
There are seven projects in the solution:
ASP.NET Zero solution contains four applications:
Thus, the back-end application is built in two different architectures (SPA and MPA). You can choose the one you are most comfortable with. If you just want to build a SPA, you can safely remove MPA files from your project, or vice versa.
Multi-tenancy is used to build SaaS (Software as a Service) applications easily. Wtih this technique, we can deploy single application to serve to multiple customers. Each Tenant will have it's own roles, users and settings.
All of the ASP.NET Zero's code-base is developed to be multi-tenant. But, it can be disabled with a single line of configuration if you are developing single-tenant application. If you disable it, all multi-tenancy stuff will be hidden and not available. If multi-tenancy is disabled, there will be a single tenant named Default.
There are two types of perspective in multi-tenant applications:
ASP.NET Zero uses ABP's (ASP.NET Boilerplate) data filters. Therefore it automatically filters tenant data if you properly use filter interfaces. Read multi-tenant documentation if you are building multi-tenant applications.
web.config file contains a setting, named "WebSiteRootAddress", which stores root URL of the web application:
<add key="WebSiteRootAddress" value="http://localhost:6240/" />
It's used to calculate some URLs in the application. So, you need to change this on deployment. For multi-tenant applications, this URL can contain dynamic tenancy name. In that case, put {TENANCY_NAME} instead of tenancy name like:
<add key="WebSiteRootAddress" value="http://{TENANCY_NAME}.mydomain.com/" />
Thus, ASP.NET Zero can automatically detect current tenant from URLs. If you configure it as above, you should also redirect all subdomains to your application. To do that;
There may be other ways of doing it but this is the simplest.
ASP.NET Zero contains front-end pages that can be a starting point for your public web site or a landing page for the application. When you first run the project, you will see the Home Page as shown below:
There are two pages here: Home Page and About. Content of these pages initially consists of placeholders for demo purposes that you should change. You can completely remove that content and build your page based on your needs. Also, you should change the logo with your Company's logo, of course.
See metronic front-end theme to review the myriad options and components available as part of the theme - they are an extensive resource that will enable you to more quickly build a richer web site.
Menus are defined in FrontEndNavigationProvider class. When you add a new menu item here, it will be automatically shown in the menu. There is a Login link at the top right corner. This link takes us to the Login page for the backend application.
Layout of front-end pages is located in the Views/Layout folder of the .Web project:
_Layout is the main layout file that includes scripts and styles. Language flags and the menu is rendered in _Header file. _PreFooter is not used but you can add it to the _Layout if you want.
When you click the "New tenant" link in the front end application, you can sign up to become a new tenant:
Here, you can create a new tenant. TenantRegistrationController is used to register a new tenant. Tenant registration can be enabled/disabled and settings can be changed in the settings page of the backend application.
AccountController provides login, register, forgot password and email activation pages.
Account management pages have a seperate _Layout view under Views/Account folder:
Main view for the AccountController is the Login page:
The first input is tenancy name which is shown only in a multi-tenant application and if "subdomain tenancy name detection" is not possible (See host settings section). There is a single tenant named Default in the initial database (see Entity framework section for initial seed data). Leave tenancy name input as blank to login as host.
You can use admin user name and 123qwe password when you first run the application. At first login, you should change admin password since 123qwe is not very secure:
After changing password you will be redirected to the Angular application.
ASP.NET Zero supports social media logins. To enable it, you should change the following settings in the web.config file.
<add key="ExternalAuth.Facebook.IsEnabled" value="false" />
<add key="ExternalAuth.Facebook.AppId" value="" />
<add key="ExternalAuth.Facebook.AppSecret" value="" />
<add key="ExternalAuth.Twitter.IsEnabled" value="false" />
<add key="ExternalAuth.Twitter.ConsumerKey" value="" />
<add key="ExternalAuth.Twitter.ConsumerSecret" value="" />
<add key="ExternalAuth.Google.IsEnabled" value="false" />
<add key="ExternalAuth.Google.ClientId" value="" />
<add key="ExternalAuth.Google.ClientSecret" value="" />
You can separately enable and configure each social media login option. To learn 'how to obtain social media API keys for your application', you can refer to this document or search the web (there are many resources on the web). So, we will not go to details of creating apps on social medias. Once you get your keys, you can write them into web.config. When you enable it, social media logos are shown on the login page as shown below:
Then you can click a social media icon to login with your existing account. Check Startup class to see where this configuration is used. You can add more social media options yourself.
In addition to social logins, ASP.NET Zero integrates with OpenId Connect login. It's configuration can be changed in web.config:
<add key="ExternalAuth.OpenId.IsEnabled" value="false" />
<add key="ExternalAuth.OpenId.Authority" value="" />
<add key="ExternalAuth.OpenId.ClientId" value="" />
<add key="ExternalAuth.OpenId.ClientSecret" value="" />
A logo (similar to social logos above) is shown in Login page when its enabled.
ADFS is just another external login like the social logins. In order to configure ADFS login, you just need to configure the following settings in the web.config file.
<add key="ExternalAuth.WsFederation.IsEnabled" value="false" />
<add key="ExternalAuth.WsFederation.MetaDataAddress" value="" />
<add key="ExternalAuth.WsFederation.Wtrealm" value="" />
ASP.NET Zero is ready to provide two factor login, but its disabled by default. You can easily enable it in the host settings page (on the Security tab):
Note: In a multi-tenant application, two factor authentication is available to tenants only if it's enabled in the host settings. Also, email verification and SMS verification settings are only available in the host side. This is by design.
When its enabled, the user is asked to select a verification provider after entering their name and password:
After that, a confirmation code is sent to the selected provider and the user enters the code in the next page:
This is available if the user has a confirmed email address. Since email sending is disabled in debug mode, you can see the code in logs. In release mode, email will be sent (you can change this and make emailing available in debug as well -- see the sending emails section).
This is available if the user has a confirmed phone number. Note that SMS sending is not fully implemented because it requires an integration to an SMS vendor. The current implementation just writes security codes to logs. You should complete the IdentitySmsMessageService class in the solution to make it usable. Otherwise, disable SMS verification in the settings.
As seen in the previous section, you can configure user lockout settings. Users are locked out when they enter wrong password for a specified count and duration.
When you click the "Create Account" link in the login page, a registration form is shown:
A user can be registered for a tenant, not for host if this is a multi-tenant application. If it is single-teant, there will be no tenancy name input here.
Recaptcha (security question) is optional. It uses Google's recaptcha service. Recaptcha service works per domain. So, to make it properly work, you should create your own private and public keys for your domain on https://www.google.com/recaptcha and replace the keys in the web.config file.
When a user registers as shown above, an email confirmation code is sent to their email address. If user did not receive this email for some reason, he can click Email activation and re-send the confirmation code.
Again, Tenancy name input is not shown for a single-tenant application or when tenant name is known via subdomain (like tenancyname.mydomain.com).
If a user forgots their password, they can click the "Forgot Password" link and will then be sent an email to reset their password.
The backend in ASP.NET Zero is a single page AngularJs application. When you login, you are redirected to the ApplicationController. It returns the layout view of the application.
All view, script and styles files are located in App folder (not all folders/files are not shown here):
There are three main folders here:
Given a view, directive, service, image -- used by both tenants and host -- it should be placed under the common folder as shown above. You should place the tenant or host specific directives, services, etc. under their own folder, not in the common folder. If you are developing a single-tenant application, you can place your files under the tenant section.
Application's main menu is defined in the AppNavigationProvider class. See ABP's navigation documentation to get a deep understanding on creating menus.
app.js is the entrance point of the application. You define the app angular module and angular routes in this file. Angular ui-router is used for routing. Routes (states in ui-router) are dynamically defined based on the current user's permissions (see authorization section). Example:
if (abp.auth.hasPermission('Pages.Administration.Tenant.Settings')) {
$stateProvider.state('tenant.settings', {
url: '/settings',
templateUrl: '~/App/tenant/views/settings/index.cshtml',
menu: 'Administration.Settings.Tenant'
});
}
Conditional routing definition prevents users from accessing an unauthorized page by simply entering a URL into the browser's address bar. Menu definition helps us to highlight the appropriate menu item when this route is activated.
As you see, .cshtml files are used for views. While .html files can be used, using .cshtml files allows us to take advantage of Razor's power when creating views.
Layout of the application is located under common/views/layout folder. All scripts and styles in the App folder (and subfolders) are bundled (see AppBundleConfig class). Any scripts and styles that you place there will be automatically added to the layout.
Layout consists of different parts as shown above. The main menu is rendered in sidebar.
If you're not developing a multi-tenant application, you can skip this section.
Most SaaS (multi-tenant) applications have editions (packages) which contain different feature sets. That us how they can provide different price and other options to their tenants (customers). Editions page (available in host login) is used to manage an application's editions:
Editions are used to group feature values and assign to tenants. When you click Actions/Edit for an edition, you can see the assigned features for that edition:
The startup project only contains the Chat feature (and it's wto sub-features) and they can be enabled/disabled per edition/tenant. All features are defined in AppFeatureProvider class. Feature values are stored in the AbpFeatures table. Features are not restricted to boolean (enabled/disabled) values and can contain different types of values as shown below:
See feature management and edition management documents for more information.
If you're not developing a multi-tenant application, you can skip this section.
If this is a multi-tenant application and you logged in as a host user, then tenants page is shown:
A tenant is represented by the Tenant class. The Tenant class can be extended by adding new properties. Initially, there is only one tenant, named Default. Tenancy Name (code name) is the unique name of a tenant. A tenant can be active or passive. If it is passive, users associated with this tenant cannot login to the application.
When you click the "Create new Tenant" button, a dialog is shown:
Tenancy name should be unique and not contain spaces or other special chars since it may be used as the subdomain name (e.g. tenancyname.mydomain.com -- see the section below). Name can be anything. Admin email is used as the email address of the admin user of the new tenant. Admin user is automatically created with the tenant. You can set a random password for admin and send an activation email. When the user first logs in, he/she should change the password. You can uncheck this to enter a known password.
When you create a new tenant, you should select/create a database to store the new tenant's data. You can select 'Use host database' to store tenant data in host database (can be used for single database approach) or you can specify a connection string to create/use a dedicated database for the new tenant. ASP.NET Zero supports a hybrid approach. That means you can use host database for some tenants and create dedicated databases for other tenants. You can even group some tenants in a separated database.
All tenant actions are handled by the TenantAppService class. Example (deleting a tenant):
[AbpAuthorize(AppPermissions.Pages_Tenants_Delete)]
public async Task DeleteTenant(EntityRequestInput input)
{
var tenant = await TenantManager.GetByIdAsync(input.Id);
CheckErrors(await TenantManager.DeleteAsync(tenant));
}
TenantAppService mostly uses TenantManager domain service for tenant operations.
An edition can be assigned to a tenant during tenant creation or by editing the tenant. The tenant will inherit all features of the assigned edition. You can also override features and values for a tenant. Click actions/change features for a tenant to customize its features:
As a host user, you may want to perform operations on behalf of a tenant. In that case, you can click the Actions button of a tenant and select "Login as this tenant" option:
When you click it, you see a modal to select a user of the tenant. You can select any user and perform such operations as that user is allowed. See User Impersonation section in this document for more information.
A multi-tenant application generally uses subdomains to identify current tenant. tenant1.mydomain.com, tenant2.mydomain.com and so on. ASP.NET Zero automatically identifies and gets the tenant name from the subdomain (see host settings section).
Organization units (OU) are used to hierarchically group users and entities. Then you can get user or entities based on their OUs. When you click Administration/Organization units, you go to the related page:
Here, you can manage OUs (create, edit, delele, move) and members (add/remove).
OrganizationUnitManager is used to manage OUs, UserManager is used to manage OU members in the code. OrganizationUnitAppService performs the application logic.
In the left OU tree, you can right click to an OU (or left click to arrow at the right) to open context menu for OU operations. When you try to add a member, a modal is shown to select the user:
This is actually a generic lookup modal and can be used to select any type of entity (see App/common/views/common/lookup.js and corresponding view). To select the users, you create a FindUsers method in CommonLookupAppService then configure the modal to work with that method (see organizationUnits/index.js file for usage of lookupModal.open).
See organization unit management document for more information.
When you click Administration/Roles menu, you go to the role management page:
Roles are used to group permissions. When a user has a role, then he/she will have all permissions of that role.
A role is represented by the Role class. The role class can be extended by adding new properties.
RoleManager performs domain logic; RoleAppService performs application logic for roles.
Roles can be dynamic or static:
One or more roles can be set as default. Default roles are assigned to newly added/registered users as default. This is not a development time property and can be set or changed after deployment.
In the startup project, you have a static admin role for the host (for multi-tenant apps). Also, you have a static admin and user roles for tenants. Admin roles have all permissions granted by default. User role is the default role for new users and has no permissions by default. These can be changed easily. See StaticRoleNames class for all static roles and AppRoleConfig for changing static roles.
Since roles are used to group permissions, you can set permissions of a role while creating or editing as shown below:
(not all permissions are shown in the figure above)
Every tenant has its own roles and any change in roles for a tenant does not affect other tenants. Also, host has its own isolated roles.

User class represents a user. User class can be extended by adding new properties.
UserManager is used to perform domain logic; UserAppService is used to perform application logic for users.
A user can have zero or more roles. If a user has more than one role, he inherits union of permissions of all the roles assigned to him/her. Also, you can set user-specific permissions. A user specific permission setting overrides role settings for this permission. A screenshot of user permission dialog (not all permissions are shown here):
(not all permissions shown in the figure above)
A dialog is used to create/edit a user:
You can change user's password, make him active/passive and so on. A user can have a profile picture. It can be changed by the user (see User Menu section). Admin user cannot be deleted as a business rule. If you don't want to use admin, you can make it passive.
As admin (or any allowed user), you may want to login as a user and perform operations on behalf of that user, without knowing their password. Click Actions button for any user and select "Login as this user":
When you click it, you are automatically redirected and logged in as this user. This is called "user impersonation". When you impersonate a user, a "back to my account" option is added to the user profile menu:
In an impersonated account, you can only perform operations that that user is allowed to do. That means everything works exactly the same as if that user logged in themself. The only difference is that audit logs will indicate that operations are performed by somebody else. Note that also a red 'back' icon is shown close to the username to indicate that you are currently impersonating another user.
Impersonation is done in AccountController of the Web project.
The language management page is used to manage (add/edit/delete) application languages and change localized texts:
You can create new language, edit/delete an existing language and set a language as default. When you click to Change text for any language, you are redirected to a new view to edit language texts:
You can select any language as a base (reference) and change the target language's texts. Since there may be different localization sources, you select the source to translate. When you click the edit icon, you can see the edit modal for the selected text:
Host users (if allowed) can edit languages and localized texts. These languages will be default for all tenants for a multi-tenant application. Tenants inherit languages and localized texts and can override localized texts or can add new languages.
Both pages use the LanguageAppService class as application service. It has methods to manage languages and localized texts. The IApplicationLanguageManager and IApplicationLanguageTextManager interfaces are used to perform domain logic (as used by LanguageAppService).
See language management documentation for more information.
The audit logs page displays all user interactions with the application:
All application service methods and MVC controller actions are automatically logged and can be viewed here. See audit logs documentation to learn how to configure it. When you click the magnifier icon, you can see all details for an audit log entry:
The audit log report is provided by the AuditLogAppService class.
The host settings page is used to configure some system settings:
Timezone is an important setting on this page. AspNet Zero can work in multiple timezones. While it's easy to change, default startup solution does not enable UTC datetimes. See timing document to know how to change.
When you switch to UTC datetime, all DateTimes are stored as UTC by default, but each user can see dates and times in his own time zone. Timezone setting on this page allows you to set a default time zone for the application including all tenants and users. Tenants and users can change the time zone in their own settings.
On the host settings page, there are also other settings. The "SAVE ALL" button saves all settings in one click. HostSettingAppService is used to retrieve and save settings (see setting provider section for more information).
The Security tab on the host settings page contains password complexity settings. The host can define system wide password complexity settings on this tab. Each tenant can override this setting on the tenant settings page. PasswordComplexityChecker class is responsible for checking if a password satisfies the password complexity settings.
In a multi-tenant application, tenant settings are shown as below:
If you disable multi-tenancy, some host settings are also shown on this page (since there is no host setting page). Tenants can also define password complexity settings for their users or they can use password complexity settings defined by the host user.
The TenantSettingAppService is used to get/set tenant settings.
LDAP (Active Directory) Authentication is disabled by default. To make it work, you should disable multi-tenancy since LDAP auth is not used in a multi-tenant system normally. In CoreModule class in .Core project, you should enable the following line:
Configuration.Modules.ZeroLdap().Enable(typeof(AppLdapAuthenticationSource));
Then you can see the LDAP settings section on the settings page:
You can check "Enable LDAP Authentication" to enable it. If the server works in domain mode and the application runs with a domain user or local system, then generally there is no need to set the domain name, user, and password. You can logout and then login with your domain user name and password. If not, you should set this information.
The maintenance page is only available to the host and is shown below:
On the Caches tab you can clear some or all caches. Clearing caches may be needed if you manually change the database and want to refresh the application cache. CachingAppService is used to clear caches on the server side.
Website Logs tab is used to see and download logs:
WebLogAppService is used to get logs from server.
ASP.NET Zero startup project also includes a sample dashboard. It is just for demo purposes, you can use it as a starting point for your actual dashboard:
Here, only Member Activity graph data is retrieved from server (from TenantDashboardAppService). You can click the refresh button to generate random graphs.
Notification icon is located next to the language selection button. The number in the red circle shows the unread notification count.
A user can see three recent notifications by clicking this icon.
A user can mark all notifications as read by clicking the "Set all as read" link or can mark a single notification by clicking the "set as read" link next to each notification.
"Settings" link opens notification settings dialog.
In this dialog there is a global setting for the user to enable/disable receiving notifications. If this setting is enabled, then the user can enable/disable each notification individually.
You can also define your custom notifications in the AppNotificationProvider class. For example, a new user registration notification is defined in the AppNotificationProvider as below.
context.Manager.Add(
new NotificationDefinition(
AppNotificationNames.NewUserRegistered,
displayName: L("NewUserRegisteredNotificationDefinition"),
permissionDependency: new SimplePermissionDependency(AppPermissions.Pages_Administration_Users)
)
);
See notification definitions section for detailed information.
The AppNotifier class is used to publish notifications. The NotificationAppService class is used to manage application logic for notifications. See notifications documentation for detailed information.
All notifications connected to the user are listed on this page.
The chat icon is located next to the user's profile image on the top right corner of the page. The number in the red circle shows the total unread chat message count.
When user clicks this icon, a chat panel appears on the right of page. This panel contains a list of friends of the user and a list of blocked users.
A user can add new friends by writing their username(s) into the username textbox above the friend list. If the "Chat with other tenants" feature is enabled for the tenant, users of other tenants can be added as a friend by writing [tenancy name]\[user name] (ex: Default\admin). If the "Chat with host users" feature is enabled, host users can be added as friends by writing .\[user name] in the same textbox.
Online friends/users have a green circle on their profile image; offline friends/users have a gray circle.
A user can pin or unpin the chat panel by clicking the pin icon on the top right corner of the chat panel. The application will remember the last state of chat panel and restores it when the user logs in to application.
When a friend/user is selected, the conversation panel is opened.
A user can block or unblock thier friends/other users in this area. There is a wrench icon to the right of the selected user's username. This icon opens an action menu that contains "block user" or "unblock user" actions according to the target user's block status.
Chat messages are distributed via the ChatHub SignalR hub class which uses the ChatMessageManager domain class.
The ChatUserStateWatcher class is responsible for watching online/offline state changes of chat users. When a user's status changes from online to offline, or vice-versa, this class catches the state change and notifies friends of the related user.
The FriendshipAppService and the FriendshipManager classes are responsible for managing friendship requests. Chat messages from blocked users are not delivered to target users.
Since chat is a real time operation, the application caches friends of online users and unread message count from each friend. The UserFriendsCache class manages these caching operations.
The UserFriendCacheSyncronizer class is responsible for keeping the user friends cache up to date. In order to do that, it watches some events of the Friendship and ChatMessage entities.
There are three chat features in the system. These are "Chat", "Chat with host", "Chat with other tenants". These features can be enabled/disabled per edition/tenant. By using these features the host can enable/disable chat with other tenant's users or host users.
A user can click his name at the top right corner to open the user menu:
Linked accounts are used to link multiple accounts to each other. A user can easily navigate through his/her accounts using this feature.
A user can link new accounts or delete already linked accounts by clicking the "Manage accounts" link.
In order to link a new account, a user must enter the login credentials of the related account.
The UserLinkAppService class is used to manage application logic for account linking; the UserLinkManager class is used to manage domain logic for account linking.
My settings is used to change user profile settings:
As shown here, the admin user name cannot be changed. It's considered a special user name since it's used in the database migration seed. Other users can change their usernames. ProfileAppService is used to get/change settings.
All login attempts (success or failed) are logged in the application. A user can see the last login attempts for his/her account. The UserLoginAppService is used to get login attempts from server.
A user can change their own profile picture. ProfileController is used to upload and get user profile pictures. The Angular file upload module used to select and upload a profile picture to the server. Currently, jpg/jpeg, gif and png files are supported, you can extend this to allow additional file extensions.
ProfileAppService is used to change password.
AccountController is used to logout the user and redirect to the Login page.
The same backend application is also available as a MPA using ASP.NET MVC, Web API and jQuery. All functionallity is identical with the SPA Angular application. It uses the same application services to perform actions. This is a screenshot from the application:
Since all functionallity is identical, you can read the SPA section above to understand the application. A few differences in setup are explained below.
This application is included in the .Web project as a separated Area as shown below:
This is a classic MVC folder structure with Controllers, Models and Views.
Application's main menu is defined in the MpaNavigationProvider class. See ABP's navigation documentation to get a deep understanding on creating menus.
Layout of the application is located under Views/Layout folder.
The header, footer and siderbar are developed as partial views.
ASP.NET Zero includes a tool, Migrator.exe, to easily migrate your databases. You can run this application to create/migrate host and tenant databases.
This application gets the host connection string from its own .config file. It will be the same in the web.config at the beginning. Be sure that the connection string in the config file is the database you want. After getting host connection sring, it first creates the host database or applies migrations if appropriate. Then it gets the connection strings of the tenant databases and runs migrations for those databases. It skips a tenant if it has not a dedicated database or its database is already migrated for another tenant (for shared databases between multiple tenants).
You can use this tool on development or production to migrate databases on deployment, instead of EntityFramework's own Migrate.exe (which requires some configuration and can work for single database in one run).
Both SPA and MPA application use AJAX extensively to provide a better user experience. They call application service methods via AJAX. Thus it is necessary to create web API controllers as adapters (A Client calls Web API Controller action via AJAX, then it calls application service method).
The ABP framework automatically creates a dynamic web API layer using the application service interface definitions. There is no web API Controller actually. You build dynamic web api controllers in PhoneBookWebApiModule class in .WebApi project. See dynamic Web API layer documentation for more information.
While ABP dynamically create Web API Controllers, you can also create regular Web API Controllers as you might normally do.
The ASP.NET Zero User Interface is completely localized. ASP.NET Zero uses dynamic, database based, per-tenant localization (see the related section above).
XML files are used as the base translation for desired languages:
PhoneBook will be your ProjectName. You can add more XML files by copying one XML file and translate it to the desired language. Notice that the XML files should be an embedded resource. See valid culture codes.
When you are adding a new localizable text snippet, add it to the XML file of the default language then use it in your application. You should also add translated values to the corresponding XML files. It is not necessary to add it to the database migration code since the value in the XML file will be used as default.
Application languages are defined in the DefaultLanguagesCreator class. This is used as a seed data in Entity Framework Migration. So, if you want to add a new language, just add it to the DefaultLanguagesCreator class. Also, you can add a corresponding XML file as described above as default translation.
See localization and language management documentations for more information.
The ASP.NET Zero template uses EntityFramework code-first and migrations. PhoneBookDbContext (YourProjectDbContext for your project) defines the DbContext class. Migrations folder contains the EF migrations.
The PhoneBookRepositoryBase class is the base class for your custom repositories. See entity framework integration documentation for more information.
The authorization system is based on permissions. AppPermissions contains constants for permission names and the AppAuthorizationProvider class defines all permissions in the system. You should define a permission here before using it in the application layer.
See authorization documentation to learn how to configure permissions.
AppFeatureProvider class defines features of the application for multi-tenant applications. Feature names are defined in the AppFeatures class as constants.
See feature management documentation to learn how to define and use features.
Every setting has a unique name. Setting names are defined in the AppSettings class as constants. All settings and their default values are defined in the AppSettingProvider class.
See setting documentation to learn how to create and use settings.
Menus are automatically generated using definitions in the AppNavigationProvider class. You have two menus: Main (the main menu in the Angular application) and FrontEnd (main menu in the front-end web site).
See navigation documentation for more information.
ASP.NET Zero uses in-memory caching but it's ready to use Redis as a cache server. If you want to enable it, just uncomment the following line in your WebModule (in App_Start folder in your .Web project):
Configuration.Caching.UseRedis();
Redis server should be running to be able to use it. See caching documentation for more information.
ABP framework contains a background job system with a default background job manager. If you want to use Hangfire as your background job manager, you can easily enable it.
First, uncomment these lines in WebModule (in App_Start folder in your .Web project):
Configuration.BackgroundJobs.UseHangfire(configuration =>
{
configuration.GlobalConfiguration.UseSqlServerStorage("Default");
});
If you want to enable the Hangfire dashboard, you can uncomment the following line in Startup.cs (in App_Start folder in your .Web project):
app.UseHangfireDashboard();
Note: Hangfire creates its own tables in the database. See background job and hangfire integration documents for more information.
SignalR is properly configured and integrated in the startup template. The real time notification system uses it. You can direcly use SignalR in your applications. See SignalR integration document for more information.
ASP.NET Zero uses Log4Net for logging as default. Configuration is defined in log4net.config file in the .Web project. It writes all logs into the Logs folder of the web site as default. When you publish your project, remember to configure write permission for the Logs folder.
Check logging documentation to see how to inject ILogger and write logs.
ASP.NET Zero uses AutoMapper for DTO to Entity mappings (and other types of object-to-object mappings). You use the Abp.AutoMapper library that uses AutoMapper, which is simple and declarative.
See the DTO class that is used to transfer a tenant's editing information:
[AutoMap(typeof (Tenant))]
public class TenantEditDto : EntityDto
{
[Required]
[StringLength(Tenant.MaxTenancyNameLength)]
public string TenancyName { get; set; }
[Required]
[StringLength(Tenant.MaxNameLength)]
public string Name { get; set; }
public bool IsActive { get; set; }
}
Here, the AutoMap attribute automatically creates mapping between TenantEditDto and the Tenant classes. Then you can automatically convert a Tenant object to a TenantEditDto (and vice verse) object as shown below:
[AbpAuthorize(AppPermissions.Pages_Tenants_Edit)]
public async Task<TenantEditDto> GetTenantForEdit(EntityRequestInput input)
{
return (await TenantManager.GetByIdAsync(input.Id)).MapTo<TenantEditDto>();
}
MapTo method does mapping.
Attribute based mapping may not be sufficient in some cases. If you need to directly use Automapper API to configure your mappings, you should do it in the CustomDtoMapper class.
See Data Transfer Objects documentation for more information on DTOs.
ASP.NET Zero sends emails to users in some cases (e.g. forgot password and email confirmation). The email template is defined in the Emailing/EmailTemplates folder of .Core project (default.html). You can change the default email template by editing this file.
Email sending is disabled in DEBUG mode. This is because the development environment may not be configured properly to send emails. You can enable it if you want. It is enabled in RELEASE mode. Check the YourProjectNameCoreModule class's PreInitialize method to change it if you like.
User profile pictures are stored in the database, instead of in the file system. But it's not stored in Users table for performance reasons (Users are frequently retrieved from database, but profile pictures are rarely needed).
A general-purpose binary saving mechanism built in ASP.NET Zero: The BinaryObject entity can be used to save any type of binary objects (byte arrays). Since a profile picture can be converted to a byte array, user profile pictures are saved here.
The IBinaryObjectManager interface defines methods to save, get, and delete binary objects. DbBinaryObjectManager implements it to save binary objects in the database. For example, ProfileController uses IBinaryObjectManager to get current user's profile picture from the database.
You can create a different implementation of the IBinaryObjectManager interface to store files in another destination.
It's common to use the soft-delete pattern which is used to not delete an entity from the database but only mark it as 'deleted.' Thus, if an entity is soft-deleted, it will not be accidently retrieved into the application. ABP's data filters make this happen automatically.
In ASP.NET Zero, most entities are soft-deleted. See ABP's data filter documentation for more information about.
ASP.NET Zero uses ASP.NET Optimization for bundling & minifying script and style files. Bundles are defined in different files:
Also, see the ScriptPaths and StylePaths classes. They contain constants for locations of JS and CSS files.
There are some useful base classes used in the application:
It's strongly recommended to inherit one of these classes since they really make Logging, Localization, Authorization, etc. easier.
ABP framework simplifies and automates CSRF protection as much as possible. ASP.NET Zero template comes with CSRF protection pre-configured and working out of the box. For more information please see ABP's XSRF-CSRF-Protection documentation
The AppVersionHelper class is used to define the current version of the application in a single place. When you change the Version here, all projects in the application will be verisoned. Also, the version and release date are automatically shown in the bottom left corner on the application pages. That way you can always see the running application version.
ASP.NET Zero uses cookie based authentication for browsers. However, if you want to consume Web APIs or application services (those are exposed via dynamic web api) from a mobile application, you probably want a token based authentication mechanism. ASP.NET Zero includes bearer token authentication infrastructure. AccountController in .WebApi project contains an Authenticate action to get the token. Then you can use the token for subsequent requests.
Here, Postman (chrome extension) will be used to demonstrate requests and responses.
Just send a POST request to http://localhost:6234/api/Account/Authenticate with Context-Type="application/json" as shown below:
We sent a JSON request body includes tenancyName, userNameOrEmailAddress and password. tenancyName is not used to authenticate as a host user. As seen above, result property of returning JSON contains the token. You can save it and use for subsequent requests.
After authenticating and getting the token, you can use it to call any authorized actions. All application services are available to be used remotely. For example, you can use the User service to get a list of users:
Just made a POST request to http://localhost:6234/api/services/app/user/GetUsers with Content-Type="application/json" and Authorization="Bearer your-auth-token". Request body was just empty {}. Of course, request and response body will be different for different APIs.
Almost all operations available in the UI are also available via the Web API (since the UI uses the same Web API) and can be easily consumed.
Swagger UI is integrated into ASP.NET Zero. The Swagger UI configuration is located in the WebApiModule class in the WebApi project. You can browse the Swagger UI under "/swagger/ui/index".
The ASP.NET Zero startup project contains unit and integration tests. Tests are developed using the following tools:
Tests cover the Domain (core) and Application layers of the project. Open Test Explorer (Test\Windows\Test Explorer in VS main menu) to run unit tests:
These unit tests are a guide to understand the code. Also, they can be a model while writing your own unit tests for your application's functionality.
All unit test classes (actually they are integration tests since they work integrated to ABP, EntityFramework, AutoMapper and other libraries used -- up to application layer) are derived from AppTestBase. It initializes ABP system, mocks the database using Effort, creates the initial test data and logs in to the application for each of the tests. It also provides some useful common methods for all tests.
Here is a sample unit test from the application:
public class UserAppService_Delete_Tests : UserAppServiceTestBase
{
[Fact]
public async Task Should_Delete_User()
{
//Arrange
CreateTestUsers();
var user = await GetUserByUserNameOrNullAsync("artdent");
user.ShouldNotBe(null);
//Act
await UserAppService.DeleteUser(new IdInput<long>(user.Id));
//Assert
user = await GetUserByUserNameOrNullAsync("artdent");
user.IsDeleted.ShouldBe(true);
}
}
It creates some users to test and then verifies there is a user named "artdent". Then it calls the DeleteUser method of the user application service (which is being tested). Finally, it checks if the user is deleted. Here, the User is a Soft Delete entity, so its IsDeleted property must be true if it is deleted.
You can read this article to understand unit testing better.
Email Settings
If you don't configure email settings, some functions may not work (Like new tenant registration).
Publishing ASP.NET Zero is not different than any other solution. You can use Visual Studio as normally you do.
Many open source frameworks and libraries are used to build ASP.NET Zero project. Here is a list of all libraries:


>>> Calling all Pythonistas!
September 15 — 17, 2018 Lagos, Nigeria
We want you to submit a proposal. We are interested in a range of topics including web development, Design, Data Science, Networks, and anything else related to Python
YES! I WANT TO SPEAK AT PYCONIf you wish to speak in PyConNG 2018. Click here to submit a proposal.
Submit a ProposalIf you wish to sponsor PyConNG 2018. Click here to request a sponsor slot.
Request SponsorshipIf you or your company is interested in sponsoring PyCon Nigeria. Click the button below and we’ll get right back to you or send us an email on<EMAIL_ADDRESS>YES! I WANT TO BE A SPONSOR


Source code for trane.core.prediction_problem
import pandas as pd
import json
from ..utils.table_meta import TableMeta
from ..ops.op_saver import *
from dateutil import parser
__all__ = ['PredictionProblem']
[docs]class PredictionProblem:
"""Prediction Problem is made up of a list of Operations. The list of operations delineate
the order the operations will be applied in.
"""
def __init__(self, operations):
"""Args:
(List) Operations: a list of operations (class Operation) that define the
order in which operations should take place.
(String) label_generating_column: the column of interest. This column
will be solely used for performing operations against.
(String) entity_id_column: the column with entity id's.
(String) time_column: the name of the column containing time information.
Returns:
None
"""
self.operations = operations
[docs] def op_type_check(self, table_meta):
temp_meta = table_meta.copy()
for op in self.operations:
temp_meta = op.op_type_check(temp_meta)
if not temp_meta:
return False
return True
[docs] def execute(self, dataframe, time_column, cutoff_time):
"""This function executes all the operations on the dataframe and returns the output. The output
should be structured as a single label/value per the Trane documentation.
See paper: "What would a data scientist ask? Automatically formulating and solving predicton
problems."
Args:
(Pandas DataFrame): the dataframe containing the data we wish to analyze.
Returns:
(Boolean/Float): The Label/Value of the prediction problem's formulation when applied to the data.
"""
dataframe = dataframe.copy()
dataframe = dataframe[dataframe[time_column] > cutoff_time]
for operation in self.operations:
dataframe = operation.execute(dataframe)
return dataframe
def __str__(self):
"""Args:
None
Returns:
A natural language text describing the prediction problem.
"""
description = ""
last_op_idx = len(self.operations) - 1
for idx, operation in enumerate(self.operations):
description += str(operation)
if idx != last_op_idx:
description += "->"
return description
[docs] def to_json(self):
return json.dumps(
{"operations": [json.loads(op_to_json(op)) for op in self.operations]})
[docs] def from_json(json_data):
data = json.loads(json_data)
operations = [op_from_json(json.dumps(item)) for item in data['operations']]
return PredictionProblem(operations)


Copyright © 2007 Mochi Media, Inc.
Authors: Bob Ippolito (bob@mochimedia.com).
end_tag() = {end_tag, Name}
html_attr() = {string(), string()}
html_comment() = {comment, Comment}
html_data() = {data, string(), Whitespace::boolean()}
html_doctype() = {doctype, [Doctype]}
html_node() = {string(), [html_attr()], [html_node() | string()]}
html_token() = html_data() | start_tag() | end_tag() | inline_html() | html_comment() | html_doctype()
inline_html() = {'=', iolist()}
start_tag() = {start_tag, Name, [html_attr()], Singleton::boolean()}
| escape/1 | Escape a string such that it's safe for HTML (amp; lt; gt;). |
| escape_attr/1 | Escape a string such that it's safe for HTML attrs (amp; lt; gt; quot;). |
| parse/1 | tokenize and then transform the token stream into a HTML tree. |
| parse_tokens/1 | Transform the output of tokens(Doc) into a HTML tree. |
| test/0 | Run tests for mochiweb_html. |
| to_html/1 | Convert a list of html_token() to a HTML document. |
| to_tokens/1 | Convert a html_node() tree to a list of tokens. |
| tokens/1 | Transform the input UTF-8 HTML into a token stream. |
escape(B::string() | atom() | binary()) -> binary()
Escape a string such that it's safe for HTML (amp; lt; gt;).
escape_attr(B::string() | binary() | atom() | integer() | float()) -> binary()
Escape a string such that it's safe for HTML attrs (amp; lt; gt; quot;).
parse(Input::string() | binary()) -> html_node()
tokenize and then transform the token stream into a HTML tree.
parse_tokens(Tokens::[html_token()]) -> html_node()
Transform the output of tokens(Doc) into a HTML tree.
test() -> ok
Run tests for mochiweb_html.
to_html(Node::[html_token()] | html_node()) -> iolist()
Convert a list of html_token() to a HTML document.
to_tokens(T::html_node()) -> [html_token()]
Convert a html_node() tree to a list of tokens.
tokens(Input::StringOrBinary) -> [html_token()]
Transform the input UTF-8 HTML into a token stream.
Generated by EDoc, Sep 8 2009, 13:22:30.


Brain Configuration
MAC Address
00:00:00:00:00:00
Rando Message
Current Config
SSID
Password
Refresh
New Config
SSID
Password
Save
Restart
Firmware Update
Firmware file
Upload Firmware


THE MOD SQUAD
** (out of 4) - a fair movie
Release Date: March 26, 1999 Starring: Claire Danes, Omar Epps, Giovanni Ribisi, Dennis Farina, Josh Brolin, Michael Lerner, Richard Jenkins Directed by: Scott Silver Distributed by: Metro-Goldwyn-Mayer MPAA Rating: R (language, violence, some sexuality) URL: http://www.execpc.com/~kinnopio/reviews/1999/modsquad.htm
Something is horribly appropriate about THE MOD SQUAD. It lies in that confusing teenage ground between mainstream and fringe, and its cynical postmodern view is suddenly becoming very prevalent in adolescent society. However, this tiny societal revolution is nothing more than a hiccup in civilization's grand scale. And so the wave of trendiness which Scott Silver's THE MOD SQUAD rides is too meaningless to make the movie of any worth.
The plot is similarly meaningless for most of its 95-minute running time, and for a movie of such brevity, that's never good. The fast-paced feeling is nothing more than an illusion created by the liberal editing job, and it should be clear that the plot is nothing more than a skeleton to hang plot devices upon. The three writers involved (director Silver as well as Stephen Kay and Katie Lanier) have little experience between them, and that's frequently obvious: the comic relief would be nothing without Giovanni Ribisi and the suspense is never well-disguised.
Of course, with a little work, THE MOD SQUAD could've easily been premiered on primetime television, and so there's not much room for extended development. In quick succession, we're introduced to the characters, their mission, and their problems which will lead to the climactic final scene. Protagonists Julie (Claire Danes), Linc (Omar Epps), and Pete (Ribisi) are teens on their way to jail who cut a deal with police captain Adam Greer (Dennis Farina). The man says: help us and we'll help you -- that is, our heroes hold a get-out-of-jail-for-now card while they undercover-cop their way into Los Angeles' hottest hangouts. All does not go as planned, however, when Greer ends up dead with some drugs on his person, and everything stinks of setup.
It takes some time for all of this to stick in the heads of the audience, and by the time it does, the end credits are only fifteen minutes away. Most of the script is filled with trivial banter or clichéd substance, and unfortunately it isn't until the last scene that one of the characters takes a poke at the recycled plot. But when all is said, the script never helped this movie.
So instead director Silver tries to put the burden of success on the movie's trendy atmosphere: the 70's-revival dress, the racous big city nightlife, and the ease with which one can get laid therein are all themes which prevade the movie. Unfortunately the actors are too one- dimensional (Danes and Epps) or over-the-top (Ribisi) to draw the audience in, and thus THE MOD SQUAD will be dismissed as smoke and mirrors. It is possible to have fun watching this movie, but that would take far more brain power than the producers assumed the target audience would have.
all contents © 1999 Craig Roush
-- Craig Roush<EMAIL_ADDRESS>-- Kinnopio's Movie Reviews http://www.execpc.com/~kinnopio
The review above was posted to the
rec.arts.movies.reviews newsgroup (de.rec.film.kritiken for German reviews).
The Internet Movie Database accepts no responsibility for the contents of the
review and has no editorial control. Unless stated otherwise, the copyright
belongs to the author.
Please direct comments/criticisms of the review to relevant newsgroups.
Broken URLs inthe reviews are the responsibility of the author.
The formatting of the review is likely to differ from the original due
to ASCII to HTML conversion.
Related links: index of all rec.arts.movies.reviews reviews


This can happen in two cases:
Example:
@Target(ElementType.METHOD)
@interface A { }
// The annotation will not appear in bytecode at all,
// as it should be propagated to the accessor but accessor is explicitly defined
record R(@A int x) {
public int x() { return x; }
}
New in 2021.1


Namespace: http://www.bioontologies.org/obd/schema/pheno
A document consists of some combination of genotypes and phenotypes, manifestations of phenotypes via genotypes, and genetic features
| version | Built-in type string | optional |
|---|---|---|
|
: File format version : should match this schema version (eg 0.01) |
Exactly 1 sequences of:
Namespace: http://www.bioontologies.org/obd/schema/pheno
Each genotype record represents a single individual or group of genetically similar individuals
| id | Simple type pheno:identifier_Type | optional |
|---|---|---|
| organism | Simple type pheno:identifier_Type | optional |
|
NCBI TAxon ID | ||
| background | Simple type pheno:identifier_Type | optional |
|
another genotype |
Exactly 1 sequences of:
Namespace: http://www.bioontologies.org/obd/schema/pheno
Simple type pheno:name_Type
Namespace: http://www.bioontologies.org/obd/schema/pheno
A genotype is a collection of alleles In general, only the mutant alleles are specified. sequence variants can also be specified
| copy_count | Built-in type int | optional |
|---|---|---|
| feature | Simple type pheno:identifier_Type | optional |
|
a reference to a genetic feature |
Empty
Namespace: http://www.bioontologies.org/obd/schema/pheno
A genetic feature may be a gene (allele), transcript, SNP, etc typed by SO This is a partial model of genetic features - a full model can be found in Chado
| id | Simple type pheno:identifier_Type | required |
|---|---|---|
|
unique stable global identifier - this can be used to reference more detailed info in a sequence/genetics db | ||
| organism | Simple type pheno:identifier_Type | optional |
|
optional: same as genotype.organism_id if not specified |
Exactly 1 sequences of:
Namespace: http://www.bioontologies.org/obd/schema/pheno
a single genotype can be associated with multiple phenotypes in different experiments and different environments
| penetrance_percentage | Built-in type float | optional |
|---|---|---|
| genotype | Simple type pheno:identifier_Type | optional |
Exactly 1 sequences of:
Namespace: http://www.bioontologies.org/obd/schema/pheno
A phenotype manifestation is an observation of a phenotype in one more individual organisms under experimental conditions, linked with the genetic and environmental causes of that phenotype
| id | Simple type pheno:identifier_Type | optional |
|---|---|---|
|
Each manifestation can be identified, but this is optional. Note that the ID is for the manifestation of the phenotype in either a single individual organism, or in a population of indistinguishable individuals in an experiment or trial |
Exactly 1 sequences of:
Namespace: http://www.bioontologies.org/obd/schema/pheno
a phenotype is a collection of characteristics possessed by an organism or collection of organisms (or in some cases, the environment of the organism, as a result of that organism's actions - for example a termite's nest) the phenotype arises as a result of the organism's genotype and the environment of the organism Examples of phenotypes are: * "red eyes and notched wings" * "reduced apoptosis and increased susceptibility to cancer" * "Initially a single lateral is formed, but it is thicker than normal and sometimes individual bundles of actin filaments can be seen. The laterals split near the distal tip as they elongate and at later stages they appear to be split over more of their length." * "interrupted imaginal disc development and stunted wings at the adult stage" The phenotype is the entire collection of characteristics exhibited by that organism (or collection of effectively indistinguishable organsisms). Each organism has a single phenotype throughout its lifespan - the characteristics that comprise that phenotype may change, this is reflected in the phenotype_character records each phenotype record represents a specific phenotype which may be instantiated in one or more organisms. If two or more organisms have indistinguishable phenotypes, the same record may be used. If phenotypes are distinguishable then a different record should be used.
Exactly 1 sequences of:
Namespace: http://www.bioontologies.org/obd/schema/pheno
A phenotype character is one or more qualities inhering in a single bearer entity. For example, a PC with quality type "red" and bearer type "eye" (written here for convenience as "red eye") represents a particular instantiation of "red eye"/"red eyes" in a particular organism or collection of like organisms examples of phenotype character types: red hair, low bone mass, square jaw, long thick bristle, 2cm long tail, spermatocyte devoid of asters, elevated blood pressure, lacking wings, having an additional digit relative to a wild type individual, having a brain size during embryonic development that is larger than a typical individual of the same genus/order, short attention span, having an abnormal shape, abnormal fusion between digits, lacking red spots, abnormally low numbers of B-cells after infection, lacking circularity in the cross-section of an arista lateral A phenotype character record represents an instance of a characteristic possessed by a single organism, or a collection of identical characteristics possessed by like organisms.
| id | Simple type pheno:identifier_Type | optional |
|---|---|---|
| expressivity_percentage | Built-in type float | optional |
Exactly 1 sequences of:
Namespace: http://www.bioontologies.org/obd/schema/pheno
each 'bearer' record represents a particular bearer of some general bearer type: for example, a particular wing of a particular fly entities can be spatial objects (3D e.g. anatomical parts) or spatiotemporal entities (4D e.g. processes)
Exactly 1 sequences of:
Namespace: http://www.bioontologies.org/obd/schema/pheno
aka attribute aka property any one particular bearer can have multiple qualities inhering in it. For example, a particular tail can have qualities such as shape, length, etc each quality inheres in a single bearer throughout the duration of that entities existence. For example, my height is a single quality that inheres in my body throughout my life. This quality can take on different states throughout the lifetime of the bearer.
| determinable | Simple type pheno:classId_Type | optional |
|---|---|---|
|
not required: it can be deduced from the quality type. if provided, the value of this field is always an OBO-style identifier from PATO may be useful for report purposes; eg the color of this entity is red (where 'color' is the determinable) | ||
| count | Built-in type integer | optional |
|
certain kinds of quality implicitly or explicitly refer to numbers. Examples of these are the qualities of "having supernumery parts" or the qualities of "lacking parts". It can be useful to state the exact number here, rather than overloading the ontology of qualities. the number will refer to either the relative or absolute quantity....? This is purely optional, as it is usually sufficient to state that a particular hand has supernumery fingers, without saying how many extra |
Exactly 1 sequences of:
Namespace: http://www.bioontologies.org/obd/schema/pheno
Relational qualities inhere in additional entities. This should be used for relational qualities (e.g. sensitivity, distance_from) and not for monadic entities. other examples include: "spermatocytes *devoid_of* asters", "thorax *lacks* wing", hand *has-supernumerary-parts* finger in these cases, the related_entity records the _type_ of part that is lacking or present in lower or higher numbers
Exactly 1 sequences of:
Namespace: http://www.bioontologies.org/obd/schema/pheno
sometimes a state is only instantiated if a certain condition holds
Exactly 1 sequences of:
Namespace: http://www.bioontologies.org/obd/schema/pheno
quality types can be absolutist (square, red) or relative (high pressure, short height). relative always implies a context. The default context is always an equivalent phenotype character in a typical individual of the same species. We can be more explicit if we like by specifying in_comparison_to Examples: an allele which has more or less pronounced effects in different genetic backgrounds; A yellow eye which is red in wildtype;
| relation | Simple type pheno:classId_Type | optional |
|---|---|---|
|
if left blank, this is inferred from the quality type; for example, if Q="high pressure", then the relation is higher-than or increased-with-respect-to | ||
| about | Simple type pheno:identifier_Type | optional |
|
Can be an ID of a particular phenotype manifestation, or an ID for a whole taxon |
Exactly 1 sequences of:
Namespace: http://www.bioontologies.org/obd/schema/pheno
for abnormal/normal these should come from the PATO modifier terminology
| about | Simple type pheno:classId_Type | required |
|---|---|---|
Empty
Namespace: http://www.bioontologies.org/obd/schema/pheno
: measurement : examples: length measurement (with ruler, in cm) spot intensity real-world measurements (exlcuding count measurements) are inexact and hence ranges.
| unit | Built-in type NMTOKEN | required |
|---|---|---|
|
the unit should be a reference to an SI unit Q: do SI units have an identifier system, or do we just use eg "mm" Q: do we need the ability to specify composite units, eg lb/kg - or is this handled by SI? | ||
| value | Built-in type float | optional |
|
the only time this would be omitted is if we only have a range | ||
| min_value | Built-in type float | optional |
|
Q: does the range reflect our lack of knowledge (eg accuracy of measuring instrument) or an actual range of values? or should we represent an actual range as multiple measurements? | ||
| max_value | Built-in type float | optional |
| standard_deviation | Built-in type float | optional |
| standard_error | Built-in type float | optional |
| assay | Simple type pheno:identifier_Type | optional |
|
TODO: reference to a particular experiment |
Empty
Namespace: http://www.bioontologies.org/obd/schema/pheno
evidence: could refer to papers, figures in papers, raw images, etc
| id | Simple type pheno:identifier_Type | required |
|---|---|---|
| type | Simple type pheno:classId_Type | optional |
Empty
Namespace: http://www.bioontologies.org/obd/schema/pheno
The type of environment. For now this is just a pre or post coordinated type reference. In future We may want to add more under here
Exactly 1 sequences of:
Namespace: http://www.bioontologies.org/obd/schema/pheno
A reference to a type. Here type is used in the ontology sense of a "kind" or "universal". A type can be referenced simply by giving a term ID from an ontology. More complex types can be "post-coordinated"
| about | Simple type pheno:classId_Type | required |
|---|---|---|
|
Base/generic type. This is often all that is required. the ID is OBO-compliant and can be from any ontology |
Exactly 1 sequences of:
Namespace: http://www.bioontologies.org/obd/schema/pheno
for cross-products these are the characteristics that distinguish a specific type from a general type e.g. if we want to annotate to an bearer "scutum bristle" and the anatomical ontology does not contain this term, only "scutum" and "bristle". In this case the bearer type_id (ie the primary term) would be the ID for "bristle". We would have one differentium "part_of scutum"
| relation | Simple type pheno:classId_Type | required |
|---|---|---|
Exactly 1 sequences of:
Namespace: http://www.bioontologies.org/obd/schema/pheno
Exactly 1 sequences of:
Namespace: http://www.bioontologies.org/obd/schema/pheno
temporal_qualifier examples: during larval stage; after pupal stage; at 7pm on 2000/01/01; overlapping M1-phase; we do not tie ourself to any one theory of time - time ranges and points are represented using time_range
| relation | Simple type pheno:classId_Type | optional |
|---|---|---|
|
e.g. before, after, during - would come from an ontology of temporal relations this is optional. If not specified, treated as *overlap* relation |
Exactly 1 sequences of:
Namespace: http://www.bioontologies.org/obd/schema/pheno
represents an interval or point in time (we are neutral w.r.t points vs intervals)
| id | Simple type pheno:identifier_Type | optional |
|---|---|---|
|
: id : OPTIONAL this is typically not used. You would use it if you wish to grant an identifier to a particular time point or range. This would allow you to make partial-order statements; e.g. t1 before t2 |
Exactly 1 sequences of:
Namespace: http://www.bioontologies.org/obd/schema/pheno
an optionally-attributed textual description
| id | Built-in type NMTOKEN | optional |
|---|---|---|
| attribution | Simple type pheno:identifier_Type | optional |
|
e.g pubmed ID |
Built-in type string
Built-in type string
Built-in type NMTOKEN


Combined Public Transport and Rail Travel Times
Visualisation based on Department of Transport combined Public Transport and Rail Travel-Time data. The project directory is here This shows shortest public transport connection times for in England and Wales via 180 rail stations in Great Britain
| Legend | Combined (07:00-00:00) |
|---|---|


The Grid enables the users to select a single row or multiple rows by enabling Row Selection. Once the Data table row selection functionality is enabled, the end-user will be able to select data rows. For more convenience, Ornamentum data table supports 03 main row selection modes.
rowSelectable: boolean
Default Value: false
Target Component: <ng-data-table>
To Enable row selection, configure the rowSelectable
to true and by default, the table does
not display row selectable option, which means the property is disabled.
Furthermore, There are some additional configurations available to customize the functionality. These properties will be discussed in the following sections.
selectMode: string = 'single' | 'single_toggle' | 'multi'
Default Value: 'single'
Target Component: <ng-data-table>
This control allows you to configure the row selection mode. There are 03 types of row selections available in the data table as mentioned above.
The user will be allowed to select only one row at a time and not allowed to deselect the selected option by clicking the same row. If another row is being selected, the previously selected row will be deselected automatically.
The user will be allowed to select only one row at a time and lets to deselect the selected option by clicking the same row. If another row is being selected, previously selected row will be automatically deselected. Additionally, users are facilitated with to remove the row selection by clicking the same row.
This selection technique facilitated with to select deselect single/multiple row selection checkboxes as desired or by clicking anywhere in the row if Select on Row Click functionality is enabled.
showRowSelectCheckbox: boolean
Default Value: true
Target Component: <ng-data-table>
By configuring This property, It displays row selection checkboxes for all the available rows in the data table and triggers the Row Select Change event for each row implicitly, when the user changes the state of the row checkbox.
showRowSelectAllCheckbox: boolean
Default Value: false
Target Component: <ng-data-table>
This property allows the users to select all the rows in current view at once by clicking on a single checkbox or else selecting all the rows one by one will trigger the checkbox. It was located in the top of the row selection checkbox column and for each page, view have separate row select all checkbox. It triggers the Row Select Change event automatically when the user changes the state of the select all checkbox.
selectOnRowClick: boolean
Default Value: false
Target Component: <ng-data-table>
This property allow the users to perform row click operation anywhere within a row. It will trigger the Row Select Change for each row click event implicitly, based on the provided Select Mode.
selectTrackBy: string
Default Value: 'id'
Target Component: <ng-data-table>
This property allows the users to provide a field name to identify a selection item schema and it might be uniquely identifiable all over the data set. When a user selects a row, the data table Row Select Change will emit the selected row selection id for each row selection operation.
selectedRow: any
Default Value: undefined
Target Component: <ng-data-table>
Depends On: [selectTrackBy]
This property allows to set a specifically selected row to display after the data table Initialization or component initialization events fired. It accepts a Select Track By column any unique field value and can only be used when Select Mode is 'single' or 'single_toggle'.
selectedRows: any[]
Default Value: []
Target Component: <ng-data-table>
Depends On: [selectTrackBy]
This property allows to set specifically selected rows to display after the data table Initialization or component initialization events fired. It accepts Select Track By column any unique field values array and can only be used when Select Mode is 'multi'.


Introduction
Push notification is the delivery of information to the user without a specific request from the user. In mobile devices, push notifications are implemented employing the use of a notification service. The notification is sent to each device that has registered to receive them, and is handled by the platform before giving it to the specific app. To implement push notification:
- App has to register itself (the device) to the platform specific notification service.
- Push messages can be sent via the notification service only, hence the backend/server code that handles it must connect to the notification service.
Basic Architecture of Push Notifications
As observed, push notifications with the client app and the server can be routed only via the Push Notification Service (PNS) provided by each platform [APNS - Apple Push Notification Service, FCM - Firebase Cloud Messaging (which replaced Google Cloud Messaging in Sept 2016), etc]. Implementing connection between them are cumbersome, and this is where Azure Notification Hub comes into play.
Architecture of Push Notifications with Azure:
Choosing Angular for the frontend was easy, especially since I wanted to try out Nebular, an Angular library with powerful components based on the Eva design system and in-built Auth & Security management. Angular 8 is now a stable release as well, so it was perfect for a production-ready website consuming a REST API.
Azure provides a notification hub that talks to each PNS, giving the developer only one service to talk to (ANH). The basic architecture remains as such, but instead of the server talking to each required PNS, it needs to talk only with ANH. This greatly reduces overhead.
How to, the steps at a glance:
- Create a Mobile App in Azure
- Add Notification Hub to Mobile App
- Register in PNS
- Configure backend to send notifications
-
Update client code
- Register device and subscribe to notifications
-
Update backend code
- Connect to Notification Hub
- Send notifications
1. Create a Mobile App in Azure
Straightforward. Refer Azure docs if required.
2. Add Notification Hub to Mobile App
Refer Azure docs if required.
3. Register in PNS
Create an account in the required PNS, and keep note of some keys.
For FCM, create a new project, go to project settings, and under Cloud Messaging tab, keep note of the SENDER_ID and Server Key.
4. Configure back-end to send notifications
Again under push settings of the Mobile App in Azure, choose the PNS (GCM for Android), and add the Server Key noted earlier under API Key. This is to connect the ANH to the PNS, so messages can be sent from the server to the client app via the PNS.
Please note that each PNS defines different methods to connect to them.
5. Update code
In client/device, registering device and subscribing to notifications:
For Ionic/Cordova apps, two plugins should be added:
- cordova-plugin-ms-azure-mobile-apps This is to connect with the Azure Mobile App that was created to handle the backend part of the app.
- phonegap-plugin-push This plugin is now the defacto plugin used for push notifications in cordova.
First, connect app to PNS with phonegap-plugin-push.
Initialising the push notification plugin with the required data to connect to the PNS.
pushRegistration = PushNotification.init({ android: { senderID: 'SENDER_ID' }, ios: { alert: 'true', badge: 'true', sound: 'true' }, wns: {} });
Registering the app with the PNS:
pushRegistration.on('registration', function (data) { ... }
On successfule registration, a registrationId is obtained from the PNS (in case of Android).
Next, connect the app with the Azure Mobile app, with cordova-plugin-ms-azure-mobile-apps
var client = new WindowsAzure.MobileServiceClient('URL to mobile app');
After registration with PNS, add the app to ANH:
client.push.register('gcm', registrationId, { mytemplate: { body: { data: { message: "{$(messageParam)}" } } } });
For GCM, similar for others too. mytemplate defines the template of each push message.
To listen for push messages:
pushRegistration.on('notification', function (data, d2) { // push message will be in data.message });
Handling errors:
pushRegistration.on('error', handleErrorCallback);
Backend:
Test push notifications can now be sent to each registered device from ANH. The server code must be updated to send push notifications based on some triggers, which could be calling an API, or adding an entry to a DB table. This part includes connecting to ANH from the mobile app and using the connection established earlier with the PNS to send notification messages.
Refer here for more implementation details.
You can test push messages from the Portal, or from Visual Studio (if connected).
Disclaimer: Implementation details may change.
Issues encountered:
- There was a problem connecting the ANH to FCM, which is unexplained. Adding the Server Key to the GCM API Key in ANH resulted in a ‘Error updating notification hub message’. This got solved after a few hours on its own. UPDATE: This error occurs when CORS is force-enabled in the browser. A lot of Azure functions behave weirdly when CORS is enabled


Schedule for the T&T Course
Tu 05.03 [#01]
Citation Management and Academic Writing ITu 19.03 [#02]
“Off with the Interface!” Getting to know the command lineTu 26.03 [#03]
Version Control and CollaborationTu 02.04 [#04]
Citation Management and Academic Writing IITu 09.04 [#05]
Regular expressionsTu 30.04 [#06]
WebscrapingTu 07.05 [#07]
Text Markup [TEI XML], and how to remove it…Tu 14.05 [#08]
Structuring dataTu 21.05 [#09]
Georeferencing with QGISTu 28.05 [#10]
Text to Map (1/2)Tu 04.06 [#11]
Text to Map (2/2)Tu 18.06 [#12]
Topic modeling with R / PythonTu 25.06 [#13]
Social Network Analysis with Gephi
Detailed Schedule
Tu 05.03 [#01]
Citation Management and Academic Writing I
- Using Styles in MS Word
- Using Zotero for managing bibliography
Tu 19.03 [#02]
“Off with the Interface!” Getting to know the command line
Tu 26.03 [#03]
Version Control and Collaboration
Tu 02.04 [#04]
Citation Management and Academic Writing II
Tu 09.04 [#05]
Regular expressions
Tu 30.04 [#06]
Webscraping
Tu 07.05 [#07]
Text Markup [TEI XML], and how to remove it…
Tu 14.05 [#08]
Structuring data
Tu 21.05 [#09]
Georeferencing with QGIS
Tu 28.05 [#10]
Text to Map (1/2)
Tu 04.06 [#11]
Text to Map (2/2)
Tu 18.06 [#12]
Topic modeling with R / Python
- with R (but better with Python)
- Python: gensim (https://radimrehurek.com/gensim/intro.html)
Tu 25.06 [#13]
Social Network Analysis with Gephi
Schedule for the R Course
Some topics are foundational and are taught in the TNT Class
Tu 05.03 [#01]
IntroductionTu 19.03 [#02]
DataTu 26.03 [#03]
Tu 02.04 [#04]
Tu 09.04 [#05]
Tu 30.04 [#06]
Tu 07.05 [#07]
Tu 14.05 [#08]
Tu 21.05 [#09]
Tu 28.05 [#10]
Tu 04.06 [#11]
Tu 18.06 [#12]
Topic modeling with R- Those who did it last year in TNT, can do Python (in TNT class, or on their own)
Tu 25.06 [#13]
Project presentations
Detailed Schedule
Tu 05.03 [#01]
Introduction
- Installing
R
: https://cloud.r-project.org/ - Installing
RStudio
: https://www.rstudio.com/products/rstudio/download/ - Basic commands in
R
Tu 19.03 [#02]
Data
- Creating, Collection and Organinzing Data
- READING: Broman, Karl W., and Kara H. Woo. “Data Organization in Spreadsheets.” The American Statistician 72, no. 1 (January 2, 2018): 2–10. https://doi.org/10.1080/00031305.2017.1375989.
Tu 26.03 [#03]
Tu 02.04 [#04]
Tu 09.04 [#05]
Tu 30.04 [#06]
Tu 07.05 [#07]
Tu 14.05 [#08]
Tu 21.05 [#09]
Tu 28.05 [#10]
Tu 04.06 [#11]
Tu 18.06 [#12]
Tu 25.06 [#13]
Topics to cover:
- R basics:
- Basic intro;
- Interactive tutorial:
- Specific tools in R:
- RMarkdown
- Shiny
- ggplot2 and ggvis
- tidyverse
- Basic intro;
- topic modeling
- stylometry
Materials and Datasets
- Library of Congress:
- [DATA] 25 mln book records: http://www.loc.gov/cds/products/MDSConnect-books_all.html
- Miriam Posner (UCLA):
- [DATA] collection of datasets: http://miriamposner.com/classes/dh201w19/final-project/datasets/
- class materials: http://miriamposner.com/classes/dh201w19/
- Lincoln Mullen (Geprge Mason U):
- [DATA]
historydata
R-package: https://lincolnmullen.com/software/historydata/ - Computational Historical Thinking, https://dh-r.lincolnmullen.com/
- [DATA]
- Paul Vierthaler:
- Lecture slides, https://github.com/vierth/hth2018Lectures
Notes
- Kieran Healy’s “Data Visualization: A Practical Guide”, http://socviz.co/
- Jupiter notebooks can be converted to markdown with
jupyter nbconvert *.ipynb --to markdown
, where*.ipynb
is the name of the jupyter notebook file. Then the notebook can be published as a blogpost with Jekyll. - Rmarkdown:
- RStudio:


--- layout: post authors: ["Greg Wilson"] title: "GSoC Projects for 2014" date: 2014-04-22 time: "09:00:00" tags: ["Announcements"] ---
We're very pleased to announce that two students will be working on Google Summer of Code projects we put forward, and that one of our regular contributors has received a GSoC as well. The projects are:
| Student | Project | Mentor | Links |
|---|---|---|---|
| Piotr Banaszkiewicz | Peer Instruction on the Web | Mike Hoye | Blog post, full proposal, repository. |
| Gabriel Ivanica | Browsercast: a Web-Based Slideshow Replay Tool | Greg Wilson | Blog post. |
| Raniere Silva | Math Virtual Keyboard | Salvador de la Puente González | Blog post. |
It's going to be an exciting summer...


Building Operating System User Interface (BOS UI)
Role: Resident
Please use the following account information to login BOS UI as an administrator and then click the button NEXT to get into tasks.
Username: resident
Password: resident
next
P.S.: Each task has a time limit. When the time is up, it will automatically jump to the next task.
If you finish the task before the end of time, please click the button NEXT to continue the next task.