.. include:: /../common/authors.txt
Omnia Foundation Documentation¶
Note
This documentation is a work in progress and contributions can be made on our Github repo
Topics¶
.. include:: /../common/authors.txt
Getting Started¶
1. Install Visual Studio 2017¶
Download and install Visual Studio 2017 (not Community edition)
2. Install Node JS¶
Download and install Node JS from https://nodejs.org/ . Choose the latest Current version. (Tested with version 8.5.0)
Or, if you have the need for running different versions of nodejs, for various projects. NVM (Node Version Manager) for windows is recomended, it allows for easy switching between nodejs versions. It can be found at https://github.com/coreybutler/nvm-windows You will need to uninstall nodejs if you already have it, instructions are on the repo.
3. Install Office Developer Tools¶
Download and install Office Developer Tools from https://www.visualstudio.com/vs/office-tools/
4. Configure Precio Fishbone NuGet package source in Visual Studio¶
Precio Fishbone NuGet package source is needed for download Omnia NuGet packages. To configure Precio Fishbone NuGet package source, follow these steps:
- In Visual Studio, navigate to Tools > NuGet Packages Manager > Packages Manager Settings
- In the Options dialog, select Package Sources in the left pane
- Add a new package source named Precio Fishbone with this URL http://nuget.preciofishbone.se/api/v2

5. Install Omnia Tooling for Visual Studio¶
Download and install Omnia Tooling for Visual Studio
6. Create new project with Omnia Extension project template¶
Note
- Omnia Documentation - Project template for creating an Omnia documentation package
- Omnia Extension - Project template for creating an Omnia extension package
Select the Omnia Extension template and name your project. Click OK.
The following screen opens
The first section is where you enter metadata about your extension. Normally there is no need to change these two values
The second section exists to help you configure the communication beween your development environment and your Omnia tenant
- Tenant Id is found in Omnia Admin in your tenant, in the Settings section (see image below)
- Foundation Url is also found in Omnia Admin, in the Settings section (see image below)
- Api Secret. This secret is recieved from Omnia by navigating to Omnia Admin > System > Extensions > Register Extension and paste in your Extension Id (from the Visual Studio dialog)


The third section’s purpose is there to help you target the correct API version, both in Omnia and SharePoint

The Foundation API version used in your tenant can be found in Omnia Admin > System, in the Developer Information section
The right hand side of the dialog determines the structure and files that will be created in the Extension projects
- The Extension Package checkbox controls if an Omnia Extension project is created in the solution
- The Web API checkbox controls if a Web API project, prepared to communicate with Omnia is created in the solution
The Extension Package checkbox has some child items that can be selected
- The Client Side checkbox determines if the project structure and files for doing client side development should be added to the solution
- The Angular Tooling checkbox makes sure the relevant files and tooling support for Angular development is added
- The Less Tooling checkbox makes sure the relevant files and tooling support for compiling Less files is added
- The Server Side checkbox determined if the project structure for doing server side development (like features, jobs etc.) is added to the project
- Below the Examples checkbox you can select different code examples to be provisioned to your project, to set you off to a quick start
- The Setup basic folder structure checkbox will add a best practice folder structure to your project
After filling in all the fields in the form, and selecting all the checkboxes, the following solution structure will be created

7. Alter the environment information in your project¶
(when changing tenant, or when passing the extension over to a fellow developer)
Open the file environment.json in MyOmniaExtension and fill in:
- TenantId: you get this from the System page in Omnia admin
- ApiSecret: the secret you got when you registered your extension in step 6
- FoundationUrl: you get this from the System page in Omnia admin

9. Deploy your extension¶
Right click on Extension project (DevelopDocumentation) and click Omnia Deploy

You can see the deployment progress in the Output window in Visual Studio

10. Verify¶
After the extension has been deployed successfully to Omnia, you can verify it by navigating to System > Extension in Omnia admin

And in the Features page you should see the features from your extension.
Congratulations, you are now ready to build your magical Omnia extension!
.. include:: /../common/authors.txt
Omnia Foundation Fundamentals¶
Note
This documentation is a work in progress and contributions can be made on our Github repo
Topics¶
.. include:: /../common/authors.txt
Omnia Extension Package¶
Omnia Foundation is built with extensibility in mind since day one and an Omnia Extension Package is the main way to extend Omnia. This article will give an overview of what you can achieve with extension packages and the basic structure of an extension package. For a more practical guide on how to start developing Omnia extensions see the Getting Started guide.
What is an Omnia Extension Package?¶
An Omnia extension package is a pack of features or extensions for Omnia. You can think of it like SharePoint solution packages but for the Omnia platform. An extension can be used to deploy all kinds of new features, from small UI changes to non-trivia applications with its own back-end and database. Examples are Omnia Intranet and Omnia Documentation Management.

At the core of an extension package are resource files. Resource files can be anything from client-side code like JavaScript, CSS, HTML templates to SharePoint artifacts like page layouts and web parts. These resources are mapped and deployed by logical containers called Omnia feature.
For example, the resources in a large extension might looks like this

An extension package can also contain Omnia jobs, pieces of code that will run as scheduled tasks in Omnia, and provisioning pipelines, pieces of code that will be hooked into the site provisioning pipeline of Omnia.
Manage extension packages¶
All extension packages in a tenant can be managed in Omnia admin, System > Extensions

New extensions can be uploaded directly from this UI by drag and drop or from Visual Studio using Omnia Tooling. An extension need to be registered before it can be uploaded, see the Getting Started guide for more details.
In this UI you can also manage configurations for each extension by clicking on the extension name

When a new version of an extension package has been deployed, all the new changes will not be available for users until the features of that extension are upgraded to the latest version.
.. include:: /../common/authors.txt
Omnia Feature¶
Omnia features are modules containing customizations for Omnia. They are very similar to SharePoint features, except that they can provisioning resources to both SharePoint and to Omnia database. An Omnia feature can also run your custom code when they are activated, upgraded or removed.
Sections:
Feature scopes¶
A feature will have one of the three scopes Site, SiteCollection and Tenant, each scope can deploy different types of artifacts.
Scope | Artifacts | SharePoint ClientContext |
---|---|---|
Site |
|
App-only context of the
target site
|
SiteCollection |
|
App-only context of the
root site of the target
site collection
|
Tenant |
|
Not available
|
Built-in methods and properties¶
Properties | Type | Description |
---|---|---|
Ctx | ClientContext | App-only client context for the targeting site.
This property is not available in tenant scope features.
|
Methods | Type | Description |
---|---|---|
CreateContextFor(string spUrl) | ClientContext | Create a new app-only context for another site
|
Log(string log) | void | Add a new entry to this feature’s logs
|
WorkWith() | ApiFactory | Return the ApiFactory that can call Omnia API
Example: WorkWith().Logging().AddLog(log)
|
Localize(string localizeKey) | string | Return the localized string
|
Create new feature¶
As usual, you can create new Omnia feature using the template from Omnia tooling

At the top of the feature is the FeatureDefinition attribute which contains the feature’s metadata
[FeatureDefinition(
id: "85544C6C-9EB9-4F99-9410-95F1EA3D07B5",
name: "MyOmniaExtension Sample Feature Core",
version: "0.1.0",
scope: FeatureScopes.Tenant
)]
public class SampleFeatureCore : Omnia.Foundation.Extensibility.Features.OmniaFeature
Feature activation, deactivation and upgrade¶
In a feature you can override the activation, decativation or upgrade events to run custom code. In these events, you can:
- Write CSOM code to work with data in SharePoint (except for Tenant scope features where the ClientContext is not available)
- Call the API of Omnia Foundation like logging and configurations using the built-in method WorkWith
- Trigger queue jobs using Omnia Queues API
Example: Provisioning new start page for the target site when activating the feature
/// <summary>
/// Activates the feature
/// </summary>
public override void Activate()
{
try
{
string pageTitle = this.Localize("$Localize:MyOmniaExtension.StartPageTitle;");
var publishingClient = this.WorkWith().Publishing(this.Ctx);
publishingClient.CreateStartPage(new Page
{
Name = "StartPage.aspx",
PageLayout = MyOmniaExtension.PageLayouts.StartPage,
Title = pageTitle
});
}
catch (Exception ex)
{
this.Log("Activate feature", ex.Message, FeatureInstanceLogTypes.Error);
throw;
}
}
/// <summary>
/// Deactivates the feature.
/// </summary>
/// <param name="fromVersion">From version.</param>
public override void Deactivate(string fromVersion)
{
// Your code to handle feature deactivation here
}
/// <summary>
/// Upgrades the feature
/// </summary>
/// <param name="fromVersion">From version.</param>
public override void Upgrade(string fromVersion)
{
// Your code to handle feature upgrade here
}
Provisioning tenant resources¶
By overriding the method OnTenantResourceMappings, a feature can provision tenant resources to Omnia database.
For code resources like JavaScript and CSS, you will also need to add them to a bundle for them to be loaded and executed on SharePoint or Omnia admin application. Read more on bundling in Omnia.
Note
Only tenant-scope features can provision tenant resources, though any features can add resources to bundles.
Example
/// <summary>
/// Called when [OmniaFeature resource mappings is being performed].
/// </summary>
/// <param name="resourceMapper">The resource mapper.</param>
public override void OnTenantResourceMappings(TenantResourcesMapper resourceMapper)
{
// Provisioning tenant resources to Omnia database
// NOTE: Only tenant-scope features can provision tenant resources
resourceMapper
.AddOrUpdateTenantResourcesFrom<ResourcesMapping>();
// Adding resources to the scope's bundles, in this case tenant.js and tenant.css
resourceMapper
.CreateBundleFor(BundleTargets.SharePoint)
.Include<ResourcesMapping.Scripts.Core>()
.Include<ResourcesMapping.Scripts.Services>()
.Include<ResourcesMapping.Scripts.Directives>()
.Include<ResourcesMapping.Scripts.Controls>()
.Include<ResourcesMapping.Styles>();
resourceMapper
.CreateBundleFor(BundleTargets.OmniaAdmin)
.Include<ResourcesMapping.Scripts.Core>()
.Include<ResourcesMapping.Scripts.Services>()
.Include<ResourcesMapping.Scripts.Directives>()
.Include<ResourcesMapping.Scripts.AdminSettings>(q => q.SampleAdminSettingsFormJs)
.Include<ResourcesMapping.Scripts.AdminSettings>(q => q.SampleAdminSettingsJs)
.Include<ResourcesMapping.Scripts.AdminSettings>();
}
.. include:: /../common/authors.txt
Resource Mappings¶
In an Omnia extension, every resource files need to be mapped with a unique ID. The resource mappings are defined with an attribute-based pattern like other entities in Omnia like feature, jobs and SharePoint artifacts.

The resource mappings aslo help create an logical hierachy or grouping of resources, which can be used to distribute the resources to different Omnia features. If your extension is small (less than 50 resource files) you should put all resource mappings into one file, otherwise you should split it into multiple files by feature area.
In the resource mappings you can also specify different properties and metadata.
Sections:
Folders mapping¶
[TenantResourceFolderMapping(id: "EE2FFD07-D5B6-4964-BD46-09472229F49C", name: "Scripts")]
public class Scripts
{
// Other folders or files mapping code in here
}
Generic files mapping¶
[TenantResourceFileMapping(id: "DC37115E-9ED7-4017-BCA1-449C67D8EBC0",
sourceRelativePath: "/TenantResources/Scripts/Core/sample.core.js")]
public string SampleCoreJs { get; set; }
Site templates mapping¶
[TenantResourceFileMapping(id: "AA5A09DA-CA8D-4289-9EF2-D05AE99E4AB2",
sourceRelativePath: "/TenantResources/SiteTemplates/sampletemplate.json",
Category = BuiltInCategories.SiteProvisioning.SiteTemplate)]
public string SampleTemplate { get; set; }
Localization files mapping¶
[TenantResourceFileMapping(id: "766F18D7-1E6B-486D-912B-C12D6683B28A",
sourceRelativePath: "/TenantResources/Localization/sample.loc.json")]
public string SampleLocalization { get; set; }
[TenantResourceFileMapping(id: "0CD92A43-9065-49DC-83EB-054123445A9E",
sourceRelativePath: "/TenantResources/Localization/sample.loc.sv-se.json")]
public string SampleLocalizationSvSe { get; set; }
.. include:: /../common/authors.txt
Localization¶
Omnia Foundation has a powerful localization engine that is using localization strings stored in JSON. By usin json which is a language neutral format we can use it both server-side and client-side.
Sections:
Creating localization files¶
You can create new localization file using the template from Omnia toolings

Note
- Public Localization - Used to store localization strings for UI in SharePoint
- Admin Localization - Used to store localization strings for UI in Omnia admin app
Each localization file contains the localization strings for only one language, and it need to follow this naming convention:
- *.loc.json for default language (English) localization. Example: sample.loc.json
- *.loc.[culture code].json for other langauge localization. Example: sample.loc.sv-se.json
Most of the cases, localization files with the same name but different culture code should contain the same JSON structure with different string values.
Note
The first level of the JSON will aways be “Public” or “Admin” depend on the localization target. You do not need to include “Public” or “Admin” part when getting localized strings.
sample.loc.json
{
"Public": {
"MyOmniaExtension": {
"Sample": {
"SiteCollection": "Site Collection",
"Site": "Site"
}
}
}
}
sample.loc.sv-se.json
{
"Public": {
"MyOmniaExtension": {
"Sample": {
"SiteCollection": "Webbplatssamling",
"Site": "Webbplats"
}
}
}
}
Localization in client-side code¶
Once the localization resources have been deployed, your client-side code can get the localized strings in three ways:
- Using the global variable $localize. This should only be used if you are writing non-Angular code. For Angular code you should use the other ways for better support.
- Using the filter omfLocalization for Angular
<span ng-bind="'MyOmniaExtension.Sample.SiteCollection' | omfLocalization">
- Using the service localizationService for Angular
constructor(private $scope: ISystemLogScope,
private localizationService: Omnia.Foundation.Services.LocalizationService) {
this.init();
}
private init = () => {
this.$scope.logTypes = new Array<Log>();
this.$scope.logTypes.push({
source: this.localizationService.getText("System.SystemLogs.LogTypes.Info"),
logType: LogTypes.Info
});
this.$scope.logTypes.push({
source: this.localizationService.getText("System.SystemLogs.LogTypes.Warning"),
logType: LogTypes.Warning
});
this.$scope.logTypes.push({
source: this.localizationService.getText("System.SystemLogs.LogTypes.Error"),
logType: LogTypes.Error
});
}
Localization in server-side code¶
Server-side code can also use localized strings. Typical examples are localized email content in Omnia timer jobs and localized title of SharePoint fields and content types.
Note
Currently the title of Omnia features cannot be localized. This may become possible in future version.
Example: Localized SharePoint content type
[ContentType(id: "78FBA358-10D6-459A-ABD9-6E1539EFF8C0",
name: "$Localize:MyOmniaExtension.Sample.ContentTypes.SampleContentType.Name;",
Group = "Sample Content Type Group",
Description = "$Localize:MyOmniaExtension.Sample.ContentTypes.SampleContentType.Description;")]
public class SampleContentType : Omnia.Foundation.Extensibility.ContentTypes.BuiltIn.Item
{
[FieldRef(typeof(SampleField))]
public string SampleField { get; set; }
}
Example: Get localized strings in timer jobs
public void SampleJobTimer([TimerTrigger("01:00:00")] TimerInfo timerInfo)
{
try
{
string language = "en-US";
string[] localizationKeys = new string[] {
"$Localize:MyOmniaExtension.Sample.EmailSubject;",
"$Localize:MyOmniaExtension.Sample.EmailContent;" };
ILocalizationService localizationService = WorkWith().Localization();
Dictionary<string, string> localizationsResult =
localizationService.GetLocalization(localizationKeys, language);
string localizedEmailSubject = "";
localizationResult.TryGetValue(localizationKeys[0], out localizedEmailSubject);
string localizedEmailContent = "";
localizationResult.TryGetValue(localizationKeys[1], out localizedEmailContent);
}
catch (Exception ex)
{
WorkWith().Logging().AddLog("SampleJobTimer", ex.Message, DefaultLogTypes.Error, ex);
}
}
Override localization in the Omnia admin app¶
End users can change the localized strings using the Omnia admin app at System > Localization
Note
Once a localized string has been changed in the admin app it will not be updated when a newer version of extension package is deployed. To make get the latest version of the localization users need to undo the customization. On the otherhand, when an extension package is removed all customization will also be removed.

.. include:: /../common/authors.txt
Permissions¶
Omnia permission roles¶
Omnia permission roles are security groups for managing access rights to Omnia resources. Permission roles can also be used to limit the access to the API of Omnia extensions. An Omnia permission role can be assign to a user or a security group in Office 365 and can be apply to site, site collection or tenant scope.
Create form for managing permission roles in Omnia extension¶
Omnia toolings provides a template for managing permission roles in admin app for each feature

The permission settings page is the same as any other admin app settings page in an Omnia extensions. The first notable part is the navigationNode. In the navigationNode, along with other metadata, you need to specify the authorizedRoles: the permission roles that can access this page and manage other permission roles. Usually, the authorizedRoles for permission settings pages are set to the OmniaAdmin.
static navigationNode: NavigationNode = {
title: "",
state: "AdminSettingsPermissionsPagePermissions",
url: "permission",
controller: AdminSettingsPermissionsPagePermissionsController.ngName,
viewId: "",
iconClass: "fa-key",
authorizedRoles: [
{
name: Omnia.Foundation.Security.PermissionRoles.OmniaAdmin,
scope: Omnia.Foundation.Security.PermissionScopes.Tenant
}
]
};
You will need to register this navigationNode to the navigation system of admin app. For more information about this read the article admin settings pages.
var node: NavigationNode = SampleSettings.SampleSettingsController.navigationNode;
if (node.children == null)
node.children = [];
node.children.push(SampleSettings.AdminSettingsPermissionsPagePermissionsController.navigationNode);
$admin.Navigation.addNode(NavigationScope.tenant, node);
The last and most important part is the roleDefinitionList property on $scope where you define all permission roles that can be managed on this page.
private init = () => {
this.$scope.roleDefinitionList = [
{
name: "AdminSettingsPermissionsPage.Admin",
scope: PermissionScopes.Tenant,
label: "AdminSettingsPermissionsPage.Permissions.Admin.Label",
description: "AdminSettingsPermissionsPage.Permissions.Admin.Description"
}
];
}
Deploy the extension and the permissions settings should be available

Secured extension API¶
The API of extensions can limit the access to certain endpoints by using the RequiredPermissionRoles attribute
[HttpGet]
[Route("api/settings")]
[RequiredPermissionRoles(""AdminSettingsPermissionsPage.Admin"",
PermissionScopes.Tenant)]
public ApiOperationResult<Settings> GetSettings()
{ }
.. include:: /../common/authors.txt
Configuration¶
Omnia configuration API provides a key-value storage that can be accessed from both server-side and client-side code.
A configuration can have the following properties:
Property | Type | Description |
---|---|---|
Name | String | Name of the configuration (case-insensitive)
|
Region | String | Group or category of the configuration (case-insensitive)
|
ExtensionPackageId | Guid | ID of the extension package that the configuration
belongs to
|
Value | String | Value of the configuration
|
UIEditable | Boolean | Specify whether the configuration is editable in
Omnia admin app
|
IncludedInClient | Boolean | Specify whether the configuration should be included
in the client-side context in
_omniaContextInfo.customConfigurations
|
A configuration “key” is the unique combination of its name, region and extension ID. Configuration value is string-based so it can be anything from plain string to URL or JSON.
Configuration API for server-side code¶
Note
To use Omnia configuration API in server-side code you need to install the NuGet package Omnia.Foundation.Extensibility.Core to you project.
In server-side code, the configuration API can be called by using OmniaApi factory
IConfigurationService configurationService = OmniaApi.WorkWith(tenantId).Configurations();
When working with configuration API, you can specify the extension ID that the configuration belongs to, or you can omit it. When omitted, the extension package ID will be read from the app setting Omnia.Foundation.Settings.ExtensionId of the current app domain.
Example: Get a single configuration by name and region
// Get a built-in configuration from Omnia Foundation
OmniaApi.WorkWith(tenantId).Configurations().GetConfiguration(
name: "configuration-name",
region: "configuration-region",
extensionPackageId: Extensibility.Core.Constants.Extensions.BuiltInExtensionPackageId);
// Get a configuration from your extension. When omitted, the extension package ID will be read
// from the app setting 'Omnia.Foundation.Settings.ExtensionId' of the current app domain
OmniaApi.WorkWith(tenantId).Configurations().GetConfiguration(
name: "configuration-name",
region: "configuration-region");
// Get a configuration from another extension.
OmniaApi.WorkWith(tenantId).Configurations().GetConfiguration(
name: "configuration-name",
region: "configuration-region",
extensionPackageId: "extension-id");
Example: Get all configurations in a region
OmniaApi.WorkWith(tenantId).Configurations().GetConfigurationsInRegion(
name: "configuration-region",
extensionPackageId: "extension-id");
Example: Add or update a configuration
MyModel myModel = new MyModel();
OmniaApi.WorkWith(tenantId).Configurations().AddOrUpdateConfiguration(
name: "configuration-name",
value: JsonConvert.SerializeObject(myModel),
region: "configuration-region",
includedInClient: false,
uiEditable: false,
extensionPackageId: "extension-id");
Example: Delete a configuration
OmniaApi.WorkWith(tenantId).Configurations().DeleteConfiguration(
name: "configuration-name",
region: "configuration-region",
extensionPackageId: "extension-id");
Configuration for extension¶
You can automatically set the configurations for your extension when it is deployed by specifying those configurations in the extension.json file
{
"Id": "3847fb18-8cb7-4597-83d8-6bcb7136ce7a",
"Title": "MyOmniaExtension",
"Description": "",
"Version": "1.0.0",
"PackageName": null,
"TenantResourceFolders": [
"TenantResources"
],
"Configurations": [
{
"Name": "MyWebApiUrl",
"Region": "MyOmniaExtension",
"IncludedInClient": true,
"UIEditable": true,
"Required": true,
"DefaultValue": "https://localhost:44300/api/"
},
{
"Name": "TermSetId",
"Region": "MyOmniaExtension",
"IncludedInClient": true,
"UIEditable": true,
"Required": true,
"DefaultValue": "888F3B90-9A90-4F77-B64D-305EFF1EB3D5"
}
]
}
Configuration default values will be used when the extension package is deployed the first time from Visual Studio. When the package is uploaded from Omnia admin app user will need to fill in the configuration values.

.. include:: /../common/authors.txt
Bundling¶
Bundling is the process of concatinate multiple files into a single file. In web development, bundling can increase performance significantly, especially in high latency networks, by reducing the number of requests and round trips to the server.
In Omnia feature you can specify which JavaScript and CSS resources to be bundled and which application the bundle is targeted for (more on this in bundle targets section). When that feature is activated, those resources will be add to the bundle corresponding to the feature’s scope and the target application.
Creating bundles¶
To bundle resources, override the method OnTenantResourceMappings in your Omnia feature and use the method CreateBundleFor of the resourceMapper.
public override void OnTenantResourceMappings(TenantResourcesMapper resourceMapper)
{
resourceMapper
.CreateBundleFor(Models.Features.BundleTargets.SharePoint)
.Include<ResourcesMapping.Core>()
.Include<ResourcesMapping.Services>(q => q.AjaxService)
.Include<ResourcesMapping.Services>();
}
You can add specific file from the resources mapping
.Include<ResourcesMapping.Services>(q => q.AjaxService)
Or you can add a whole folder and the resourceMapper will recursively include every files in that folder. The resource mapper will be smart enough to not include a file again if it is already in the bundle
.Include<ResourcesMapping.Services>(q => q.AjaxService)
.Include<ResourcesMapping.Services>()
The resources will be bundled in the same order as they were included here. In this example, the resources will be bundled in the following order:
- All the files (recursively including child folders) in Core folder
- The ajaxService file in Services folder
- All the files in Services folder (recursively including child folders) except for ajaxService
Bundle scopes¶
There are 3 bundle scopes: Tenant, Site Collection and Site. These scopes map with Omnia feature scopes, meaning an tenant-scope feature can only add resources to the tenant-scope bundle, etc.
On each Omnia page load (in SharePoint or in admin web), these 6 bundle files that will be loaded:
Scope | Bundle | Content |
---|---|---|
Site |
|
All resources bundled by site-scope features
activated on the current site
|
SiteCollection |
|
All resources bundled by sitecollection-scope features
activated on the current site collection
|
Tenant |
|
All resources bundled by activated tenant-scope
features
|
Bundle targets¶
Currently there are only two bundle targets, SharePoint and OmniaAdmin. As the names imply, resources bundles targeting SharePoint will only be loaded in SharePoint and the resources bundle targeting OmniaAdmin will only be loaded in Omnia admin web.
A general guideline on bundle targets would be:
- JavaScript services and directives usually can target both SharePoint and Omnia Admin.
- Omnia controls should only target SharePoint.
- Admin settings should only target OmniaAdmin.
public override void OnTenantResourceMappings(TenantResourcesMapper resourceMapper)
{
resourceMapper
.AddOrUpdateTenantResourcesFrom<TenantResources>();
resourceMapper
.CreateBundleFor(Models.Features.BundleTargets.SharePoint)
.Include<ResourcesMapping.Enums>()
.Include<ResourcesMapping.Core>()
.Include<ResourcesMapping.Services>()
.Include<ResourcesMapping.Directives>()
.Include<ResourcesMapping.Styles>();
resourceMapper
.CreateBundleFor(Models.Features.BundleTargets.OmniaAdmin)
.Include<ResourcesMapping.Enums>()
.Include<ResourcesMapping.Core>()
.Include<ResourcesMapping.Services>()
.Include<ResourcesMapping.Directives>()
.Include<ResourcesMapping.Styles>()
.Include<ResourcesMapping.AdminSettings.Controllers>()
.Include<ResourcesMapping.AdminSettings>();
}
Bundle sequence number¶
While you can specify the order of resources in your feature just by order they were included, sometimes you will also need to ensure the resources of one feature is loaded before the resources of other features. For that purpose you can set the sequence number for your feature bundle:
public override void OnTenantResourceMappings(TenantResourcesMapper resourceMapper)
{
resourceMapper
.AddOrUpdateTenantResourcesFrom<TenantResources>();
resourceMapper
.CreateBundleFor(Models.Features.BundleTargets.SharePoint)
.Include<ResourcesMapping.Enums>()
.Include<ResourcesMapping.Core>()
.Include<ResourcesMapping.Services>()
.Include<ResourcesMapping.Directives>()
.Include<ResourcesMapping.Styles>();
resourceMapper
.CreateBundleFor(Models.Features.BundleTargets.OmniaAdmin)
.Include<ResourcesMapping.Enums>()
.Include<ResourcesMapping.Core>()
.Include<ResourcesMapping.Services>()
.Include<ResourcesMapping.Directives>()
.Include<ResourcesMapping.Styles>()
.Include<ResourcesMapping.AdminSettings.Controllers>()
.Include<ResourcesMapping.AdminSettings>();
resourceMapper
.SetBundlesSequence(90000, Models.Features.BundleTargets.SharePoint)
.SetBundlesSequence(80000, Models.Features.BundleTargets.OmniaAdmin);
}
The bundle with lower sequence number will be included first in the bundle. The default sequence number is 100000. You should not set the sequence number to lower than 100 because the sequence numbers from 0 to 100 are reserved for core features of Omnia Foundation.
Also, from the example you can see that the sequence number can be different for bundling targets.
Bundle minification¶
In non-development environments, all JavaScript bundles will be minified to reduce the size of the bundles and further improve performance. However, this sometimes can cause issues if the code was not written in a way that is compatible with minification. If you have errors happened only in non-development environments and you suspect it could be from the minification, use the querystring parameter “debug=true” to un-minify your code.
One common issue with minification is Angular dependencies injection. For example, this code will not work when minified
var app = angular.module('bigApp', []);
app.controller('mainController', function($scope) {
$scope.message = 'OH NO!';
});
But this will code will
var app = angular.module('bigApp', []);
app.controller('mainController', ['$scope', function($scope) {
$scope.message = 'HOORAY!';
}]);
To understand why the second code block works with minification while the first does not, read this article.
.. include:: /../common/authors.txt
Logging¶
Omnia provides a logging API for extensions to write logs to Omnia Foundation’s logs database. There are three different types of logs in Omnia: System Logs, Queue Logs and Feature Logs.
System Logs is a general-purpose place for information or error logs from both Omnia Foundation and extensions. System Logs can be viewed in Omnia admin app at System > Logs

Queue Logs contains logs from queue messages jobs. For errors related to long-running operations like uploading extension packages or creating site collection, check the Queue Logs. Queue Logs can be viewed in Omnia admin app at System > Queues

The last type of logs is Feature Logs, which contains logs from custom code in feature activation, upgrade or deactivation. Feature Logs can be viewed in the feature detail page.

Logging in extension Web API¶
In extension API that inherit from SharePointContextProvidedController you can use the built-in Logging service to write to the System Logs.
[HttpGet]
[Route("api/documents")]
public ApiOperationResult<IEnumerable<Document>> GetDocuments()
{
try
{
// Web API code here
}
catch (Exception ex)
{
// The built-in Logging service can be used to write to System Logs
this
.Logging
.AddLog(this.GetType().ToString(), ex.Message, DefaultLogTypes.Error, ex);
return ApiUtils.CreateErrorResult<IEnumerable<Document>>(ex);
}
}
For API that does not inherit from SharePointContextProvidedController, you can use OmniaApi factory to create the Logging service.
[HttpGet]
[Route("api/documents")]
public ApiOperationResult<IEnumerable<Document>> GetDocuments(
string tokenKey, string spUrl, string language)
{
try
{
// Web API code here
}
catch (Exception ex)
{
// For controller that does not inherit from SharePointContextProvidedController
// we need to create the ClientContext first.
ClientContext ctx = SharePointContextProvider
.CreateUserClientContext(tokenKey, spUrl, language);
OmniaApi
.WorkWith(Ctx.Omnia())
.Logging()
.AddLog(this.GetType().ToString(), ex.Message, DefaultLogTypes.Error, ex);
return ApiUtils.CreateErrorResult<IEnumerable<Document>>(ex);
}
}
Logging in extension features¶
In Omnia feature you can write to System Logs using OmniaApi factory or write to Feature Logs using the built-in Log method
[FeatureDefinition(
id: "85544C6C-9EB9-4F99-9410-95F1EA3D07B5",
name: "MyOmniaExtension Sample Feature Core",
version: "0.1.0",
scope: FeatureScopes.Tenant
)]
public class SampleFeatureCore : Omnia.Foundation.Extensibility.Features.OmniaFeature
{
/// <summary>
/// Activates the OmniaFeature
/// </summary>
public override void Activate()
{
// This will write to System Logs
this.WorkWith().Logging()
.AddLog("SampleFeatureCore", "Feature activation", DefaultLogTypes.Info);
// This will write to Feature Logs
this.Log("Feature activation", "Success", FeatureInstanceLogTypes.Information);
}
}
Logging in extension jobs¶
Similar to features, in jobs you can use the OmniaApi factory to write to System Logs. One important thing to note is that currently any uncachted error in queue job will be write to the Queue Logs, but for timer jobs you need to handle the error and explicitly write to the System Logs in your code.
public void SampleJobTimer([TimerTrigger("01:00:00")] TimerInfo timerInfo)
{
try
{
// Your job code here
}
catch (Exception ex)
{
WorkWith().Logging().AddLog("SampleJobTimer", ex.Message, DefaultLogTypes.Error, ex);
}
}
public void SampleJobQueue([QueueTrigger("SampleJob")] object queueMessage)
{
try
{
// Your job code here
}
catch (Exception ex)
{
WorkWith().Logging().AddLog("SampleJobQueue", ex.Message, DefaultLogTypes.Error, ex);
}
}
.. include:: /../common/authors.txt
.. include:: /../common/authors.txt
Omnia API¶
Omnia contains various API’s designed to simplify various tasks.
The API’s are located in the OmniaApi class in the Omnia.Foundation.Extensibility.Core namespace.
The basic C# code needed to begin working with the API’s from an Omnia Feature or a Custom Web API for Omnia extensions looks like below.
OmniaApi.WorkWith(Ctx.Omnia());
By adding a . after WorkWith(Ctx.Omnia()) you will reach the available API services listed below. E.g.
OmniaApi.WorkWith(Ctx.Omnia()).Caching();
Services¶
.. include:: /../common/authors.txt
Caching¶
The Caching API makes it easy to work with object caching, either locally on one server or distributed to all servers in an Omnia server cluster (similar to Distributed Cache used in SharePoint).
You reach the Caching API through the following service
OmniaApi.WorkWith(Ctx.Omnia()).Caching();
The API contains the following methods:
AddOrUpdateMemoryCache¶
Adds or updates an already existing object in the memory cache
void OmniaApi.WorkWith(Ctx.Omnia()).Caching().AddOrUpdateMemoryCache(string key, object value);
Optionally you can supply an expiration time as a DateTimeOffset
void OmniaApi.WorkWith(Ctx.Omnia()).Caching().AddOrUpdateMemoryCache(string key, object value, DateTimeOffset expires);
GetFromMemoryCache¶
Gets an object from the memory cached by suppling the key the object was stored with
object OmniaApi.WorkWith(Ctx.Omnia()).Caching().GetFromMemoryCache(string key);
GetFromMemoryCache<T>¶
Gets an object from the memory cached by suppling the key the object was stored with. Casts the object to the supplied type
T OmniaApi.WorkWith(Ctx.Omnia()).Caching().GetFromMemoryCache<T>(string key);
MemoryCacheContains¶
Checks if an object with the given key is present in the memory cache
bool OmniaApi.WorkWith(Ctx.Omnia()).Caching().MemoryCacheContains(string key);
RemoveFromMemoryCache¶
Deletes the object with the given key from the memory cache
void OmniaApi.WorkWith(Ctx.Omnia()).Caching().RemoveFromMemoryCache(string key)
AddOrUpdateDistributedCache¶
Adds or updates an already existing object in the distributed cache
void OmniaApi.WorkWith(Ctx.Omnia()).Caching().AddOrUpdateDistributedCache(string key, object value, DateTimeOffset expires);
Optionally you can cache the data encrypted
void OmniaApi.WorkWith(Ctx.Omnia()).Caching().AddOrUpdateMemoryCache(string key, object value, bool encrypted, DateTimeOffset expires);
You can also cache multiple objects at once by creating a List<CachedItem> (CachedItem is found in the Omnia.Foundation.Extensibility.Core.Caching namespace
void OmniaApi.WorkWith(Ctx.Omnia()).Caching().AddOrUpdateDistributedCache(List<CachedItem> objectsToCache);
GetFromDistributedCache¶
Gets objects from the distributed cache by supplying a list of the keys the items are stored with
List<CachedItem> OmniaApi.WorkWith(Ctx.Omnia()).Caching().GetFromDistributedCache(List<string> keys);
GetFromDistributedCache<T>¶
Gets an object from the distributed cache, cast to the specified type
T OmniaApi.WorkWith(Ctx.Omnia()).Caching().GetFromDistributedCache<T>(string key);
RemoveFromDistributedCache¶
Deletes objects from the distributed cache by supplying a list of keys
void OmniaApi.WorkWith(Ctx.Omnia()).Caching().RemoveFromDistributedCache(List<string> keys);
.. include:: /../common/authors.txt
Configurations¶
The Configurations API allows you to read, store, update and delete configurations for you solution.
Use Configurations as a means for allowing certain values in your solution to be configurable, via code or from the Omnia Admin app, to make it more adaptable.
You reach the Configurations API through the following service
OmniaApi.WorkWith(Ctx.Omnia()).Configurations();
The API contains the following methods:
AddOrUpdateConfiguration¶
Adds a new configuration, or updates an existing one.
void OmniaApi.WorkWith(Ctx.Omnia()).Configurations()
.AddOrUpdateConfiguration(Configuration configuration);
You find the Configuration class in the Omnia.Foundation.Models.Configurations namespace
You can also add or update a configuration with the following overload
void OmniaApi.WorkWith(Ctx.Omnia()).Configurations()
.AddOrUpdateConfiguration(string key, dynamic value, [string region = ""], [bool includedInClient = false], [bool uiEditable = false], [string permissionRoles = ""]);
AddOrUpdateConfigurations¶
To add / update multiple configurations at once, use the following method
void OmniaApi.WorkWith(Ctx.Omnia()).Configurations()
.AddOrUpdateConfigurations(IEnumerable<Configuration> configurations);
You find the Configuration class in the Omnia.Foundation.Models.Configurations namespace
DeleteConfiguration¶
Deletes an existing configuration by passing the name and region of it.
void OmniaApi.WorkWith(Ctx.Omnia()).Configurations()
.DeleteConfiguration(string name, string region);
Optionally you can also pass in an extension id as the last parameter, to target configurations for a specific extension
void OmniaApi.WorkWith(Ctx.Omnia()).Configurations()
.DeleteConfiguration(string name, string region, [Guid? extensionPackageId = null]);
GetConfiguration¶
Gets a specific configuration by name and region.
Configuration OmniaApi.WorkWith(Ctx.Omnia()).Configurations()
.GetConfiguration(string name, string region);
Optionally you can also pass in an extension id as the last parameter, to target configurations for a specific extension
Configuration OmniaApi.WorkWith(Ctx.Omnia()).Configurations() .GetConfiguration(string name, string region, Guid? extensionPackageId = null]);
GetConfigurations¶
To get all existing configurations, use the following method
IEnumerable<Configuration> OmniaApi.WorkWith(Ctx.Omnia()).Configurations()
.GetConfigurations();
You can also scope this to only get configurations for a specific extension by supplying the Id of the solution
IEnumerable<Configuration> OmniaApi.WorkWith(Ctx.Omnia()).Configurations()
.GetConfigurations([Guid? extensionPackageId = null]);
To specify which configurations to get, use the following method
IEnumerable<Configuration> OmniaApi.WorkWith(Ctx.Omnia()).Configurations()
.GetConfigurations(List<string> names, string region);
Where you pass in the names and region of the configurations to retrieve.
GetConfigurationsInRegion¶
To get all configurations in a given region, use the following method
IEnumerable<Configuration> OmniaApi.WorkWith(Ctx.Omnia()).Configurations()
.GetConfigurationsInRegion(string region);
You can also scope this to only get configurations for a specific extension by supplying the Id of the solution
IEnumerable<Configuration> OmniaApi.WorkWith(Ctx.Omnia()).Configurations()
.GetConfigurationsInRegion(string region, [Guid? extensionPackageId = null]);
GetOmniaInstanceMode¶
In some scenarios you might need know if Omnia is running in Site collection or Tenant mode. To get this information, call the following method
OmniaInstanceModes OmniaApi.WorkWith(Ctx.Omnia()).Configurations()
.GetOmniaInstanceMode();
This will return a value from the enum Omnia.Foundation.Models.Shared.OmniaInstanceModes, either SiteCollection or Tenant
GetParentSiteConfigurations¶
Gets configurations from a specified parent site, based on the site URL and region of the configuration.
IEnumerable<Configuration> OmniaApi.WorkWith(Ctx.Omnia()).Configurations()
.GetParentSiteConfigurations(string fromSiteUrl, string region);
.. include:: /../common/authors.txt
Controls¶
The Controls API contains methods that makes it easier to work with Omnia Controls.
You reach the Controls API through the following service
OmniaApi.WorkWith(Ctx.Omnia()).Controls();
The API contains the following methods:
GetControlSettings¶
Use this method to get the stored settings for a given instance of an Omnia Control
string OmniaApi.WorkWith(Ctx.Omnia()).Controls()
.GetControlSettings(string scope, Guid controlId, string siteCollectionUrl, string siteUrl, int? pageItemId, Guid? featureResourceId);
Pass in the scope of the control (“masterpage”, “site”, “page” or “webpart”), the Guid of the control, the url of the site collection and site.
To target a control on a certain page pass the a item ID of the page.
You can also pass in the feature resource Id of your control.
.. include:: /../common/authors.txt
Email¶
The Email API allows you to send email from your solution.
You reach the Caching API through the following service
OmniaApi.WorkWith(Ctx.Omnia()).Email(Ctx);
The API contains the following methods:
SendEmail¶
Sends an email message
void OmniaApi.WorkWith(Ctx.Omnia()).Email(Ctx).SendEmail(string subject, string body, List<string> emailTo);
You can add multiple email addresses in the emailTo list
There is also two optional input parameters: emailCC and emailBcc, both of type List<string>.
- Add email addresses to emailCC to add them to the the carbone copies list of the email .
- Add email addresses to emailBCC to add them to the the blind carbone copies list of the email.
.. include:: /../common/authors.txt
Features¶
The Features API allows you to Activate, Deactivate and in other ways work with Omnia Features.
Note
This API works with Omnia Features, not SharePoint Features.
You reach the Features API through the following service
OmniaApi.WorkWith(Ctx.Omnia()).Features();
The API contains the following methods:
ActivateFeature¶
To activate an Omnia Feature, use the following method
FeatureInstance OmniaApi.WorkWith(Ctx.Omnia()).Features()
.ActivateFeature(Guid id, string spUrl, bool force);
Supply the unique Guid of the feature, the URL of the tenant authority / site collection / web where the feature should be activated. Set the force parameter to true to ignore errors on activation.
DeactivateFeature¶
To deactivate an Omnia Feature, use the following method
FeatureInstance OmniaApi.WorkWith(Ctx.Omnia()).Features()
.DeactivateFeature(Guid id, string spUrl);
Supply the unique Guid of the feature and the URL of the tenant authority / site collection / web where the feature should be deactivated.
GetFeature¶
To get more information about a specific feature, use the following method
FeatureModel OmniaApi.WorkWith(Ctx.Omnia()).Features()
.GetFeature(Guid id);
Supply the unique Guid of the feature. In return you get a Omnia.Foundation.Models.Features.FeatureInstance object containing feature details like Name, Description and Scope
GetFeatures¶
To get more information about a all existing features, use the following method
IEnumerable<FeatureModel> OmniaApi.WorkWith(Ctx.Omnia()).Features()
.GetFeatures();
GetFeatureActivationStatus¶
To check if a given feature is activated or not on a site / site collection / tenant, use the following method
FeatureInstanceStatus OmniaApi.WorkWith(Ctx.Omnia()).Features()
.GetFeatureActivationStatus(Guid id, string spUrl);
This will return a value from the Omnia.Foundation.Models.Features.FeatureInstanceStatus enumeration.
This can have any of the following values:
- NotActivated
- Activating
- Activated
- Upgrading
- Deactivating
- Error
GetFeatureInstanceLogs¶
To get the log messages written for a specific feature, use the following method
IEnumerable<FeatureInstanceLog> OmniaApi.WorkWith(Ctx.Omnia()).Features()
.GetFeatureInstanceLogs(Guid id, DateTimeOffset? startingBefore = default(DateTimeOffset?), int take = -1);
GetFeatureInstances¶
To get all instances of a feature (e.g. all places where a feature is activated), use the following method
IEnumerable<FeatureInstance> OmniaApi.WorkWith(Ctx.Omnia()).Features()
.GetFeatureInstances(Guid id);
This will return a collection of Omnia.Foundation.Models.Features.FeatureInstance, containing for example Status and Target of the feature
UpgradeFeature¶
To upgrade a feature on one target (Tenant / Site collection / Site), use the following method
FeatureInstance OmniaApi.WorkWith(Ctx.Omnia()).Features()
.UpgradeFeature(Guid id, string spUrl);
To upgrade features in multiple places at once, you can use the following method
Dictionary<string, ApiOperationResult> OmniaApi.WorkWith(Ctx.Omnia()).Features()
.UpgradeFeature(Guid id, List<string> spUrls);
This will update the feature in all of the instances specified by the list of URLs supplied in the spUrls parameter.
.. include:: /../common/authors.txt
Lists¶
The Lists API contains methods that makes it easier to work with lists and libraries in SharePoint.
You reach the Lists API through the following service
OmniaApi.WorkWith(Ctx.Omnia()).Lists(Ctx);
The API contains the following methods:
AddFileToList¶
Use this method to create a file in a library based on a supplied byte array containing the file data.
void OmniaApi.WorkWith(Ctx.Omnia()).Lists(Ctx)
.AddFileToList(Guid listId, string folderServerRelativeUrl, string fileName, byte[] data);
Pass in the GUID of the library, a server relative Url to a folder (or empty string to add in root folder) and a file name.
Optionally, you can also supply a boolean indicating if the file should be published or not
void OmniaApi.WorkWith(Ctx.Omnia()).Lists(Ctx)
.AddFileToList(Guid listId, string folderServerRelativeUrl, string fileName, byte[] data, bool publish);
GetAllDocumentLibraries¶
To get information about all document libraries on the current web, use the following method
IEnumerable<ListIdentifier> OmniaApi.WorkWith(Ctx.Omnia()).Lists(Ctx)
.GetAllDocumentLibraries();
The returned array contains ListIdentifier objects containing for example Title, Id and ListUrl for the document libraries.
GetAllImageLibraries¶
To get information about all image libraries on the current web, use the following method
IEnumerable<ListIdentifier> OmniaApi.WorkWith(Ctx.Omnia()).Lists(Ctx)
.GetAllImageLibraries();
The returned array contains ListIdentifier objects containing for example Title, Id and ListUrl for the image libraries.
GetDocuments¶
To get documents from a library, you can use the following method
IEnumerable<DocumentIdentifier> OmniaApi.WorkWith(Ctx.Omnia()).Lists(Ctx)
.GetDocuments(Guid listId, ListQuery listQuery, bool recursive = true, string folderServerRelativeUrl = "");
Supply a ListQuery object to filter the results.
To get a paged subset of the documents, you can instead use the following method
IEnumerable<DocumentIdentifier> OmniaApi.WorkWith(Ctx.Omnia()).Lists(Ctx)
GetDocuments(Guid listId, string searchString = null, int skipId = 0, int take = -1, string orderBy = null, bool ascending = true, bool isGetAbsoluteUrl = false);
Passing in a skipId decides from which item to start fetching, and take sets the number of documents to return. You can also supply orderBy and ascending parameters to decide the sort order.
The returned DocumentIdentifier class contains basic information about the documents in the library, for example Id, Title, FileName, DocumentUrl and more.
GetDocumentsByFolder¶
Much like the GetDocuments method, you can use this method to get a paged subset of documents, but in a specific folder
IEnumerable<DocumentIdentifier> OmniaApi.WorkWith(Ctx.Omnia()).Lists(Ctx)
GetDocumentsByFolder(Guid listId, string folderUrl, string searchString = null, int skipId = 0, int take = -1, string orderBy = null, bool ascending = true);
Pass in site relative folderUrl
GetListItems¶
Use this method to get list items from a list
IEnumerable<ListItem> OmniaApi.WorkWith(Ctx.Omnia()).Lists(Ctx)
.GetListItems(Guid listId, ListQuery listQuery);
Note that this returns the full ListItem objects. Use the listQuery parameter to filter what items are returned.
GetPageList¶
Note
Publishing webs only
To get the Pages list of the current web use one of the following methods
List OmniaApi.WorkWith(Ctx.Omnia()).Lists(Ctx)
.GetPageList(Web web, string webUrl);
or (to target a specific list)
List OmniaApi.WorkWith(Ctx.Omnia()).Lists(Ctx)
.GetPageList(Web web, string webUrl, string listId);
GetPageListId¶
Note
Publishing webs only
To get the Guid of the Pages library on a publishing web, use the following method
Guid OmniaApi.WorkWith(Ctx.Omnia()).Lists(Ctx)
GetPageListId(Web web, string webUrl);
GetPageListUrl¶
Note
Publishing webs only
To get the URL of the Pages library on a publishing web, use the following method
string OmniaApi.WorkWith(Ctx.Omnia()).Lists(Ctx)
GetPageListUrl(Web web, string webUrl);
.. include:: /../common/authors.txt
Logging¶
Omnia provides a logging API for extensions to write logs to Omnia Foundation’s logs database. There are three different types of logs in Omnia: System Logs, Queue Logs and Feature Logs.
System Logs is a general-purpose place for information or error logs from both Omnia Foundation and extensions. System Logs can be viewed in Omnia admin app at System > Logs

Queue Logs contains logs from queue messages jobs. For errors related to long-running operations like uploading extension packages or creating site collection, check the Queue Logs. Queue Logs can be viewed in Omnia admin app at System > Queues

The last type of logs is Feature Logs, which contains logs from custom code in feature activation, upgrade or deactivation. Feature Logs can be viewed in the feature detail page.

Logging in extension Web API¶
In extension API that inherit from SharePointContextProvidedController you can use the built-in Logging service to write to the System Logs.
[HttpGet]
[Route("api/documents")]
public ApiOperationResult<IEnumerable<Document>> GetDocuments()
{
try
{
// Web API code here
}
catch (Exception ex)
{
// The built-in Logging service can be used to write to System Logs
this
.Logging
.AddLog(this.GetType().ToString(), ex.Message, DefaultLogTypes.Error, ex);
return ApiUtils.CreateErrorResult<IEnumerable<Document>>(ex);
}
}
For API that does not inherit from SharePointContextProvidedController, you can use OmniaApi factory to create the Logging service.
[HttpGet]
[Route("api/documents")]
public ApiOperationResult<IEnumerable<Document>> GetDocuments(
string tokenKey, string spUrl, string language)
{
try
{
// Web API code here
}
catch (Exception ex)
{
// For controller that does not inherit from SharePointContextProvidedController
// we need to create the ClientContext first.
ClientContext ctx = SharePointContextProvider
.CreateUserClientContext(tokenKey, spUrl, language);
OmniaApi
.WorkWith(Ctx.Omnia())
.Logging()
.AddLog(this.GetType().ToString(), ex.Message, DefaultLogTypes.Error, ex);
return ApiUtils.CreateErrorResult<IEnumerable<Document>>(ex);
}
}
Logging in extension features¶
In Omnia feature you can write to System Logs using OmniaApi factory or write to Feature Logs using the built-in Log method
[FeatureDefinition(
id: "85544C6C-9EB9-4F99-9410-95F1EA3D07B5",
name: "MyOmniaExtension Sample Feature Core",
version: "0.1.0",
scope: FeatureScopes.Tenant
)]
public class SampleFeatureCore : Omnia.Foundation.Extensibility.Features.OmniaFeature
{
/// <summary>
/// Activates the OmniaFeature
/// </summary>
public override void Activate()
{
// This will write to System Logs
this.WorkWith().Logging()
.AddLog("SampleFeatureCore", "Feature activation", DefaultLogTypes.Info);
// This will write to Feature Logs
this.Log("Feature activation", "Success", FeatureInstanceLogTypes.Information);
}
}
Logging in extension jobs¶
Similar to features, in jobs you can use the OmniaApi factory to write to System Logs. One important thing to note is that currently any uncachted error in queue job will be write to the Queue Logs, but for timer jobs you need to handle the error and explicitly write to the System Logs in your code.
public void SampleJobTimer([TimerTrigger("01:00:00")] TimerInfo timerInfo)
{
try
{
// Your job code here
}
catch (Exception ex)
{
WorkWith().Logging().AddLog("SampleJobTimer", ex.Message, DefaultLogTypes.Error, ex);
}
}
public void SampleJobQueue([QueueTrigger("SampleJob")] object queueMessage)
{
try
{
// Your job code here
}
catch (Exception ex)
{
WorkWith().Logging().AddLog("SampleJobQueue", ex.Message, DefaultLogTypes.Error, ex);
}
}
.. include:: /../common/authors.txt
Security¶
Note
This is a draft version of the documentation, it is not yet complete. Feel free to contribute to it via GitHub.
The Security API allows you to work with permissions, both Omnia permissions and SharePoint permissions.
You can for example check if the current user has a certain permission on a web, or a certain role in Omnia.
You reach the Security API through the following service
OmniaApi.WorkWith(Ctx.Omnia()).Security(Ctx);
The API contains the following methods:
AddOrUpdateOmniaPermissionRoles¶
Documentation in progress
DeleteOmniaPermissionRolesForExtensionPackage¶
Documentation in progress
DoesUserHavePermissionOnWeb¶
Use this method to check if the user has the specified permission on the current web.
bool OmniaApi.WorkWith(Ctx.Omnia()).Security(Ctx)
.DoesUserHavePermissionOnWeb(PermissionKind permissionKind);
Returns true if the user has the supplied permissionKind, otherwise false.
GetAllOmniaPermissionRoles¶
Use this method to get all available Omnia Permission roles for a given URL.
IEnumerable<PermissionRole> OmniaApi.WorkWith(Ctx.Omnia()).Security(Ctx)
.GetAllOmniaPermissionRoles(string targetUrl);
Returns an array of PermissionRole for the given targetUrl.
GetCurrentUserADGroups¶
If you need to get all AD groups the current user is a member of, use the following end-point.
Note
Only AD groups used somewhere in Omnia Foundation will be returned, e.x. groups used for security in Omnia Administration or as part of targeting definitions.
IEnumerable<string> OmniaApi.WorkWith(Ctx.Omnia()).Security(Ctx)
.GetCurrentUserADGroups(string[] groups);
If you supply and empty groups parameter, you will get all AD groups, used somewhere in Omnia, that the user is a member of.
var allGroups = OmniaApi.WorkWith(Ctx.Omnia()).Security(Ctx)
.GetCurrentUserADGroups(new string[0]());
To only check specific AD groups, pass their names in the groups parameter
var someGroups = OmniaApi.WorkWith(Ctx.Omnia()).Security(Ctx)
.GetCurrentUserADGroups(new string{ "ADGroup1", "ADGroup2" });
GetPermissionRoles¶
To get Permissions Roles for given Permission Role Definitions you can use the following method, passing in a List<PermissionRoleDefinition> containing the role definitions of interest.
IEnumerable<PermissionRole> OmniaApi.WorkWith(Ctx.Omnia()).Security(Ctx)
GetPermissionRoles(List<PermissionRoleDefinition> requestedRoles);
This will return an array containing all permissions roles existing for the supplied definitions.
IsUserAuthorized¶
Use this method to check if the user is authorized, e.g. is a member of the required Omnia PermissionRoleDefinition
bool OmniaApi.WorkWith(Ctx.Omnia()).Security(Ctx)
.IsUserAuthorized(PermissionRoleDefinition requiredRole);
Returns true if the user is a member of the required Omnia role, else false.
SearchOmniaPermissionRoles¶
Documentation in progress
.. include:: /../common/authors.txt
Custom Web API for Omnia extensions¶
Note
This documentation is a work in progress and contributions can be made on our Github repo
Topics¶
.. include:: /../common/authors.txt
Omnia base controller¶
When building Web API for Omnia extension it’s recommended to use the base class SharePointContextProvidedController from Omnia. This base class provides many useful services when working with SharePoint and Omnia.
using Omnia.Foundation.Extensibility.Core;
using Omnia.Foundation.Extensibility.Core.Utilities;
using Omnia.Foundation.Extensibility.WebApi;
using Omnia.Foundation.Models.Shared;
using Omnia.Foundation.Models.Logging;
using System;
using System.Web.Http;
using System.Collections.Generic;
using Microsoft.SharePoint.Client;
public class MyController: SharePointContextProvidedController
{
[HttpGet, Route("api/items")]
public ApiOperationResult<IEnumerable<Item>> GetItems()
{
try
{
// Your controller logic here
}
catch (Exception ex)
{
this
.Logging
.AddLog(this.GetType().ToString(), ex.Message, DefaultLogTypes.Error, ex);
return ApiUtils.CreateErrorResult<IEnumerable<Item>>(ex);
}
}
}
Omnia Foundation Services¶
SharePointContextProvidedController has a built-in Logging service which write to Omnia Foundation logs database. Other Omnia Foundation services can be accessed using the factory method WorkWith()
using Omnia.Foundation.Extensibility.Core;
using Omnia.Foundation.Extensibility.Core.Utilities;
using Omnia.Foundation.Extensibility.WebApi;
using Omnia.Foundation.Extensibility.Core.Configurations;
using Omnia.Foundation.Models.Shared;
using Omnia.Foundation.Models.Logging;
using System;
using System.Web.Http;
using System.Collections.Generic;
using Microsoft.SharePoint.Client;
public class MyController: SharePointContextProvidedController
{
[HttpGet, Route("api/items")]
public ApiOperationResult<IEnumerable<Item>> GetItems()
{
try
{
// Use Omnia configuration service
var configuration = WorkWith().Configurations().GetConfiguration(
name: "configuration-name",
region: "configuration-region");
}
catch (Exception ex)
{
// Built-in logging service
this
.Logging
.AddLog(this.GetType().ToString(), ex.Message, DefaultLogTypes.Error, ex);
return ApiUtils.CreateErrorResult<IEnumerable<Item>>(ex);
}
}
}
Other contextual information are also provided:
- TenantId: ID of the Omnia tenant that the current SharePoint site belongs to.
- LoginName: SharePoint loginname of the current user.
- OmniaInstanceMode: The mode that Omnia Foundation is running in, either Tenant or SiteCollectionOnly
.. include:: /../common/authors.txt
Omnia Jobs¶
Omnia Jobs are pieces of code for handling long-running operations that can be run either as a message queue or as a scheduled timer job.
Create new Omnia Job¶
You can create Omnia Job using the template from Omnia Tooling

[JobDefinition(
id: "368D7722-9F75-4789-A1BA-460DBB6595F8",
name: "MyJob",
description: ""
)]
public class MyJob : OmniaJob
{
// Scheduled Job job function
public void MyJobTimer([TimerTrigger("01:00:00")] TimerInfo timerInfo)
{
try
{
// Your job code here
}
catch (Exception ex)
{
WorkWith().Logging().AddLog("MyJobTimer", ex.Message, DefaultLogTypes.Error, ex);
}
}
// Message Queue job function
public void MyJobQueue([QueueTrigger("MyJob")] object queueMessage)
{
try
{
// Your job code here
}
catch (Exception ex)
{
WorkWith().Logging().AddLog("MyJobQueue", ex.Message, DefaultLogTypes.Error, ex);
}
}
}
The job metadata is defined by the attribute JobDefinition. Each Omnia Job can contains any number of independent job functions, each can be of one of the two types Scheduled Job or Message Queue.
Built-in methods and properties¶
Similar to Omnia Feature and Omnia Web API, Omnia common services are available through the built-in WorkWith method. The code in Omnia Jobs is run at tenant scope so there is no user context, you can get an app-only ClientContext using the method CreateContextFor
Properties | Type | Description |
---|---|---|
Tenant | Tenant | The current tenant.
|
OmniaInstanceMode | Enum | The mode of the current tenant.
could be Tenant or Sitecollection
|
Methods | Type | Description |
---|---|---|
CreateContextFor(string spUrl) | ClientContext | Create an app-only context
|
WorkWith() | ApiFactory | Return the ApiFactory that can call Omnia API
Example: WorkWith().Logging().AddLog(log)
|
Manage jobs in a tenant¶
Unlike tenant resources, jobs are available and running immediately after the extension is deployed, there is no need to activate any feature.
All jobs deployed by extensions can be viewed in admin app at Systems > Jobs. You can also change the interval of scheduled jobs or stop/force run them from this interface. Note that built-in jobs will not be displayed here.

Job Types¶
.. include:: /../common/authors.txt
Scheduled Job¶
// Scheduled Job job function
public void MyJobTimer([TimerTrigger("01:00:00")] TimerInfo timerInfo)
{
try
{
// Your job code here
}
catch (Exception ex)
{
WorkWith().Logging().AddLog("MyJobTimer", ex.Message, DefaultLogTypes.Error, ex);
}
}
Scheduled jobs will run at the interval defined in the TimerTrigger. There are 2 different contructors you can use:
Note
The minimum interval supported by Omnia Jobs is 10 seconds
Note
TimerInfo is a place-holder for future features, currently it contains no information
public void MyJobTimer([TimerTrigger("01:00:00")] TimerInfo timerInfo)
public void MyJobTimer([TimerTrigger(1, 0, 0)] TimerInfo timerInfo)
.. include:: /../common/authors.txt
Message Queues¶
public void MyJobQueue([QueueTrigger("MyQueue")] object queueMessage)
{
try
{
// Your job code here
}
catch (Exception ex)
{
WorkWith().Logging().AddLog("MyJobQueue", ex.Message, DefaultLogTypes.Error, ex);
}
}
Message queue jobs will be triggered everytime a message is added to the queue that the jobs listen to (“MyQueue” in this example).
Queue messages can be added when a feature is activated/deactivated, when an web api endpoint is called or from another Omnia Job. To add a queue message, use the Queues service:
public void MyJobTimer([TimerTrigger(1, 0, 0)] TimerInfo timerInfo)
{
try
{
// Add a queue message to the queue "MyQueue" every hour, triggering the queue message job.
WorkWith().Queues().AddQueueMessage("MyQueue", new MyModel());
}
catch (Exception ex)
{
WorkWith().Logging().AddLog("MyJobTimer", ex.Message, DefaultLogTypes.Error, ex);
}
}
// The content of the queue message will de deserialized to type MyModel
public void MyJobQueue([QueueTrigger("MyQueue")] MyModel queueMessage)
{
try
{
// Your job code here
}
catch (Exception ex)
{
WorkWith().Logging().AddLog("MyJobQueue", ex.Message, DefaultLogTypes.Error, ex);
}
}
Dequeue Mode¶
When adding a queue message you can set the transaction ID for the message, so that multiple messages can be grouped together in the same transaction. By default, the message queue job will be triggered immediately when a new message is added, however you can change this behavior by setting the dequeue mode to SynchronousTransaction.
When running synchronous dequeue mode, all messages in the same transaction will be processed sequentially by the order that they was added. In other words, if a new message of the same transaction is added while the previous message was being processed, the new message will not be processed until the previous message has been finished.
public void MyJobQueue([QueueTrigger("MyJob", DequeueMode = Models.Queues.DequeueModes.SynchronousTransaction)] MyModel queueMessage)
.. include:: /../common/authors.txt
Client-Side Development¶
Note
This documentation is a work in progress and contributions can be made on our Github repo
Topics¶
.. include:: /../common/authors.txt
Live reload¶
When doing client side development, you can enable a mode called “Live reload”. In this mode, the page is automatically updated to reflect your new HTML, TypeScript and Less code when you save a file in Visual Studio.
Enable Live reload¶
- Open Visual Studio as Administrator
- In the environment.json file of your Omnia extension, do the following
- In the Hosting section set Enabled to true, and UseLiveReload to true
- Note the Port number (ex 9900)
- Save the file
![]()
- In the Output window of Visual Studio, select “Omnia Tooling” in the Show output from dropdown
- Make sure the Hosting server has started correctly by reading the output.
Note
If you get an error message in the output, you need to make sure that the IIS Express SSL certificate is installed on your computer.
You can trigger the installation by creating an MVC project, Enable SSL and then start Debugging the project. You will now get a dialog asking if you want to trust the IIS Express SSL certificate. Click “Yes”
- In your web browser
- Navigate to a site in the Office 365 Tenant used for developing your Omnia Extension
- Add ?console=on to the URL of the page, ex /somepage?console=on. If you are on a quick page, instead add |console=on, ex /#/somepage|console=on
- This will display the Omnia Console on the current page. Type help in the console to get a list of all available commands
- To enable Live reload, type hosting enable https://localhost:9900 where 9900 is the port number you noted in Step 2, from the environment.json
![]()
- The page should now be reloaded and after some time your controls should be displayed, now served from https://localhost:9900 instead of the Omnia server
Working in Live reload mode¶
Edit your LESS, TypeScript or HTML files as you normally would. When saved, the browser will update to instantly display the changes.
Disable Live reload¶
To disable Live reload, do the following:
- In the Omnia console in the browser window, write hosting disable
- In the Visual Studio project, in the environment.json file, set the Enabled parameter in the Hosting section to false
.. include:: /../common/authors.txt
Angular 1¶
Note
This documentation is a work in progress and contributions can be made on our Github repo
Topics¶
.. include:: /../common/authors.txt
Note
This documentation is a work in progress and contributions can be made on our Github repo
.. include:: /../common/authors.txt
Note
This component is an Angular 1 directive registered in module Omnia.Foundation.Core.Module
The single picker is a dropdown component that supports type-ahead search and customizable UI.

$scope.employees = [
{ id: 1, firstName: 'Mary', lastName: 'Brown', age: 27 },
{ id: 2, firstName: 'John', lastName: 'Smith', age: 36 }
];
$scope.department = {
id: 1,
name: "Marketing",
managerId: 1
}
<omf-single-picker
items="employees"
title-expression="[firstName] [lastName]"
id-prop="id"
bind-selected-item-id="department.managerId"
pre-selected-item-id="department.managerId">
</omf-single-picker>
Name | Binding | Description |
---|---|---|
items | = | The list of options in the dropdown |
titleProp | @ | The property on model to be used as the display text |
titleExpression | @ | The format string for display text. Example: [firstName] [lastName] ([email]) |
idProp | @ | The property on model to be used as the value |
onSelect | & | Callback when an option is selected. Parameters: (selectedItem, parentItem) |
onDeselect | & | Callback when the dropdown is cleared. |
onOpen | & | Callback when the dropdown is opened. |
bindSelectedItemId | = | The selected value. This property is only one-way binding from the dropdown to the consumer scope. |
preSelectedItemId | = | The initial selected value. |
updateSelectedItemEvent | @ | The event name used to update selected value of the dropdown from outsite scope. |
preSelectFirstItem | @ | true or false - whether to preselect the first option if no initial selected value is provided. |
parentItem | = | An object to be pass along the selected item on the onSelect callback. |
.. include:: /../common/authors.txt
Note
This component is an Angular 1 directive registered in module Omnia.Foundation.Core.Module
The multi picker is a dropdown component that supports multiple selected values, type-ahead search and customizable UI.

$scope.employees = [
{ id: 1, firstName: 'Mary', lastName: 'Brown', age: 27 },
{ id: 2, firstName: 'John', lastName: 'Smith', age: 36 }
];
$scope.department = {
id: 1,
name: "Marketing",
managerId: 1,
members: [
{ id: 1, firstName: 'Mary', lastName: 'Brown', age: 27 },
{ id: 2, firstName: 'John', lastName: 'Smith', age: 36 }
]
}
<omf-multi-picker items="employees"
title-expression="[firstName] [lastName]"
selected-items="department.members">
</omf-multi-picker>
Name | Binding | Description |
---|---|---|
items | = | The list of options in the dropdown |
titleProp | @ | The property on model to be used as the display text |
titleExpression | @ | The format string for display text. Example: [firstName] [lastName] ([email]) |
idProp | @ | The property on model to be used as the value |
onSelect | & | Callback when an option is selected. Parameters: (selectedItem) |
onDeselect | & | Callback when the dropdown is cleared. |
onOpen | & | Callback when the dropdown is opened. |
selectedItems | = | The selected value. This property is only two-way binding between the dropdown and the consumer scope. |
.. include:: /../common/authors.txt
.. include:: /../common/authors.txt
Angular 2¶
Note
This documentation is a work in progress and contributions can be made on our Github repo
Topics¶
.. include:: /../common/authors.txt
Note
This documentation is a work in progress and contributions can be made on our Github repo
.. include:: /../common/authors.txt
Note
This documentation is a work in progress and contributions can be made on our Github repo
DropDownList is a dropdown component that supports type-ahead search and customizable UI.

<omf-dropdown-list></omf-dropdown-list>
import { Component, Inject, ViewContainerRef } from '@angular/core';
@Component({
selector: 'my-component'
})
export class MyComponent {
employees = [
{ id: 1, firstName: 'Mary', lastName: 'Brown', age: 27 },
{ id: 2, firstName: 'John', lastName: 'Smith', age: 36 }
];
selectedEmployeeId = 1;
constructor(@Inject(ViewContainerRef) private viewContainer: ViewContainerRef) {
}
}
<omf-dropdown-list [items]="employees"
textProperty="firstName"
valueProperty="id"
[(selectedItemValue)]="selectedEmployeeId">
</omf-dropdown-list>
.. include:: /../common/authors.txt
Note
This documentation is a work in progress and contributions can be made on our Github repo
ColorPicker is a component for selecting color from Omnia corporate colors feature or from custom colors.

<omf-color-picker></omf-color-picker>
import { Component, Inject, ViewContainerRef } from '@angular/core';
@Component({
selector: 'my-component'
})
export class MyComponent {
selectedColor = '#ffffff';
constructor(@Inject(ViewContainerRef) private viewContainer: ViewContainerRef) {
}
}
<omf-color-picker [color]="selectedColor" [position]="'bottom'"></omf-color-picker>
.. include:: /../common/authors.txt
Note
This documentation is a work in progress and contributions can be made on our Github repo
.. include:: /../common/authors.txt
Note
This documentation is a work in progress and contributions can be made on our Github repo
AJAX service is a utility for making AJAX requests to Omnia Foundation and Omnia extensions web API. The AJAX service is usually not used directly in UI components but in other services.
Method | Description | Parameters |
---|---|---|
buildRequest | Fluent API for making
an AJAX request
|
- apiPath (string): The request’s URL. If apiPath is a relative URL, it will be direct to Omnia Foundation.
Other extensions can inherit this AJAX and override the internal method getFullApiPath to make calls to it’s API instead
- dataType (string) (optional): The request’s Content-Type. Default value is ‘application/json’
|
Note
To use the AjaxService, you need to import The module OmniaExtensibilityModule into the NgModule of your component or add it directly to the list of providers of your compoment
Normal Usage
import { AjaxService } from "Omnia/Foundation/Extensibility/Services";
import { Pipe, Injectable , Inject } from '@angular/core';
@Injectable()
export class ConfigurationService {
constructor(@Inject(AjaxService) private ajaxService: AjaxService) {
}
public getConfiguration = (callback: (result: Configurations.IConfiguration) => void, name: string, region: string, extensionPackageId: string = null) => {
var params = {
name: name,
region: region,
extensionPackageId: extensionPackageId
};
this.ajaxService.buildRequest("configuration/configurations")
.addQueryStrings(params)
.doGet<Configurations.IConfiguration>()
.subscribe((result) => { callback(result.json()); });
}
}
Inherit AJAX Service
import { AjaxService as FoundationAjaxService } from 'Omnia/Foundation/Extensibility/Services'
import { Utils } from "Omnia/Foundation/Extensibility";
@Injectable()
export class AjaxService extends FoundationAjaxService{
static apiBaseUrl: string = "";
public getFullApiPath(apiPath: string): string {
if (Utils.isNullOrEmpty(AjaxService.apiBaseUrl)) {
AjaxService.apiBaseUrl = Utils.ensureTrailingSlash("<my-extension-api-url>");
}
return AjaxService.apiBaseUrl + apiPath;
}
}
.. include:: /../common/authors.txt
Note
This documentation is a work in progress and contributions can be made on our Github repo
Dialogs service is a utility for working with modal dialogs in Angular 2 and Omnia.
Method | Description | Parameters |
---|---|---|
onConfirmationDialog | Show a confirmation dialog
with yes/no outcome
|
- title (string): The dialog’s title
- body (string): The dialog’s body text
- viewContainerRef (ViewContainerRef): the viewContainerRef of the calling component
- okCallback (() => void): The callback for ‘OK’ outcome
- cancelCallback (() => void): The callback for ‘Cancel’ outcome
|
openDialog | Show a custom dialog
|
- componentType (Type<any>): The component to show in the dialog
- params (any): the parameters passed to the dialog
- viewContainerRef (ViewContainerRef): the viewContainerRef of the calling component
- dialogSize (DialogSize): can be small, medium and large. Default value is medium
- okCallback (() => void): The callback for ‘OK’ outcome
- cancelCallback (() => void): The callback for ‘Cancel’ outcome
|
blockUI | Show a loading indicator
and block the whole page UI
|
|
unblockUI | Remove the UI block from
blockUI method
|
Note
To use the DialogService, you need to import The module OmniaExtensibilityModule into the NgModule of your component or add it directly to the list of providers of your compoment
Injection
import { DialogService } from "Omnia/Foundation/Extensibility/Services";
import { Component, Inject, ViewContainerRef } from '@angular/core';
@Component({
selector: 'my-component',
providers: [ DialogService ]
})
export class MyComponent {
constructor(@Inject(ViewContainerRef) private viewContainer: ViewContainerRef,
@Inject(DialogService) private dialogService: DialogService) {
}
}
Open confirmation dialog
private deleteItem(item) {
let dialogTitle = "Delete Item";
let dialogBody = "Are you sure you want to delete this item?";
this.dialogService.onConfirmationDialog(dialogTitle, dialogBody, this.viewContainer, () => {
// Confirmed, proceed to delete the item
});
}
Open custom dialog
import { EditItemForm } from "MyComponent/EditItemForm";
import { DialogSize } from "Omnia/Foundation/Extensibility/Enums";
// ...
private editItem(item) {
this.dialogService.openDialog(EditItemForm, { item: item },
this.viewContainer, DialogSize.Large);
}
import { Component, Inject, ViewContainerRef, OnDestroy , OnInit } from '@angular/core';
import { DialogRef} from 'angular2-modal';
import { BaseDialogComponent, BaseDialogModel } from "Omnia/Foundation/Extensibility/Services";
@Component({
selector: 'edit-item-form'
})
export class EditItemForm extends BaseDialogComponent<BaseDialogModel<any>> implements OnInit {
item: Item;
constructor(@Inject(DialogRef) public dialog: DialogRef<BaseDialogModel<any>>) {
super(dialog);
}
ngOnInit() {
this.item = this.context.params.item;
}
}
.. include:: /../common/authors.txt
Note
This documentation is a work in progress and contributions can be made on our Github repo
Configuration service is a utility for working with Omnia configurations. Read more about configuration in Omnia here
Method | Description | Parameters |
---|---|---|
getConfiguration | Get configuration from
Omnia Foundation API
|
- callback ((result: Configurations.IConfiguration) => void): The callback with the requested configuration
- name (string): The name of the configuration
- region (string): The region of the configuration
- extensionPackageId (string) (optional): The ID of the extension that created the configuration. Default value is built-in configurations
|
getClientConfiguration | Get configuration included
in client-side
|
- name (string): The name of the configuration
- region (string): The region of the configuration
- extensionPackageId (string) (optional): The ID of the extension that created the configuration. Default value is built-in configurations
|
addOrUpdateConfigurations | Add or update a list of
configurations
|
- configurations (Array<Configurations.IConfiguration>): The list of configurations to add or update
- callback ((isSuccess: boolean) => void): The callback function
|
getConfigurationsInRegion | Get all configurations by
region
|
- region (string): The region of the configurations
- callback ((result: Array<Configurations.IConfiguration>) => void): The callback function with result
|
updateConfiguration | Update a configuration
|
- configuration (Configurations.IConfiguration): The configuration to be updated
- callback ((isSuccess: boolean) => void): The callback function
|
deleteConfiguration | Remove a configuration
|
- name (string): The name of the configuration
- region (string): The region of the configuration
- callback ((isSuccess: boolean) => void): The callback function
|
Note
To use the ConfigurationService, you need to import The module OmniaExtensibilityModule into the NgModule of your component or add it directly to the list of providers of your compoment
Injection
import { ConfigurationService } from "Omnia/Foundation/Extensibility/Services";
import { Component, Inject, ViewContainerRef } from '@angular/core';
@Component({
selector: 'my-component',
providers: [ ConfigurationService ]
})
export class MyComponent {
constructor(@Inject(ViewContainerRef) private viewContainer: ViewContainerRef,
@Inject(ConfigurationService) private configurationService: ConfigurationService) {
}
}
Get configuration
private getDefaultColors() {
this.configurationService.getConfiguration((configuration: Configurations.IConfiguration) => {
let defaultColors = configuration.value;
}, "defaultcolors", "");
}
.. include:: /../common/authors.txt
Note
This documentation is a work in progress and contributions can be made on our Github repo
Localization service is a utility for getting localized text in Omnia. Read more about localization in Omnia here
Method | Description | Parameters |
---|---|---|
getText | Get the localized text
for a label in Omnia
|
- key (string): The key for the localization. If no localized text match, this key will be return
|
Note
To use the LocalizationService, you need to import The module OmniaExtensibilityModule into the NgModule of your component or add it directly to the list of providers of your compoment
Injection
import { LocalizationService } from "Omnia/Foundation/Extensibility/Services";
import { Component, Inject, ViewContainerRef } from '@angular/core';
@Component({
selector: 'my-component',
providers: [ ConfigurationService ]
})
export class MyComponent {
constructor(@Inject(ViewContainerRef) private viewContainer: ViewContainerRef,
@Inject(LocalizationService) private localizationService: LocalizationService) {
}
}
Get localized text
private getItemTypes() {
return [
{ id: 0, title: this.localizationService.getText('MyExtension.ItemTypes.Small') },
{ id: 1, title: this.localizationService.getText('MyExtension.ItemTypes.Medium') },
{ id: 2, title: this.localizationService.getText('MyExtension.ItemTypes.Large') }
];
}
.. include:: /../common/authors.txt
Performance¶
The following sections will guide you in using functionality in Omnia to improve the performance in your solution
ClientContext.LoadIfNeeded and ClientContext.ExecuteQueryIfNeeded¶
Often, a single SharePoint Client Context is passed between different services and you do not know if the data you need has already been loaded or if an ExecuteQuery is needed.
To make this process more effective and straight forward, Omnia has implemented two extension methods on ClientContext: LoadIfNeeded and ExecuteQueryIfNeeded.
By using the above methods, already loaded and fetched data will not trigger a new ExecuteQuery to the server.
Example:
public string GetServerRelativeUrl(ClientContext ctx)
{
ctx.LoadIfNeeded(Ctx.Web, x => x.ServerRelativeUrl).ExecuteQueryIfNeeded();
return ctx.Web.ServerRelativeUrl;
}
The ExecuteQueryIfNeeded method also takes an optional parameter of type Microsoft.SharePoint.Client.ClientContextExtensions.ExecuteOption. This is an enum with two possible values:
- LoadAllIfOneIsNeeded
- LoadOnlyNeeded
This is useful to decide if only missing property should be loaded from the server, or if all loaded properties should be reloaded if an execute needs to be done.
If this parameter is not supplied, LoadOnlyNeeded is used.
.. include:: /../common/authors.txt
Release Notes¶
Topics¶
.. include:: /../common/authors.txt
Omnia Foundation¶
Sections:
1.0.1.1681 (2016-09-20)¶
What’s new
- It’s now possible in the API for an extension to change the configuration created by another extension.
- A new feature called “Omnia Statistics Provider” makes it possible to register a third-party analytics script in the Admin UI to be included on all pages within a specific site collection.
- Targeting api that makes it possible to specify targeting definitions in Omnia Admin using Taxonomy/Profile Properites or Security Groups and then use the api in extensions to filter content based on selected targeting.
- Omnia Jobs is a new feature that makes it possible to create Jobs in Extensions that can be based on a Timer or by listening on a Queue.
- OmniaApi support to work with queues.
- Updated font awesome to version 4.6.3.
- Omnia Console now has support to listen to commands. Currently we support two commands that enables support for the built in webserver in Omnia Tooling for example:
- hosting enable https://localhost:9930
- hosting disable
- A new section in Omnia Admin > System called Developers was added. It lists the version of Omnia Foundation and also displays the nuget version to be used for Extensions.
- OmniaApi now has a SitesService that has the following methods GetSiteRequestById, GetRecentSites, AddOrUpdateRecentSite.
Bug fixes
- When provisioning a Field without a description an error was thrown.
- Left navigation in admin missing scroll support.
- Slow performance in Features view in Admin.
- Fixed an performance issue where the JobHost was loading all extension packages from database at startup.
- When adding new properties to a site template and performing a migration the migration would stop if a site was deleted.
- When using approval flow in site requests there was sometimes a timeout error when approving the request.
- When editing site templates deployed by extensions the save button was always disabled.
- The announcements control had a problem with overflow when long text without space was in the message.
- When uploading a extension package with configuration we now always sort it in alphabetic order.
- The customized localization made in the localization editor in Omnia Admin for an extension package was removed when a feature was upgraded.
- Selected features in site templates was not checked in UI when the template was loaded.
- When specifying a FieldRef using [FieldRef(typeof(Field1), Required = true)] it didn’t listen on the Required property.
.. include:: /../common/authors.txt
Omnia Tooling¶
Here you can find the releases of the Omnia Tooling for Visual Studio 2013/2015
Sections:
- Visual Studio 2017 1.0.0
- Visual Studio 2017 1.0.6924 Beta 4 (Vietnam Codebase Edition)
- Visual Studio 2017 1.0.6828 Beta 3 (France Codebase Edition)
- Visual Studio 2017 1.0.6250 Beta 2
- Visual Studio 2017 1.0.5935 Beta 1
- Visual Studio 2017 Preview
- Stable 1.0.1.3965
- Stable 1.0.1.2305-62
- Stable 1.0.1.1699-48
- Stable 1.0.1.1115-38
Visual Studio 2017 1.0.6924 Beta 4 (Vietnam Codebase Edition)¶
Note
- To be able to use this Tooling you need to target a Tenant with Omnia Foundation version 1.0.5862 or higher
What`s new
- Improvement in Resource Mapper
- Its now possible to create new Omnia Controls without any additional setup
- Bugfixes
Please report issues with tooling on our Github repo
Visual Studio 2017 1.0.6828 Beta 3 (France Codebase Edition)¶
Note
- To be able to use this Tooling you need to target a Tenant with Omnia Foundation version 1.0.5862 or higher
What`s new
- Visual Resource Mapper makes it easy adding resources to mapping files
- Support for Visual Resource Mapper when adding TenantResources from item templates
Please report issues with tooling on our Github repo
Visual Studio 2017 1.0.6250 Beta 2¶
Note
- To be able to use this Tooling you need to target a Tenant with Omnia Foundation version 1.0.5862 or higher
What`s new
- Improved Copy to Tenant
- Remove extra folder from solution
- Upgrade TypeScript to version 2.4.1
Please report issues with tooling on our Github repo
Visual Studio 2017 1.0.5935 Beta 1¶
Note
- To be able to use this Tooling you need to target a Tenant with Omnia Foundation version 1.0.5862 or higher
What`s new
- Completely new Project Wizard and Item Template Wizard that uses Github as source
- Angular 4 support
- Extensible TaskRunner (angular aot, less etc)
- We now use npm for Foundation (https://www.npmjs.com/package/@omnia/foundation)
Please report issues with tooling on our Github repo
Stable 1.0.1.2305-62¶
What`s new
- Update Omnia Control Item Templates for Angular 2 to comply with Angular 2.0.0
- Update Omnia Extension Sample Project Template with new samples of Angular 2
Stable 1.0.1.1699-48¶
What`s new
- Omnia Control Item Templates for Angular 2
- Built in websever for hosting Tenant bundles locally
- Live Reload support for Tenant bundles
Note
The Omnia Control Templates for Angular 2 is only for preview purposes since the Angular 2 RTM was just released we removed the bootstrapping for Angular 2 in Foundation until we have a working version running on Angular 2 RTM
Bug fixes
- The item template for Field contained a space in the internalname which could cause problems in provisioning
- Item Template for Omnia Control without settings should have enableSettings value set to false and the constructor should not have the ControlConfigService injected
.. include:: /../common/authors.txt
Contribute to this Documentation¶
This documentation is a constant work in progress, and contributions can be made on our Github repo. For more extensive contributions please follow the steps below to get started with using Sphinx.
.. include:: /../common/authors.txt
Get started¶
Please follow the steps below to install Sphinx and get the source code from our Git repository.
1. Install Python¶
Download and install Python 3.6.0 from here https://www.python.org/downloads/
Note
Make sure to select pip and Add Python to environment variables during the installation
2. Install Sphinx¶
Open a command prompt
Run
pip install sphinx sphinx-autobuild sphinx_rtd_theme
3. Install Git for Windows¶
Download and install Git from here https://git-scm.com/download/win
4. Get the Git repository¶
Create a folder in your file system where you would like to keep the documentation source code, for example
C:\Git\OMF-docs
In a command prompt, navigate to the folder you just created and execute the following command
git clone https://github.com/preciofishbone/Omnia-Foundation-Docs.git
The source code is now cloned to the current folder
.. include:: /../common/authors.txt
Work with the documentation¶
To work with the source code locally using Sphinx, follow the steps below
- Open a command prompt and navigate to the folder containing the source code for the documentation
- Execute the following command
make livehtmlAfter a while the console window will settle down, and you will find a link in the window, like this Serving on http://127.0.0.1:8000
- In a web browser, enter the link from above. A locally rendered version of the documentation will be displayed.
Now, any time you add a file, or edit an existing file and then save it, Sphinx will rebuild the documentation locally and reload the browser window to display the latest changes.
You do edits, additions and deletes by just working with the files in the source code folder in your favorite text editor.
Note
The documentation is written with reStructuredText. To learn more about this markup language, you can use this link http://sphinx-doc.org/rest.html#rst-primer
To stop Sphinx, press Ctrl + C in the command prompt and then select Y
.. include:: /../common/authors.txt
Commit your changes¶
To commit your change to the Git-repo perform the following steps
- Open a command prompt and navigate to the folder containing the source code for the documentation
- Execute the following command
git pull
- Execute the following command
git commit -a -m "A description of your changes"
- Execute the following command
git push
You have now successfully contributed to this documentation. Thank you for your time and effort!