eFormidling
How to configure integration with eFormidling for an app.
In addition to the documentation below, we have created a sample application showing the complete eFormidling setup.
Prerequisites
Before setting up eFormidling you will need to have the following set up:
Maskinporten Integration
In order to enable eFormidling in your application you will need to setup an integration between your app and Maskinporten.
NB! In
Program.cs
add the following instead of what is described in the steps above in theRegisterCustomAppServices
-method:App/Program.cs
void RegisterCustomAppServices(IServiceCollection services, IConfiguration config, IWebHostEnvironment env) { services.Configure<MaskinportenSettings>(config.GetSection("MaskinportenSettings")); services.AddMaskinportenJwkTokenProvider("MaskinportenSettings--EncodedJwk"); }
Events
An event subscription needs to be setup in order to ensure that the application knows the delivery status of the messages sent through eFormidling.
Setup eFormidling in your application
Register eFormidling Services
In order to add support for eFormidling in your application you need to register its services by adding the following to the RegisterCustomAppServices
-method in Program.cs
:
App/Program.cs
void RegisterCustomAppServices(IServiceCollection services, IConfiguration config, IWebHostEnvironment env)
{
services.AddEFormidlingServices2<EFormidlingMetadata, EFormidlingReceivers>(config);
}
Configuring Shipment Metadata
Metadata related to the eFormidling shipment is required, and this is set up in applicationmetadata.json
.
In order to setup the required metadata you will need to create a new section "eFormidling"
in applicationmetadata.json
and populate values for the
parameters defined below.
Property | Type | Description |
---|---|---|
serviceId * | string | ID that specifies the shipment type. (DPO, DPV, DPI or DPF) |
dpfShipmentType | string | The DPF shipment type used for routing in the receiving system |
receiver | string | Organisation number of the receiver (can be omitted). Only Norwegian organisations are supported. |
sendAfterTaskId | string | ID of the task to be completed before the shipment is sent. |
process ** | string | Process type |
standard *** | string | The document standard |
typeVersion | string | Version of the message type |
type *** | string | The document type |
securityLevel *** | number | Security level to be set on the StandardBusinessDocument |
dataTypes | array | List of data types to include in the shipment |
* Altinn only supports DPF and DPO.
** Available processes for each receiver can be found at:
https://platform.altinn.no/eformidling/api/capabilities/{orgnumber}
*** Can be found within the pages describing each document type or using the URL above.
Below is an example of the configuration for the message type arkivmelding
.
App/applicationmetadata.json
{
...
"eFormidling": {
"serviceId": "DPO",
"receiver": "991825827",
"sendAfterTaskId": "Task_1",
"process": "urn:no:difi:profile:arkivmelding:administrasjon:ver1.0",
"standard": "urn:no:difi:arkivmelding:xsd::arkivmelding",
"typeVersion": "2.0",
"type": "arkivmelding",
"securityLevel": 3,
"dataTypes": [
"ref-data-as-pdf"
]
},
...
}
Activate eFormidling Integration in your application
Integration with eFormidling needs to be explicitly activated in the application.
In appsettings.json
you need to enable eFormidling in the "AppSettings"
-section as well as add a new section "EFormidlingClientSettings"
:
App/appsettings.json
{
...
"AppSettings": {
...
"EnableEFormidling": true
},
"EFormidlingClientSettings": {
"BaseUrl": "http://localhost:9093/api/"
}
}
If you do not wish to test the eFormidling integration locally, you can add an "AppSettings"
-section to appsettings.Development.json
and set "EnableEFormidling"
to false
.
Message Metadata Generation in the application
It is the application developer’s responsibility to create the message of the shipment sent through eFormidling.
In order to create the shipment message you will need a class that implements the IEFormidlingMetadata
-interface and create your message in the GenerateEFormidlingMetadata
-method. Remember to register your class in Program.cs
.
You will need to replace YourMessageType
and yourMessage
with your shipment message type.
App/logic/EFormidling/EFormidlingMetadata.cs
public class EFormidlingMetadata : IEFormidlingMetadata
{
public async Task<(string MetadataFilename, Stream Metadata)> GenerateEFormidlingMetadata(Instance instance)
{
YourMessageType yourMessage = new YourMessageType();
MemoryStream stream = new MemoryStream();
XmlSerializer serializer = new XmlSerializer(typeof(YourMessageType));
serializer.Serialize(stream, yourMessage);
stream.Position = 0;
StreamContent streamContent = new StreamContent(stream);
streamContent.Headers.ContentType = MediaTypeHeaderValue.Parse("application/xml");
return await Task.FromResult(("yourMessage.xml", stream));
}
}
The following example shows a setup of an EFormidlingMetadata
-class with the arkivmelding
message type.
In order for this example to work we have created a class Arkivmelding
(based on arkivmelding.xsd). Bear in mind that this only includes the required parts of the arkivmelding, so if you wish to include other parts you must do so yourself.
App/logic/EFormidling/EFormidlingMetadata.cs
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Threading.Tasks;
using System.Xml.Serialization;
using Altinn.App.Core.EFormidling.Interface;
using Altinn.App.Core.Internal.App;
using Altinn.App.Core.Models;
using Altinn.App.Models.Arkivmelding;
using Altinn.Platform.Storage.Interface.Models;
using Microsoft.Extensions.Logging;
namespace Altinn.App.logic.EFormidling;
public class EFormidlingMetadata : IEFormidlingMetadata
{
private readonly ApplicationMetadata _applicationMetadata;
private readonly ILogger<EFormidlingMetadata> _logger;
private readonly string _documentCreator = "Digitaliseringsdirektoratet";
public EFormidlingMetadata(IAppMetadata appMetadata, ILogger<EFormidlingMetadata> logger)
{
_applicationMetadata = appMetadata.GetApplicationMetadata().Result;
_logger = logger;
}
public async Task<(string MetadataFilename, Stream Metadata)> GenerateEFormidlingMetadata(Instance instance)
{
string title = $"{_applicationMetadata.Title["nb"]}";
Guid mappeSystemID = Guid.NewGuid();
List<Dokumentbeskrivelse> dokumentbeskrivelse = new List<Dokumentbeskrivelse>();
int documentNumber = 1;
DataElement pdf = instance.Data.First(dataElement => dataElement.DataType == "ref-data-as-pdf");
dokumentbeskrivelse.Add(GetDokumentbeskrivelse(pdf.Filename, documentNumber, "Hoveddokument"));
List<DataElement> attachments = new List<DataElement>(instance.Data.FindAll(dataElement => dataElement.DataType == "attachments"));
foreach (DataElement attachment in attachments)
{
documentNumber += 1;
dokumentbeskrivelse.Add(GetDokumentbeskrivelse(attachment.Filename, documentNumber, "Vedlegg"));
}
Arkivmelding arkivmelding = new()
{
System = "Altinn",
MeldingId = Guid.NewGuid().ToString(),
Tidspunkt = DateTime.Now,
AntallFiler = documentNumber,
Mappe = new List<Mappe> {
new Mappe {
Type = "saksmappe",
SystemID = mappeSystemID,
Tittel = title,
OpprettetDato = DateTime.Now,
OpprettetAv = _documentCreator,
Basisregistrering = new Basisregistrering
{
Type = "journalpost",
SystemID = Guid.NewGuid(),
OpprettetDato = DateTime.Now,
OpprettetAv = _documentCreator,
ReferanseForelderMappe = mappeSystemID,
Dokumentbeskrivelse = dokumentbeskrivelse,
Tittel = title,
OffentligTittel = title,
Journalposttype = "Utgående dokument",
Journalstatus = "Journalført",
Journaldato = DateTime.Now,
},
Saksdato = DateTime.Now,
AdministrativEnhet = _documentCreator,
Saksansvarlig = "Ingen",
Saksstatus = "Under behandling"
}
}
};
MemoryStream stream = new MemoryStream();
XmlSerializer serializer = new XmlSerializer(typeof(Arkivmelding));
serializer.Serialize(stream, arkivmelding);
stream.Position = 0;
StreamContent streamContent = new StreamContent(stream);
streamContent.Headers.ContentType = MediaTypeHeaderValue.Parse("application/xml");
return await Task.FromResult(("arkivmelding.xml", stream));
}
private Dokumentbeskrivelse GetDokumentbeskrivelse(string fileName, int documentNumber, string tilknyttetRegistreringSom)
{
return new Dokumentbeskrivelse
{
SystemID = Guid.NewGuid(),
Dokumenttype = "Skjema",
Dokumentstatus = "Dokumentet er ferdigstilt",
Tittel = fileName,
OpprettetDato = DateTime.Now,
OpprettetAv = _documentCreator,
TilknyttetRegistreringSom = tilknyttetRegistreringSom,
Dokumentnummer = documentNumber,
TilknyttetDato = DateTime.Now,
TilknyttetAv = _documentCreator,
Dokumentobjekt = new Dokumentobjekt
{
Versjonsnummer = 1,
Variantformat = "Produksjonsformat",
OpprettetDato = DateTime.Now,
OpprettetAv = _documentCreator,
ReferanseDokumentfil = fileName,
},
};
}
}
Dynamically setting the shipment receiver
If the receiver of a shipment needs to be set dynamically, a class implementing the IEFormidlingReceivers
-interface needs to be created and registered in Program.cs
.
App/logic/EFormidling/EFormidlingReceivers.cs
using System.Collections.Generic;
using System.Threading.Tasks;
using Altinn.App.Core.EFormidling.Interface;
using Altinn.Common.EFormidlingClient.Models.SBD;
using Altinn.Platform.Storage.Interface.Models;
namespace Altinn.App.logic.EFormidling;
public class EFormidlingReceivers : IEFormidlingReceivers
{
public async Task<List<Receiver>> GetEFormidlingReceivers(Instance instance)
{
Identifier identifier = new()
{
Authority = "iso6523-actorid-upis",
// All Norwegian organisations need a prefix of '0192:'
Value = "0192:{organisationNumber}"
};
List<Receiver> receiverList = [new Receiver { Identifier = identifier }];
return await Task.FromResult(receiverList);
}
}
NB! Note that only Norwegian organisations are supported, and that the prefix 0192:
is required before the organisation number.
Adding a feedback task to the application process
While not strictly necessary, it is recommended to add a feedback task to your application. This is to ensure that the process is moved along when the message has been received.
No further changes are needed when the task has been added as the eFormidling service we added earlier will automatically move the process along.
If you wish to customize the texts that are presented to the user during this step you can do so by overriding the text keys
Ensuring unique filenames
If the message sent by your application contains multiple attachments, it is important to ensure that these have unique filenames as the shipment will fail otherwise.
If the message includes the generated PDF of the form, you need to check that the other filename(s) are not the same as the application name.
One way to ensure unique filenames is through the use of file validation.
Testing
Thorough testing for the eFormidling integration in an application is encouraged.
Safety measures and retry mechanisms are in place to ensure that a shipment reaches the receiver when errors are due to weak network connections.
However, invalid shipments, including but not limited to missing attachments or mistakes in the "arkivmelding"
, will cause the shipment to fail without explicit warning to the end user or app owner.
Local
Test environment (TT02)
You can monitor the status of a shipment sent in the test environment through the endpoint below.https://platform.tt02.altinn.no/eformidling/api/conversations?messageId={instanceGuid}
{instanceGuid}
: the GUID of the instance that has been archived.