Intergrating Attcius in a .NET frontend

Atticus can be integrated in .NET that use Windows Forms, WPF, or UWP. This page focuses on the UI integration in .NET applications. The technology used for this integration is WebView2, a browser control that renders web applications in .NET applications.

Prerequisites

Before you start integrating Atticus in your .NET application, make sure you have the following prerequisites:

Set up the WebView2 control

To get started with integrating Atticus in your .NET application, follow these steps:

  1. Create a new .NET Windows Forms application in Visual Studio.

  2. Add the necessary NuGet packages to your project:

    • Microsoft.Web.WebView2
    • Newtonsoft.Json
  3. Add the webview control to your form in the designer:

  • Drag a WebView2 control from the toolbox to your form. See the Microsoft docs for more information
  • Initialize the WebView2 control in the form constructor:
    public Form1()
    {
        InitializeComponent();
        InitializeWebView2Async();
    
        async void InitializeAsync()
        {
            await webView.EnsureCoreWebView2Async(null);
            await createSession();
        }
    
        async Task createSession()
        {
            // Here comes the code to create a session
        }
    }
    

Create an authenticated session

Using the WebView2 control, you can create an authenticated session with Atticus. The idea is to create a session in the background using a POST request with authentication headers. The Atticus Authorization Server will set a cookie that holds the session information. Once the session is created, you can navigate to the Atticus Filler UI. To create an authenticated requeset, you need to include both client credentials in an Authorization header and the user identifier in the X-User-Id header and send a POST request along with session-specific data. More info about this can be found on the authentication page.

Here is an example of how to create a session in a .NET application:

  1. Create a dictionary with the required session data:

    var launchContext = new Dictionary<string, string>
    {
        { "patient", patientId }, // FHIR Patient.id
        { "encounter", encounterId } // FHIR Encounter.id (optional)
    };
    
  2. Build a POST request with the necessary headers:

    var launchContextStream = new MemoryStream(Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(launchContext)));
    var request = webView.CoreWebView2.Environment.CreateWebResourceRequest(
        "https://auth.tiro.health/session",
        "POST",
        launchContextStream,
        null);
    
    // Add authentication header
    string clientId = Environment.GetEnvironmentVariable("CLIENT_ID");
    string clientSecret = Environment.GetEnvironmentVariable("CLIENT_SECRET");
    var authToken = Encoding.ASCII.GetBytes($"{clientId}:{clientSecret}");
    var authHeader = $"Basic {Convert.ToBase64String(authToken)}";
    request.Headers.SetHeader("Authorization", authHeader);
    
    // Add content-type header
    request.Headers.SetHeader("Content-Type", "application/fhir+json");
    
    // Add user identification header
    request.Headers.SetHeader("x-user-id", userIdentifier);
    
  3. Send the request and handle the response:

    webView.CoreWebView2.NavigateWithWebResourceRequest(request);
    webView.CoreWebView2.NavigationCompleted += (sender, args) =>
    {
        if (args.IsSuccess)
        {
            // Navigate to the Atticus Filler UI
            webView.CoreWebView2.Navigate("https://app.tiro.health/reports/edit?response=QuestionnaireResponse/123");
        }
    };
    

After completing these steps, you should have a working WebView2 control that can be used to display the Atticus Filler UI in your .NET application.

Demo repository

A demo repository with a working example can be found here. The code that creates the session can be found here

Receive real-time updates of the form state

Atticus can send realtime updates of the form state as FHIR QuestionnaireResponse resources. The realtime updates are sent using message events. The messaging protocol is based on SMART Web Messaging.

To make this integration easier we have created a package that handles the SMART Web Messages and generates events. If a resource is changed (create or update) the SmartMessageHandler fires a ResourceChangedEvent containing the changed resource. Here are the steps to setup the message handler:

  1. Add the message handler to your form class and subscribe to the ResourceChangedEvent:

    this.MessageHandler = new SmartMessageHandler();
    this.MessageHandler.ResourceChanged += ResourceChanged;
    


    The ResourceChanged handler is a method that will receive the changed resources. We'll implement it later.

    private void ResourceChanged(object sender, ResourceChangedEventArgs e)
    {
        // Handle the resource change here
    }
    
  2. Subscribe to the SMARTWebMessages by creating an event handler and passing it to the message handler.

    await webView.EnsureCoreWebView2Async();
    webView.CoreWebView2.WebMessageReceived += SMARTWebMessageReceived;
    
    private void SMARTWebMessageReceived(object sender, CoreWebView2WebMessageReceivedEventArgs e)
    {
        // Handle the incoming message here
        string responseJson = this.MessageHandler.HandleMessage(e.WebMessageAsJson);
    
        // Send the response back to the web content
        webView.CoreWebView2.PostWebMessageAsJson(responseJson);
    }
    
  3. Handle the ResourceChangedEvent by implementing the ResourceChanged method.

    private void ResourceChanged(object sender, ResourceChangedEventArgs e)
    {
        if (e.Resource.TypeName == "QuestionnaireResponse")
        {
            QuestionnaireResponse questionnaireResponse = e.Resource as QuestionnaireResponse;
        }
    }
    

Demo repository

A demo repository with a working example can be found here.

Was this page helpful?