Hulkstance
Hulkstance
CC#
Created by Hulkstance on 7/15/2023 in #help
❔ Key Vault + AppConfiguration usage
@snowy9228, thanks, so I will continue using it that way^^
8 replies
CC#
Created by Hulkstance on 7/15/2023 in #help
❔ Application Insights Health Checks
14 replies
CC#
Created by Hulkstance on 7/15/2023 in #help
❔ Application Insights Health Checks
it's indeed 3rd party
14 replies
CC#
Created by Hulkstance on 7/15/2023 in #help
❔ Application Insights Health Checks
just found the package
14 replies
CC#
Created by Hulkstance on 7/15/2023 in #help
❔ Application Insights Health Checks
14 replies
CC#
Created by Hulkstance on 7/15/2023 in #help
❔ Application Insights Health Checks
oh, thanks
14 replies
CC#
Created by Hulkstance on 3/24/2023 in #help
❔ Trying to use Azure SignalR Service as Backplane and for client affinity (Sticky sessions)
thanks once again ❤️
14 replies
CC#
Created by Hulkstance on 3/24/2023 in #help
❔ Trying to use Azure SignalR Service as Backplane and for client affinity (Sticky sessions)
@TeBeConsulting
14 replies
CC#
Created by Hulkstance on 3/18/2023 in #help
❔ EF Core "upsert" - insert if it doesn't exist, update if it does
public class EventType
{
public Guid Id { get; set; }
public string Name { get; set; } = default!;

public ICollection<GlobalNotificationSettings> GlobalNotificationSettings { get; set; } = default!;
}

public class GlobalNotificationSettings
{
public Guid EventTypeId { get; set; }
public bool InternalNotificationsEnabled { get; set; }
public bool EmailNotificationsEnabled { get; set; }
public bool SmsNotificationsEnabled { get; set; }

public EventType EventType { get; set; } = default!;
}

public class AppDbContext : DbContext
{
public AppDbContext(DbContextOptions<AppDbContext> options)
: base(options)
{
}

public DbSet<EventType> EventTypes => Set<EventType>();
public DbSet<GlobalNotificationSettings> GlobalNotificationSettings => Set<GlobalNotificationSettings>();

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<GlobalNotificationSettings>(entity =>
{
entity.HasKey(gns => gns.EventTypeId);

entity.HasOne(et => et.EventType)
.WithMany(gns => gns.GlobalNotificationSettings)
.HasForeignKey(gns => gns.EventTypeId)
.OnDelete(DeleteBehavior.Cascade);
});
}
}
public class EventType
{
public Guid Id { get; set; }
public string Name { get; set; } = default!;

public ICollection<GlobalNotificationSettings> GlobalNotificationSettings { get; set; } = default!;
}

public class GlobalNotificationSettings
{
public Guid EventTypeId { get; set; }
public bool InternalNotificationsEnabled { get; set; }
public bool EmailNotificationsEnabled { get; set; }
public bool SmsNotificationsEnabled { get; set; }

public EventType EventType { get; set; } = default!;
}

public class AppDbContext : DbContext
{
public AppDbContext(DbContextOptions<AppDbContext> options)
: base(options)
{
}

public DbSet<EventType> EventTypes => Set<EventType>();
public DbSet<GlobalNotificationSettings> GlobalNotificationSettings => Set<GlobalNotificationSettings>();

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<GlobalNotificationSettings>(entity =>
{
entity.HasKey(gns => gns.EventTypeId);

entity.HasOne(et => et.EventType)
.WithMany(gns => gns.GlobalNotificationSettings)
.HasForeignKey(gns => gns.EventTypeId)
.OnDelete(DeleteBehavior.Cascade);
});
}
}
4 replies
CC#
Created by Hulkstance on 3/18/2023 in #help
❔ EF Core "upsert" - insert if it doesn't exist, update if it does
public sealed class UpsertGlobalNotificationSettingsCommand : IRequest
{
public Guid EventTypeId { get; set; }
public bool InternalNotificationsEnabled { get; set; }
public bool EmailNotificationsEnabled { get; set; }
public bool SmsNotificationsEnabled { get; set; }
}

public sealed class UpsertGlobalNotificationSettingsCommandHandler : IRequestHandler<UpsertGlobalNotificationSettingsCommand>
{
private readonly AppDbContext _dbContext;

public UpsertGlobalNotificationSettingsCommandHandler(AppDbContext dbContext)
{
_dbContext = dbContext;
}

public async Task Handle(UpsertGlobalNotificationSettingsCommand request, CancellationToken cancellationToken)
{
var existingSettings = await _dbContext.GlobalNotificationSettings.FindAsync(new object[] { request.EventTypeId }, cancellationToken);

if (existingSettings == null)
{
var entity = new GlobalNotificationSettings
{
EventTypeId = request.EventTypeId,
InternalNotificationsEnabled = request.InternalNotificationsEnabled,
EmailNotificationsEnabled = request.EmailNotificationsEnabled,
SmsNotificationsEnabled = request.SmsNotificationsEnabled
};

_dbContext.GlobalNotificationSettings.Add(entity);
}
else
{
existingSettings.InternalNotificationsEnabled = request.InternalNotificationsEnabled;
existingSettings.EmailNotificationsEnabled = request.EmailNotificationsEnabled;
existingSettings.SmsNotificationsEnabled = request.SmsNotificationsEnabled;
}

await _dbContext.SaveChangesAsync(cancellationToken);
}
}
public sealed class UpsertGlobalNotificationSettingsCommand : IRequest
{
public Guid EventTypeId { get; set; }
public bool InternalNotificationsEnabled { get; set; }
public bool EmailNotificationsEnabled { get; set; }
public bool SmsNotificationsEnabled { get; set; }
}

public sealed class UpsertGlobalNotificationSettingsCommandHandler : IRequestHandler<UpsertGlobalNotificationSettingsCommand>
{
private readonly AppDbContext _dbContext;

public UpsertGlobalNotificationSettingsCommandHandler(AppDbContext dbContext)
{
_dbContext = dbContext;
}

public async Task Handle(UpsertGlobalNotificationSettingsCommand request, CancellationToken cancellationToken)
{
var existingSettings = await _dbContext.GlobalNotificationSettings.FindAsync(new object[] { request.EventTypeId }, cancellationToken);

if (existingSettings == null)
{
var entity = new GlobalNotificationSettings
{
EventTypeId = request.EventTypeId,
InternalNotificationsEnabled = request.InternalNotificationsEnabled,
EmailNotificationsEnabled = request.EmailNotificationsEnabled,
SmsNotificationsEnabled = request.SmsNotificationsEnabled
};

_dbContext.GlobalNotificationSettings.Add(entity);
}
else
{
existingSettings.InternalNotificationsEnabled = request.InternalNotificationsEnabled;
existingSettings.EmailNotificationsEnabled = request.EmailNotificationsEnabled;
existingSettings.SmsNotificationsEnabled = request.SmsNotificationsEnabled;
}

await _dbContext.SaveChangesAsync(cancellationToken);
}
}
4 replies
CC#
Created by Hulkstance on 3/11/2023 in #help
❔ ERD Review
erDiagram
User ||--o{ UserEventNotification : "has"
Tenant ||--o{ User : "has"
UserEventNotification ||--|{ Event : "for"
UserEventNotification ||--o{ AlertTone : "uses"
GlobalNotificationType ||--o{ Event : "for"

User {
string UserId
string Email
string Phone
string TenantId
}
Tenant {
string TenantId
string Name
}
Event {
string EventId
string EventName
}
AlertTone {
string AlertToneId
string AlertToneName
string AlertToneUrl
}
UserEventNotification {
string UserEventNotificationId
string UserId
string EventId
boolean InAppNotification
boolean EmailNotification
boolean SmsNotification
string AlertToneId
}
GlobalNotificationType {
string GlobalNotificationTypeId
string EventId
boolean InAppNotification
boolean EmailNotification
boolean SmsNotification
}
erDiagram
User ||--o{ UserEventNotification : "has"
Tenant ||--o{ User : "has"
UserEventNotification ||--|{ Event : "for"
UserEventNotification ||--o{ AlertTone : "uses"
GlobalNotificationType ||--o{ Event : "for"

User {
string UserId
string Email
string Phone
string TenantId
}
Tenant {
string TenantId
string Name
}
Event {
string EventId
string EventName
}
AlertTone {
string AlertToneId
string AlertToneName
string AlertToneUrl
}
UserEventNotification {
string UserEventNotificationId
string UserId
string EventId
boolean InAppNotification
boolean EmailNotification
boolean SmsNotification
string AlertToneId
}
GlobalNotificationType {
string GlobalNotificationTypeId
string EventId
boolean InAppNotification
boolean EmailNotification
boolean SmsNotification
}
3 replies
CC#
Created by Hulkstance on 2/20/2023 in #help
❔ React Redux SignalR
import {
HttpTransportType,
HubConnectionBuilder,
LogLevel,
} from "@microsoft/signalr";
import { Table } from "antd";
import { useEffect, useState } from "react";
import { useDispatch } from "react-redux";
import { addStock, Stock } from "../store/stockSlice";

const connection = new HubConnectionBuilder()
.withUrl("https://localhost:5001/stockticker", {
skipNegotiation: true,
transport: HttpTransportType.WebSockets,
})
.configureLogging(LogLevel.Information)
.withAutomaticReconnect()
.build();

const Grid = () => {
const dispatch = useDispatch();
const [stocks, setStocks] = useState<Stock[]>([]);

useEffect(() => {
async function start() {
try {
await connection.start();

const reader = await connection.invoke("getStockTickerStream");
while (true) {
const { done, value } = await reader.read();
if (done) {
break;
}
dispatch(addStock(value));
setStocks((prevStocks) => [...prevStocks, value]);
}
} catch (err) {
console.error(err);
}
}

start();

return () => {
// connection.stop();
};
}, [dispatch]);

return (
<Table dataSource={stocks}>
<Table.Column title="Symbol" dataIndex="symbol" key="symbol" />
<Table.Column title="Price" dataIndex="price" key="price" />
</Table>
);
};

export default Grid;
import {
HttpTransportType,
HubConnectionBuilder,
LogLevel,
} from "@microsoft/signalr";
import { Table } from "antd";
import { useEffect, useState } from "react";
import { useDispatch } from "react-redux";
import { addStock, Stock } from "../store/stockSlice";

const connection = new HubConnectionBuilder()
.withUrl("https://localhost:5001/stockticker", {
skipNegotiation: true,
transport: HttpTransportType.WebSockets,
})
.configureLogging(LogLevel.Information)
.withAutomaticReconnect()
.build();

const Grid = () => {
const dispatch = useDispatch();
const [stocks, setStocks] = useState<Stock[]>([]);

useEffect(() => {
async function start() {
try {
await connection.start();

const reader = await connection.invoke("getStockTickerStream");
while (true) {
const { done, value } = await reader.read();
if (done) {
break;
}
dispatch(addStock(value));
setStocks((prevStocks) => [...prevStocks, value]);
}
} catch (err) {
console.error(err);
}
}

start();

return () => {
// connection.stop();
};
}, [dispatch]);

return (
<Table dataSource={stocks}>
<Table.Column title="Symbol" dataIndex="symbol" key="symbol" />
<Table.Column title="Price" dataIndex="price" key="price" />
</Table>
);
};

export default Grid;
How do I spawn the SignalR connection correctly and maintain it? Grid.tsx is the problematic code. It's completely wrong
5 replies
CC#
Created by Hulkstance on 2/20/2023 in #help
❔ React Redux SignalR
configureStore.ts
import { configureStore } from "@reduxjs/toolkit";
import stockReducer from "./stockSlice";

export const store = configureStore({
reducer: {
stock: stockReducer,
},
});

// Infer the `RootState` and `AppDispatch` types from the store itself
export type RootState = ReturnType<typeof store.getState>;

// Inferred type: {stock: StockState}
export type AppDispatch = typeof store.dispatch;
import { configureStore } from "@reduxjs/toolkit";
import stockReducer from "./stockSlice";

export const store = configureStore({
reducer: {
stock: stockReducer,
},
});

// Infer the `RootState` and `AppDispatch` types from the store itself
export type RootState = ReturnType<typeof store.getState>;

// Inferred type: {stock: StockState}
export type AppDispatch = typeof store.dispatch;
stockSlice.ts
import { createSlice, PayloadAction } from "@reduxjs/toolkit";

export type Stock = Readonly<{
symbol: string;
price: number;
}>;

export type StockState = Readonly<{
stocks: Stock[];
}>;

const initialState: StockState = {
stocks: [],
};

const stockSlice = createSlice({
name: "stock",
initialState: initialState,
reducers: {
addStock(state, action: PayloadAction<Stock>) {
state.stocks.push(action.payload);
},
},
});

export const { addStock } = stockSlice.actions;

export default stockSlice.reducer;
import { createSlice, PayloadAction } from "@reduxjs/toolkit";

export type Stock = Readonly<{
symbol: string;
price: number;
}>;

export type StockState = Readonly<{
stocks: Stock[];
}>;

const initialState: StockState = {
stocks: [],
};

const stockSlice = createSlice({
name: "stock",
initialState: initialState,
reducers: {
addStock(state, action: PayloadAction<Stock>) {
state.stocks.push(action.payload);
},
},
});

export const { addStock } = stockSlice.actions;

export default stockSlice.reducer;
hooks.ts
import type { RootState, AppDispatch } from './configureStore';
import { useDispatch, useSelector, type TypedUseSelectorHook } from 'react-redux';

// Use throughout your app instead of plain `useDispatch` and `useSelector`
export const useAppDispatch = () => useDispatch<AppDispatch>();
export const useAppSelector: TypedUseSelectorHook<RootState> = useSelector;
import type { RootState, AppDispatch } from './configureStore';
import { useDispatch, useSelector, type TypedUseSelectorHook } from 'react-redux';

// Use throughout your app instead of plain `useDispatch` and `useSelector`
export const useAppDispatch = () => useDispatch<AppDispatch>();
export const useAppSelector: TypedUseSelectorHook<RootState> = useSelector;
5 replies
CC#
Created by Hulkstance on 1/29/2023 in #help
❔ FluentValidation on startup
I'm so dumb, forgot to uncomment builder.Services.AddValidatorsFromAssemblyContaining<Program>();
5 replies
CC#
Created by Hulkstance on 1/29/2023 in #help
❔ FluentValidation on startup
builder.Services.AddOptions<BinanceConfiguration>()
.BindConfiguration("Exchanges:Binance")
.ValidateFluentValidation()
.ValidateOnStart();
builder.Services.AddOptions<BinanceConfiguration>()
.BindConfiguration("Exchanges:Binance")
.ValidateFluentValidation()
.ValidateOnStart();
5 replies
CC#
Created by Hulkstance on 1/29/2023 in #help
❔ FluentValidation on startup
public class BinanceConfigurationValidator : AbstractValidator<BinanceConfiguration>
{
public BinanceConfigurationValidator()
{
RuleFor(x => x.PollingInterval).GreaterThan(0);

RuleForEach(x => x.Accounts)
.ChildRules(account =>
{
account.RuleFor(c => c.Name).NotEmpty().NotNull();
});
}
}
public class BinanceConfigurationValidator : AbstractValidator<BinanceConfiguration>
{
public BinanceConfigurationValidator()
{
RuleFor(x => x.PollingInterval).GreaterThan(0);

RuleForEach(x => x.Accounts)
.ChildRules(account =>
{
account.RuleFor(c => c.Name).NotEmpty().NotNull();
});
}
}
5 replies
CC#
Created by Hulkstance on 12/25/2022 in #help
Swagger Doc failed
@AntonC agreed, I actually use Nuke myself but that's a project I wanted to run
28 replies