eFormidling service task
A service task for sending instance data via eFormidling is included with the app by default and can be added as a step in the process to be used.
Prerequisites
Before setting up eFormidling, you must have the following in place:
Setting up eFormidling in your application
Register eFormidling services
To add support for eFormidling in your application, you must register the services by adding the following to the RegisterCustomAppServices method in Program.cs:
App/Program.csvoid RegisterCustomAppServices(IServiceCollection services, IConfiguration config, IWebHostEnvironment env)
{
services.AddEFormidlingServices2<EFormidlingMetadata, EFormidlingReceivers>(config);
}
Add eFormidling as a service task in your application’s workflow
Integration with eFormidling is added to the workflow as a service task. Remember that the task must have an incoming and an outgoing sequence flow.
Note: In the future, it will be possible to drag in eFormidling directly via the Workflow editor in Altinn Studio, but this functionality is unfortunately not yet available.
For now, the following procedure is recommended:
- Drag in a regular data task in the Workflow editor
- Share the changes in Studio
- Manually edit
process.bpmnon your own machine - Convert the data task to a
bpmn:serviceTask(see example below)
This ensures that sequence flows and the diagram are correct.
App/config/process.bpmn<bpmn:serviceTask id="Task_eFormidling" name="eFormidling">
<bpmn:extensionElements>
<altinn:taskExtension>
<altinn:taskType>eFormidling</altinn:taskType>
<altinn:eFormidlingConfig>
<altinn:disabled env="local">true</altinn:disabled> <!-- Prevents it from running in local development environment. -->
<altinn:receiver>991825827</altinn:receiver>
<altinn:process>urn:no:difi:profile:arkivmelding:administrasjon:ver1.0</altinn:process>
<altinn:standard>urn:no:difi:arkivmelding:xsd::arkivmelding</altinn:standard>
<altinn:typeVersion>2.0</altinn:typeVersion>
<altinn:type>arkivmelding</altinn:type>
<altinn:securityLevel>3</altinn:securityLevel>
<altinn:dpfShipmentType>digital</altinn:dpfShipmentType>
<altinn:dataTypes>
<altinn:dataType>ref-data-as-pdf</altinn:dataType>
</altinn:dataTypes>
</altinn:eFormidlingConfig>
</altinn:taskExtension>
</bpmn:extensionElements>
<bpmn:incoming>Flow_1uewkmg</bpmn:incoming>
<bpmn:outgoing>Flow_0c1ure8</bpmn:outgoing>
</bpmn:serviceTask>
| Property | Type | Description |
|---|---|---|
| receiver | string | Recipient’s organization number (can be omitted). Only Norwegian organizations are supported. |
| process | string | Process type. See https://platform.altinn.no/eformidling/api/capabilities/{orgnumber} |
| standard | string | Document standard |
| typeVersion | string | Version of the message type |
| type | string | Document type, which can be found within the pages describing each document type or here: https://platform.altinn.no/eformidling/api/capabilities/{orgnumber} |
| securityLevel | number | Security level to be set on the StandardBusinessDocument |
| dpfShipmentType | string | DPF shipment type used for routing in the recipient system |
| dataTypes | array | List of data types to be included in the shipment. Each dataType is added as <altinn:dataType>ref-data-as-pdf</altinn:dataType> |
Generating message metadata in the application
It is the application developer’s responsibility to create the message for the shipment sent via eFormidling.
To create the shipment message, you need a class that implements the IEFormidlingMetadata interface and creates your message in the GenerateEFormidlingMetadata method. Remember to register your class in Program.cs.
You must replace YourMessageType and yourMessage with your shipment message type.
App/logic/EFormidling/EFormidlingMetadata.cspublic 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 message type arkivmelding.
For this example to work, we have created a class Arkivmelding (based on arkivmelding.xsd). Note that this only includes the required parts of the arkivmelding, so if you want to include other parts, you must do so yourself.
App/logic/EFormidling/EFormidlingMetadata.csusing 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 recipient
The recipient can be set in two ways:
- Statically via
<altinn:receiver>in the BPMN configuration (see table above) - Dynamically by implementing the
IEFormidlingReceiversinterface
If the recipient of a shipment must be set dynamically, a class implementing the IEFormidlingReceivers interface must be created and registered in Program.cs.
App/logic/EFormidling/EFormidlingReceivers.csusing 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);
}
}
Note: Only Norwegian organizations are supported, and the prefix 0192: is required before the organization number.
Adding a feedback task to the application process
Although not strictly necessary, it is recommended to add a feedback task to your application. This is to ensure that the process moves forward when the message has been received. No further changes are necessary once the task has been added, as the eFormidling service we added earlier will automatically move the process forward. If you want to customize the texts presented to the user at this stage, you can do so by overriding the text keys
Ensuring unique filenames
Filenames of attachments sent via eFormidling must be unique. The integration contains logic to guarantee this and may change the filenames slightly before the files are sent.
Testing
Thorough testing of the eFormidling integration in an application is recommended.
Security measures and retry mechanisms are in place to ensure that a shipment reaches the recipient when errors are due to weak network connections.
However, invalid shipments, including but not limited to missing attachments or errors in the "arkivmelding", will cause the shipment to fail without explicit notification to the end user or app owner.
Local
Test environment (TT02)
You can monitor the status of a shipment sent in the test environment via the endpoint below.
https://platform.tt02.altinn.no/eformidling/api/conversations?messageId={instanceGuid}