DeaDo
DeaDo
CC#
Created by DeaDo on 7/23/2024 in #help
✅ ASP.NET Core Environment Variables: missing Parameter "clientSecret" for EntraId
I want to authenticate Users with EntraId & call Downstream-APIs
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddMicrosoftIdentityWebApi(azureAdConfig)
.EnableTokenAcquisitionToCallDownstreamApi()
.AddInMemoryTokenCaches();
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddMicrosoftIdentityWebApi(azureAdConfig)
.EnableTokenAcquisitionToCallDownstreamApi()
.AddInMemoryTokenCaches();
However, I struggle to get my Environment Variables & Secrets working Because this is running in a Container I use Environment Variables. This works fine:
string instance = Environment.GetEnvironmentVariable("ENTRA_INSTANCE") ?? throw new Exception("Missing Environment Variable ENTRA_INSTANCE");
string clientId = Environment.GetEnvironmentVariable("ENTRA_CLIENT_ID") ?? throw new Exception("Missing Environment Variable ENTRA_CLIENT_ID");
string tenantId = Environment.GetEnvironmentVariable("ENTRA_TENANT_ID") ?? throw new Exception("Missing Environment Variable ENTRA_TENANT_ID");
string entraScope = Environment.GetEnvironmentVariable("ENTRA_SCOPES") ?? throw new Exception("Missing Environment Variable ENTRA_SCOPES");
string instance = Environment.GetEnvironmentVariable("ENTRA_INSTANCE") ?? throw new Exception("Missing Environment Variable ENTRA_INSTANCE");
string clientId = Environment.GetEnvironmentVariable("ENTRA_CLIENT_ID") ?? throw new Exception("Missing Environment Variable ENTRA_CLIENT_ID");
string tenantId = Environment.GetEnvironmentVariable("ENTRA_TENANT_ID") ?? throw new Exception("Missing Environment Variable ENTRA_TENANT_ID");
string entraScope = Environment.GetEnvironmentVariable("ENTRA_SCOPES") ?? throw new Exception("Missing Environment Variable ENTRA_SCOPES");
The Compose Secret is in the correct Path in the Container and i add it to config with:
builder.Configuration.AddKeyPerFile(directoryPath: "/run/secrets", optional: false);
builder.Configuration.AddKeyPerFile(directoryPath: "/run/secrets", optional: false);
But i have no idea how to get Auth to work. I have a workaround for the Config that works:
var azureAdConfig = new ConfigurationBuilder()
.AddInMemoryCollection(new Dictionary<string, string>
{
{"AzureAd:Instance", instance},
{"AzureAd:TenantId", tenantId},
{"AzureAd:ClientId", clientId},
{"AzureAd:Scopes", entraScope}
})
.Build();
...
.AddMicrosoftIdentityWebApi(azureAdConfig)
var azureAdConfig = new ConfigurationBuilder()
.AddInMemoryCollection(new Dictionary<string, string>
{
{"AzureAd:Instance", instance},
{"AzureAd:TenantId", tenantId},
{"AzureAd:ClientId", clientId},
{"AzureAd:Scopes", entraScope}
})
.Build();
...
.AddMicrosoftIdentityWebApi(azureAdConfig)
The secret however is not recognized. This error occurs on Request:
System.ArgumentNullException: Value cannot be null. (Parameter 'clientSecret')
System.ArgumentNullException: Value cannot be null. (Parameter 'clientSecret')
23 replies
CC#
Created by DeaDo on 6/26/2024 in #help
UseStaticFiles for HTML
I have generated a Static WebApp from my Markdown Files.
c#
app.UseStaticFiles(new StaticFileOptions
{
FileProvider = new PhysicalFileProvider(Path.Combine(builder.Environment.ContentRootPath, "Documentation")),
RequestPath = "/docs",
});
c#
app.UseStaticFiles(new StaticFileOptions
{
FileProvider = new PhysicalFileProvider(Path.Combine(builder.Environment.ContentRootPath, "Documentation")),
RequestPath = "/docs",
});
I want this to serve the File "Documentation/Userguide.html" if the route is "/docs/Userguide" If i serve it via NGNIX i would configure something like this
location / {
try_files $uri $uri.html $uri/ =404;
}
location / {
try_files $uri $uri.html $uri/ =404;
}
24 replies
CC#
Created by DeaDo on 6/12/2024 in #help
ASP.NET & EntraId: Acquire Token on Behalf of User for Azure Resource Manager
I have 2 Applications - A SPA thats authenticated with MSAL. - A ASP.NET web-api thats secured with Entra Id. I created 2 App-registrations in EntraId and im able to authenticate the User, obtain a Token for Web-API & call the backend. The Backend is using the AzureResourceManager with the ArmClient SDK & DefaultAzureCredentials (with shared secret in environment variables). The ArmClient can access resources if the application registration has permission. Now I want to use the Users Permission from the SPA & OBO Flow to request resources he has access to. However. After struggling with the documentation for 2 days I cant figure out how to do that. https://github.com/Azure-Samples/active-directory-dotnet-native-aspnetcore-v2/tree/master/2.%20Web%20API%20now%20calls%20Microsoft%20Graph this seems closest to what i want to achieve (with ArmClient though, not with GraphAPI) But i have no idea how to obtain the ARM Client in my service & IDK how to authenticate it
1 replies
CC#
Created by DeaDo on 3/13/2023 in #help
Blazor Wasm: Avoiding frequent & slow rerendering of the component
My client is listening to a websocket who is frequently sending dataobjects with 1 image each to the client. The wasm project should display those dataobjects immediately after receiving them (as a card with a image) This makes the UI very laggy I simply run StateHasChanged each time a new object arrives What is the propper way of doing this?
27 replies
CC#
Created by DeaDo on 2/14/2023 in #help
MapPost: Parameters are null
This is my Post endpoint
app.MapPost("/register", (UserRepo userRepo, RegisterDto RegisterDto ) =>
{
...
}
app.MapPost("/register", (UserRepo userRepo, RegisterDto RegisterDto ) =>
{
...
}
When sending a Request with this Payload
{RegisterDto: {Name: "Herbert"}}
{RegisterDto: {Name: "Herbert"}}
the Endpoint is hit, but the Name-Property in RegisterDto is still null with [FromBody] and [AsParameters] i have the same issue
public class RegisterDto
{
public string Name { get; set; }
}
public class RegisterDto
{
public string Name { get; set; }
}
What does the JSON have to look like so that it works?
9 replies
CC#
Created by DeaDo on 1/22/2023 in #help
Inherit from Abstract class: base.Do() vs field.Do
If im using the command Pattern, is there some rule, that says, that i should use base.Do instead of creating a field? Example:
public class Increment : CounterCommand
{

private Counter counter;

public Increment(Counter counter) : base(counter)
{
this.counter = counter;
}

public override void Execute() => counter.Increment();
public override void Undo() => counter.Decrement();
public override void Redo() => counter.Increment();
}
public class Increment : CounterCommand
{

private Counter counter;

public Increment(Counter counter) : base(counter)
{
this.counter = counter;
}

public override void Execute() => counter.Increment();
public override void Undo() => counter.Decrement();
public override void Redo() => counter.Increment();
}
or:
public class Increment : CounterCommand
{
public Increment(Counter counter) : base(counter)
{

}

public override void Execute() => base.counter.Increment();
public override void Undo() => base.counter.Decrement();
public override void Redo() => base.counter.Increment();
}
public class Increment : CounterCommand
{
public Increment(Counter counter) : base(counter)
{

}

public override void Execute() => base.counter.Increment();
public override void Undo() => base.counter.Decrement();
public override void Redo() => base.counter.Increment();
}
Why is the better approach better?
14 replies
CC#
Created by DeaDo on 11/23/2022 in #help
ASP Web-API with MessageBroker - Post was processed, what now?
I'm trying to seperate the ASP Web-API from the workers which interact with the daterbase using RabbitMQ as MessageBroker. Im starting with a CRUD. So the controller got the postrequest, a message was created and and the consumer (worker) saved the object in the db. But the Web-API is supposed to return the Id of the saved object or some error if the worker failed. So how does it get the id from the worker? Should a create a 2nd massage in the worker and make the API-Project subscribe to it? Am i supposed to build this more like CQRS and just inform the User with 200, the post-request was received and inform him again later when the request was processed using a different microservice?
8 replies
CC#
Created by DeaDo on 10/19/2022 in #help
Is there a good way to use a object from Type Type in a generic method?
Type type = typeof(object);
GenericMethod</*use Type here*/>();
Type type = typeof(object);
GenericMethod</*use Type here*/>();
I have a lot of serialized different Objects in a Database along with their typename as string. All of them share the same Interface. Now i want to deserialize all of those to the right Objects. Therefore i created a Application scanner that collects the Types for all those objects. Now i want to compare the typenames and deserialize them in a loop. All of this feels wrong.
private IInterface GetObject(StoredObject storedObject)
{
foreach(var type in TypeList)
{
if(type.Name == storedObject.Type)
return JsonConvert.DeserializeObject</*TheCorrectType*/>(storedObject.ActualObjectData);
}
}
private IInterface GetObject(StoredObject storedObject)
{
foreach(var type in TypeList)
{
if(type.Name == storedObject.Type)
return JsonConvert.DeserializeObject</*TheCorrectType*/>(storedObject.ActualObjectData);
}
}
sth. like this
8 replies
CC#
Created by DeaDo on 10/7/2022 in #help
Best API for low latency
I have a small client application that does simple calculations. Now i want to make it report the results to my asp server. Other clients in the same wifi network should take the results and also work on those calculations. So they have to exchange their results as fast as possible. The rest api is too slow for that though. I thought that a gRPC stream would be more suitable for this Task. UDP maybe? Does a faster API even help even if i want exchange data without a direct ethernet connection?
76 replies
CC#
Created by DeaDo on 10/5/2022 in #help
ASP Minimal API Deserializor - allow Fields
app.MapPost("/update", ((int[] cities, double distance) newBest) =>
app.MapPost("/update", ((int[] cities, double distance) newBest) =>
I want my minimal api to be able to deserialize that tuple. The System.Test cant do that by default though. Typically i fix that with those serializor options, but i dont know how to provide my settings for the minimal api
var serializerOptions = new JsonSerializerOptions { IncludeFields = true };
var serializerOptions = new JsonSerializerOptions { IncludeFields = true };
3 replies
CC#
Created by DeaDo on 10/1/2022 in #help
Why is my code not thread save?
await Task.WhenAll(tasks).ContinueWith(task => Selection());
await Task.WhenAll(tasks).ContinueWith(task => Selection());
is in a loop tasks is a list of tasks which add elements to a list; Selection is a method which edits the list (cuts off the worse results that were delivered when "tasks" were executed) I thought that all tasks are finished when starting Selection() and i start it like this afterwards. But i always get the following error after a few cycles:
System.ArgumentException: 'Destination array was not long enough. Check the destination index, length, and the array's lower bounds. Arg_ParamName_Name'
System.ArgumentException: 'Destination array was not long enough. Check the destination index, length, and the array's lower bounds. Arg_ParamName_Name'
16 replies
CC#
Created by DeaDo on 9/6/2022 in #help
The right HTTP-Verb for assigning things
Using minimal API and im wondering what Http-Verb is appropriate for this. Get seems wrong because i dont get something. I just have 2 IDs in the uri. Entity Framework is using them to assign a different element from table A to table B
3 replies
CC#
Created by DeaDo on 8/27/2022 in #help
Does AsNoTracking improve Performance in this Case?
public async Task<ItemDto?> GetAsync(int id)
{
return await Context.Items.AsNoTracking().Select(i => new ItemDto()
{
Id = i.Id,
Name = i.Name
}).FirstOrDefaultAsync(i => i.Id == id);
}
public async Task<ItemDto?> GetAsync(int id)
{
return await Context.Items.AsNoTracking().Select(i => new ItemDto()
{
Id = i.Id,
Name = i.Name
}).FirstOrDefaultAsync(i => i.Id == id);
}
5 replies
CC#
Created by DeaDo on 8/26/2022 in #help
ASP MinimalAPI Autzhorization
Hey, I would like to know how to create permissions dynamically. I know how to use things like Roles and the Authorized Keyword so far. But in my case, i want to enable deleting/updating entries only to people who created those / or which are related to these entries. For example i have a m:n relation between users and entityA. Right now i have a prop in the "in-between-table" that defines the relation between those. If somebody wants to change the entity, i take the userId in the endpoint and check in a linq querry if the relationship allows that. But this approach seems a bit weird since its in a completely different location than the authorization system of ms-identity and identity-server do those have a feature i could use to make authorization in a better way?
20 replies
CC#
Created by DeaDo on 8/12/2022 in #help
ASP, Identity, Blazor Give Permission for delete to specific users.
In my Database i have a entity that acts like a group for multible users. There is a m:n relation between groups and users(IdentityUser) I want that only users in those groups are able to create/update/delete group related data. Like events in a scheduler or messages in the group-chat. But i can't think of a neat way to prevent other users from adding/deleting things to a group they are not part of. Right now i always get the userId in the controller and then a linq statement checks if there is a user with this Id in the group he wants to access. This feels a bit wrong because i have to make sure that nobody else gets hold of a foreign userId and it's in a different location than the default role based authorization i use.
74 replies