using System.Collections.Generic;
using System.Diagnostics;
static public void Main(string[] args)
var exceptions = new Exception[]{
new HubException("storage error", "StorageService", HttpStatusCode.BadRequest),
new HubException("target error", "TargetService"),
new Exception("exception error")
AggregateHubException achex = new(exceptions, "Controller");
Console.WriteLine(achex.Message);
Console.WriteLine($"Status Code: {achex.StatusCode}");
public class AggregateHubException : AggregateException {
public HttpStatusCode StatusCode { get; set; }
public string SourceName { get; set; }
public override string Message { get; }
public AggregateHubException(Exception[] exceptions, string sourceName) : base(exceptions) {
sourceName = $"{Assembly.GetCallingAssembly().FullName.Split(',').First()}.{NameOfCallingClass()}";
this.StatusCode = exceptions.Select(
ex => ex is HubException chex ?
HttpStatusCode.InternalServerError
this.SourceName = sourceName;
this.Message = String.Join(
new string[] { $"[{sourceName}] One or more errors occurred:" }.Concat(
exceptions.Select(ex => ex is HubException chex ?
$"[{chex.SourceName}] {(int)chex.StatusCode}-{chex.StatusCode}: {chex.PureMessage}" :
$"500-InternalServerError: {ex.Message}"))
public static string NameOfCallingClass(){
MethodBase method = new StackFrame(skipFrames, false).GetMethod();
declaringType = method.DeclaringType;
if (declaringType == null)
fullName = declaringType.FullName;
while (declaringType.Module.Name.Equals("mscorlib.dll", StringComparison.OrdinalIgnoreCase));
public class HubException : Exception {
public HttpStatusCode StatusCode { get; set; }
public string SourceName { get; set; }
public override string Message { get; }
public string PureMessage { get; }
public HubException(string message, string sourceName, HttpStatusCode? statusCode = HttpStatusCode.InternalServerError, Exception ex = null) : base(message, ex) {
sourceName = $"{Assembly.GetCallingAssembly().FullName.Split(',').First()}.{sourceName}";
this.StatusCode = statusCode.Value;
this.SourceName = sourceName;
this.PureMessage = message;
this.Message = $"[{sourceName}] {((ex != null) ? ex.Message : message)}";