Skip to content

Commit cb8d0a7

Browse files
author
Vadim Belov
committed
Refactor and extend web API exception classes
- Replace AccessException with AccessDeniedException, supporting custom messages and generic type-based usage. - Add generic versions for BadRequest, Duplicate, EntityNotFound, and Unauthorized exceptions. - Allow custom error messages for all exception types. - Improve XML documentation for clarity and consistency. - Enhances flexibility and type safety for API error handling.
1 parent 8b47f06 commit cb8d0a7

6 files changed

Lines changed: 76 additions & 29 deletions

File tree

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
// SPDX-License-Identifier: MIT
2+
// Copyright (c) 2025–2026 Vadim Belov <https://belov.us>
3+
4+
using System.Net;
5+
6+
namespace EasyExtensions.AspNetCore.Exceptions
7+
{
8+
/// <summary>
9+
/// Represents an exception that is thrown when access to a specified object is denied due to insufficient
10+
/// permissions.
11+
/// </summary>
12+
/// <param name="objectName">The name of the object for which access was denied. This value is used to identify the resource involved in the
13+
/// access violation.</param>
14+
/// <param name="message">The error message that explains the reason for the exception. If not specified, a default message of "Access
15+
/// denied" is used.</param>
16+
public class AccessDeniedException(string objectName, string message = "Access denied")
17+
: WebApiException(HttpStatusCode.Forbidden, objectName, message) { }
18+
19+
/// <summary>
20+
/// Represents an exception that is thrown when access to a resource of type T is denied, typically corresponding to
21+
/// an HTTP 403 Forbidden response.
22+
/// </summary>
23+
/// <typeparam name="T">The type of the resource for which access was denied.</typeparam>
24+
/// <param name="message">The error message that describes the reason for the access denial.</param>
25+
public class AccessDeniedException<T>(string message = "Access denied")
26+
: AccessDeniedException(typeof(T).Name, message) { }
27+
}

Sources/EasyExtensions.AspNetCore/Exceptions/AccessException.cs

Lines changed: 0 additions & 15 deletions
This file was deleted.

Sources/EasyExtensions.AspNetCore/Exceptions/BadRequestException.cs

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,19 @@
66
namespace EasyExtensions.AspNetCore.Exceptions
77
{
88
/// <summary>
9-
/// Represents an exception that is thrown when a request is unauthorized or invalid for a specified object.
9+
/// Represents an exception that is thrown to indicate a bad request (HTTP 400) in a web API operation.
1010
/// </summary>
11-
/// <param name="objectName">The name of the object associated with the unauthorized or invalid request.</param>
12-
public class BadRequestException(string objectName)
13-
: WebApiException(HttpStatusCode.BadRequest, objectName, "Bad request")
14-
{ }
11+
/// <param name="objectName">The name of the object or entity associated with the bad request. This value is used to provide context for the
12+
/// error.</param>
13+
/// <param name="message">The error message that describes the reason for the bad request. The default is "Bad request".</param>
14+
public class BadRequestException(string objectName, string message = "Bad request")
15+
: WebApiException(HttpStatusCode.BadRequest, objectName, message) { }
16+
17+
/// <summary>
18+
/// Represents an exception that is thrown to indicate a bad request error associated with a specific resource type.
19+
/// </summary>
20+
/// <typeparam name="T">The type of the resource or entity related to the bad request.</typeparam>
21+
/// <param name="message">The error message that describes the reason for the bad request. The default is "Bad request".</param>
22+
public class BadRequestException<T>(string message = "Bad request")
23+
: BadRequestException(typeof(T).Name, message) { }
1524
}

Sources/EasyExtensions.AspNetCore/Exceptions/DuplicateException.cs

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,16 @@ namespace EasyExtensions.AspNetCore.Exceptions
1212
/// to indicate that a resource with the specified name already exists. Use this exception to signal duplicate
1313
/// creation attempts in resource management scenarios.</remarks>
1414
/// <param name="objectName">The name of the object that caused the conflict.</param>
15-
public class DuplicateException(string objectName)
16-
: WebApiException(HttpStatusCode.Conflict, objectName, "Object already exists")
17-
{ }
15+
/// <param name="message">The error message that describes the reason for the conflict. The default is "Object already exists."</param>
16+
public class DuplicateException(string objectName, string message = "Object already exists")
17+
: WebApiException(HttpStatusCode.Conflict, objectName, message) { }
18+
19+
/// <summary>
20+
/// Represents an exception that is thrown when an attempt is made to create or add a duplicate object of the
21+
/// specified type.
22+
/// </summary>
23+
/// <typeparam name="T">The type of the object that caused the duplication error.</typeparam>
24+
/// <param name="message">The error message that explains the reason for the exception. The default is "Object already exists."</param>
25+
public class DuplicateException<T>(string message = "Object already exists")
26+
: DuplicateException(typeof(T).Name, message) { }
1827
}

Sources/EasyExtensions.AspNetCore/Exceptions/EntityNotFoundException.cs

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,15 @@ namespace EasyExtensions.AspNetCore.Exceptions
1010
/// </summary>
1111
/// <param name="objectName">The name of the entity that was not found. This value is included in the exception details to identify the
1212
/// missing entity.</param>
13-
public class EntityNotFoundException(string objectName)
14-
: WebApiException(HttpStatusCode.NotFound, objectName, "Entity was not found")
15-
{ }
13+
/// <param name="message">The error message that describes the reason for the exception. The default is "Entity was not found".</param>
14+
public class EntityNotFoundException(string objectName, string message = "Entity was not found")
15+
: WebApiException(HttpStatusCode.NotFound, objectName, message) { }
16+
17+
/// <summary>
18+
/// Represents an exception that is thrown when an entity of the specified type cannot be found.
19+
/// </summary>
20+
/// <typeparam name="T">The type of the entity that was not found.</typeparam>
21+
/// <param name="message">The error message that explains the reason for the exception. If not specified, a default message is used.</param>
22+
public class EntityNotFoundException<T>(string message = "Entity was not found")
23+
: EntityNotFoundException(typeof(T).Name, message) { }
1624
}

Sources/EasyExtensions.AspNetCore/Exceptions/UnauthorizedException.cs

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,16 @@ namespace EasyExtensions.AspNetCore.Exceptions
1212
/// API scenarios to indicate that the caller must authenticate or does not have permission to access the specified
1313
/// resource.</remarks>
1414
/// <param name="objectName">The name of the object or resource for which access was denied.</param>
15-
public class UnauthorizedException(string objectName)
16-
: WebApiException(HttpStatusCode.Unauthorized, objectName, "Unathorized")
17-
{ }
15+
/// <param name="message">The error message that describes the reason for the unauthorized access. The default is "Unathorized".</param>
16+
public class UnauthorizedException(string objectName, string message = "Unathorized")
17+
: WebApiException(HttpStatusCode.Unauthorized, objectName, message) { }
18+
19+
/// <summary>
20+
/// Represents an exception that is thrown when an operation is attempted without the required authorization for a
21+
/// specific resource type.
22+
/// </summary>
23+
/// <typeparam name="T">The type of the resource or entity for which authorization failed.</typeparam>
24+
/// <param name="message">The error message that explains the reason for the exception. The default is "Unathorized".</param>
25+
public class UnauthorizedException<T>(string message = "Unathorized")
26+
: UnauthorizedException(typeof(T).Name, message) { }
1827
}

0 commit comments

Comments
 (0)