How do I make an Update call to a Digital Twin with the SDK from a C# program running on a Docker container?

Samuel Bidó 0 Reputation points
2025-06-17T04:02:00.68+00:00

I'm trying to display the local state of a SCADA system (i.e. machines on or off) on a Digital Twin 3D scene. I already tested that 3D scene.

I made a .NET program that retrieves the data from the SCADA Server through a REST API and then runs await client.UpdateDigitalTwinAsync(id, patch); to update the state of the specified digital twin. But this gives me a 403 Forbidden error.

The program is running on the dotnet:9.0 Docker image so I used environment variables for the credentials with Docker Compose.

I've created the App Registration, which is where I got the credentials from, gave the registration Read/Write API access to Digital Twins and added to my user the Azure Digital Twins Data Owner role.

If I get to publish the state to the digital twin I believe I'll be set for the project. Please help as my undergrad depends on this.

Here's the code for the program:

// See https://aka.ms/new-console-template for more information

using System.Text.Json;
using System.Text.Json.Serialization;
using Azure;
using Azure.DigitalTwins.Core;
using Azure.Identity;

Console.WriteLine("Azure Digital Twins publisher started.");

HttpClient httpClient = new()
{
	BaseAddress = new Uri($"http://{Environment.GetEnvironmentVariable("CONTROLLER_HOST")}:{Environment.GetEnvironmentVariable("CONTROLLER_PORT")}"),
};

async Task<T> queryDeviceState<T>(string id)
{
	var url = new Uri($"{httpClient.BaseAddress.AbsoluteUri}status/{id}");
	Console.WriteLine(url.AbsolutePath);
	return JsonSerializer.Deserialize<T>(await httpClient.GetAsync(url.AbsolutePath).Result.Content.ReadAsStringAsync());
}

string adtInstanceUrl = $"https://{Environment.GetEnvironmentVariable("DIGITAL_TWINS_INSTANCE")}"; 

var credential = new EnvironmentCredential();
var client = new DigitalTwinsClient(new Uri(adtInstanceUrl), credential);

async Task publishToTwin(string id, DeviceState state)
{
	var patch = new JsonPatchDocument();
	patch.AppendAdd("/id", state.id);
	patch.AppendAdd("/isOn", state.isOn);

	await client.UpdateDigitalTwinAsync(id, patch);
}

while (true)
{
	string[] twins = ["a1", "a2", "c1", "c2"];

	foreach (string deviceId in twins)
	{
		DeviceState state = await queryDeviceState<DeviceState>(deviceId);

		DeviceState example = new DeviceState("a3",true);

		Console.WriteLine("Should look like:");
		Console.WriteLine($"{example.id} is {example.isOn}");

		Console.WriteLine($"{state.id} is {state.isOn}");
		await publishToTwin(id: deviceId, state: state);
	}

	Thread.Sleep(int.Parse(Environment.GetEnvironmentVariable("UPDATE_PERIOD") ?? "2000"));
}

struct DeviceState
{
	[JsonPropertyName("id")]
	public string id { get; set; }
	[JsonPropertyName("isOn")]
	public bool isOn { get; set; }

	public DeviceState(string id, bool isOn)
	{
		this.id = id;
		this.isOn = isOn;
	}
}
Azure Digital Twins
Azure Digital Twins
An Azure platform that is used to create digital representations of real-world things, places, business processes, and people.
236 questions
{count} votes

1 answer

Sort by: Most helpful
  1. VSawhney 800 Reputation points Microsoft External Staff Moderator
    2025-06-17T06:33:05.81+00:00

    Hello Samuel Bidó,

    It looks like you're running into a 403 Forbidden error when trying to update your Digital Twin using the .NET SDK in your Docker container. Let's break down a few things to troubleshoot this.

    1. Permissions Check: Ensure that your App Registration has the necessary permissions. You've mentioned that you've assigned the "Azure Digital Twins Data Owner" role to your user, but make sure that the App Registration also has the appropriate permissions set up in the Azure portal under "API permissions" for Azure Digital Twins. Sometimes it might require admin consent for the permissions to take effect.
    2. Environment Variables: Since you're using Docker, double-check that your environment variables containing the credentials and other relevant information are correctly set in your docker-compose.yml. Make sure that the variables you are trying to access (like DIGITAL_TWINS_INSTANCE) are being passed correctly into the Docker container.
    3. Service Principal Authentication: If you're running the application in a non-interactive environment (like from a Docker container), make sure you're using the correct method to authenticate. You might want to consider using a client secret or certificate-based authentication instead of environment variables for the credentials.
    4. Endpoint and Instance: Double-check the adtInstanceUrl to ensure it points to the correct Azure Digital Twins instance URL.
    5. Rate Limits and Throttling: While less likely, keep in mind that Azure subscription limits or throttling could also be a reason for the error. Check your Azure subscription's usage and look for any limits on requests or updates.
    6. Logs and Trace: If possible, enable logging within your application to get more insight into what's happening when it attempts to make that update call. This could also help to identify if there are issues with the payload being sent in the request.

    Hope this helps!
    Thank you!

    0 comments No comments

Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.