refactoring some of codes
All checks were successful
Build and Deploy LSFE / build-and-deploy (push) Successful in 1m43s
All checks were successful
Build and Deploy LSFE / build-and-deploy (push) Successful in 1m43s
This commit is contained in:
parent
15656becac
commit
015422a507
2
.gitignore
vendored
2
.gitignore
vendored
@ -361,3 +361,5 @@ MigrationBackup/
|
|||||||
|
|
||||||
# Fody - auto-generated XML schema
|
# Fody - auto-generated XML schema
|
||||||
FodyWeavers.xsd
|
FodyWeavers.xsd
|
||||||
|
|
||||||
|
**/appsettings.Production.json
|
||||||
|
|||||||
12
LSFE.Application/Common/Exceptions/BusinessRuleException.cs
Normal file
12
LSFE.Application/Common/Exceptions/BusinessRuleException.cs
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace LSFE.Application.Common.Exceptions
|
||||||
|
{
|
||||||
|
public class BusinessRuleException : Exception
|
||||||
|
{
|
||||||
|
public BusinessRuleException(string message)
|
||||||
|
: base(message) { }
|
||||||
|
}
|
||||||
|
}
|
||||||
12
LSFE.Application/Common/Exceptions/ForbiddenException.cs
Normal file
12
LSFE.Application/Common/Exceptions/ForbiddenException.cs
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace LSFE.Application.Common.Exceptions
|
||||||
|
{
|
||||||
|
public class ForbiddenException : Exception
|
||||||
|
{
|
||||||
|
public ForbiddenException()
|
||||||
|
: base("You do not have permission to perform this action.") { }
|
||||||
|
}
|
||||||
|
}
|
||||||
12
LSFE.Application/Common/Exceptions/NotFoundException.cs
Normal file
12
LSFE.Application/Common/Exceptions/NotFoundException.cs
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace LSFE.Application.Common.Exceptions
|
||||||
|
{
|
||||||
|
public class NotFoundException : Exception
|
||||||
|
{
|
||||||
|
public NotFoundException(string name, object key)
|
||||||
|
: base($"Entity '{name}' with key '{key}' was not found.") { }
|
||||||
|
}
|
||||||
|
}
|
||||||
12
LSFE.Application/Common/Exceptions/UnauthorizedException.cs
Normal file
12
LSFE.Application/Common/Exceptions/UnauthorizedException.cs
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace LSFE.Application.Common.Exceptions
|
||||||
|
{
|
||||||
|
public class UnauthorizedException : Exception
|
||||||
|
{
|
||||||
|
public UnauthorizedException(string message)
|
||||||
|
: base(message) { }
|
||||||
|
}
|
||||||
|
}
|
||||||
20
LSFE.Application/Common/Exceptions/ValidationException.cs
Normal file
20
LSFE.Application/Common/Exceptions/ValidationException.cs
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
using FluentValidation.Results;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace LSFE.Application.Common.Exceptions
|
||||||
|
{
|
||||||
|
public class ValidationException : Exception
|
||||||
|
{
|
||||||
|
public IDictionary<string, string[]> Errors { get; }
|
||||||
|
|
||||||
|
public ValidationException(IEnumerable<ValidationFailure> failures)
|
||||||
|
: base("One or more validation errors occurred.")
|
||||||
|
{
|
||||||
|
Errors = failures
|
||||||
|
.GroupBy(f => f.PropertyName, f => f.ErrorMessage)
|
||||||
|
.ToDictionary(g => g.Key, g => g.ToArray());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
14
LSFE.Application/Common/Models/ErrorResponse.cs
Normal file
14
LSFE.Application/Common/Models/ErrorResponse.cs
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace LSFE.Application.Common.Models
|
||||||
|
{
|
||||||
|
public class ErrorResponse
|
||||||
|
{
|
||||||
|
public int StatusCode { get; set; }
|
||||||
|
public string Message { get; set; } = string.Empty;
|
||||||
|
public IDictionary<string, string[]>? Errors { get; set; }
|
||||||
|
public string? StackTrace { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
13
LSFE.Application/LSFE.Application.csproj
Normal file
13
LSFE.Application/LSFE.Application.csproj
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>net8.0</TargetFramework>
|
||||||
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="FluentValidation" Version="12.1.1" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
@ -30,7 +30,6 @@ namespace LSFE.Infrastructure.Converter
|
|||||||
}
|
}
|
||||||
else if (reader.TokenType == JsonTokenType.PropertyName)
|
else if (reader.TokenType == JsonTokenType.PropertyName)
|
||||||
{
|
{
|
||||||
// Handle object format if needed
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
6
LSFE.sln
6
LSFE.sln
@ -17,6 +17,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Sql", "Sql", "{F7832112-A88
|
|||||||
EndProject
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LSFE.MobApp", "LSFE.MobApp\LSFE.MobApp.csproj", "{7AD0D34F-BE46-4141-8D95-9870FE8C1FEC}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LSFE.MobApp", "LSFE.MobApp\LSFE.MobApp.csproj", "{7AD0D34F-BE46-4141-8D95-9870FE8C1FEC}"
|
||||||
EndProject
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LSFE.Application", "LSFE.Application\LSFE.Application.csproj", "{478AA6B2-E2AA-4ED5-B266-936F913D4996}"
|
||||||
|
EndProject
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
Debug|Any CPU = Debug|Any CPU
|
Debug|Any CPU = Debug|Any CPU
|
||||||
@ -41,6 +43,10 @@ Global
|
|||||||
{7AD0D34F-BE46-4141-8D95-9870FE8C1FEC}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
{7AD0D34F-BE46-4141-8D95-9870FE8C1FEC}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
{7AD0D34F-BE46-4141-8D95-9870FE8C1FEC}.Release|Any CPU.Build.0 = Release|Any CPU
|
{7AD0D34F-BE46-4141-8D95-9870FE8C1FEC}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
{7AD0D34F-BE46-4141-8D95-9870FE8C1FEC}.Release|Any CPU.Deploy.0 = Release|Any CPU
|
{7AD0D34F-BE46-4141-8D95-9870FE8C1FEC}.Release|Any CPU.Deploy.0 = Release|Any CPU
|
||||||
|
{478AA6B2-E2AA-4ED5-B266-936F913D4996}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{478AA6B2-E2AA-4ED5-B266-936F913D4996}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{478AA6B2-E2AA-4ED5-B266-936F913D4996}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{478AA6B2-E2AA-4ED5-B266-936F913D4996}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
HideSolutionNode = FALSE
|
HideSolutionNode = FALSE
|
||||||
|
|||||||
@ -46,57 +46,43 @@ namespace LSFE.API.Controllers.Account
|
|||||||
public async Task<IActionResult> Login([FromBody] Users model,
|
public async Task<IActionResult> Login([FromBody] Users model,
|
||||||
[FromServices] IAccountService tokenService)
|
[FromServices] IAccountService tokenService)
|
||||||
{
|
{
|
||||||
try
|
var user = await _userManager.FindByNameAsync(model.UserName.ToLower());
|
||||||
{
|
if (user == null)
|
||||||
var user = await _userManager.FindByNameAsync(model.UserName.ToLower());
|
|
||||||
if (user == null)
|
|
||||||
return BadRequest(new Infrastructure.Model.Response
|
|
||||||
{
|
|
||||||
Success = false,
|
|
||||||
MessCode = 0,
|
|
||||||
Message = "Invalid username or password."
|
|
||||||
});
|
|
||||||
|
|
||||||
var signInResult = await _signInManager.CheckPasswordSignInAsync(user, model.Password, false);
|
|
||||||
|
|
||||||
if (signInResult.Succeeded)
|
|
||||||
{
|
|
||||||
await HandleSuccessfulLogin(user);
|
|
||||||
|
|
||||||
var token = await tokenService.CreateToken(user);
|
|
||||||
return Ok(new
|
|
||||||
{
|
|
||||||
token,
|
|
||||||
expiration = DateTime.UtcNow.AddMinutes(30),
|
|
||||||
userId = user.Id,
|
|
||||||
userName = user.UserName,
|
|
||||||
fullName = user.FullName,
|
|
||||||
email = user.Email,
|
|
||||||
phoneNumber = user.PhoneNumber,
|
|
||||||
employeeId = user.EmployeeId,
|
|
||||||
company = user.Company,
|
|
||||||
Success = true,
|
|
||||||
MessCode = 1,
|
|
||||||
Message = "Yehey!"
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return await HandleFailedLogin(user, signInResult);
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
var message = ex.InnerException?.Message ?? ex.Message;
|
|
||||||
return BadRequest(new Infrastructure.Model.Response
|
return BadRequest(new Infrastructure.Model.Response
|
||||||
{
|
{
|
||||||
Success = false,
|
Success = false,
|
||||||
MessCode = 0,
|
MessCode = 0,
|
||||||
Message = message
|
Message = "Invalid username or password."
|
||||||
|
});
|
||||||
|
|
||||||
|
var signInResult = await _signInManager.CheckPasswordSignInAsync(user, model.Password, false);
|
||||||
|
|
||||||
|
if (signInResult.Succeeded)
|
||||||
|
{
|
||||||
|
await HandleSuccessfulLogin(user);
|
||||||
|
|
||||||
|
var token = await tokenService.CreateToken(user);
|
||||||
|
return Ok(new
|
||||||
|
{
|
||||||
|
token,
|
||||||
|
expiration = DateTime.Now.AddMinutes(30),
|
||||||
|
userId = user.Id,
|
||||||
|
userName = user.UserName,
|
||||||
|
fullName = user.FullName,
|
||||||
|
email = user.Email,
|
||||||
|
phoneNumber = user.PhoneNumber,
|
||||||
|
employeeId = user.EmployeeId,
|
||||||
|
company = user.Company,
|
||||||
|
Success = true,
|
||||||
|
MessCode = 1,
|
||||||
|
Message = "Yehey!"
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return await HandleFailedLogin(user, signInResult);
|
||||||
}
|
}
|
||||||
protected async Task HandleSuccessfulLogin(AppsUsers user)
|
protected async Task HandleSuccessfulLogin(AppsUsers user)
|
||||||
{
|
{
|
||||||
// Unlock if necessary
|
|
||||||
if (user.LockoutEnabled || user.LockoutEnd != null)
|
if (user.LockoutEnabled || user.LockoutEnd != null)
|
||||||
{
|
{
|
||||||
await _userManager.SetLockoutEnabledAsync(user, false);
|
await _userManager.SetLockoutEnabledAsync(user, false);
|
||||||
@ -104,13 +90,11 @@ namespace LSFE.API.Controllers.Account
|
|||||||
await _userManager.UpdateAsync(user);
|
await _userManager.UpdateAsync(user);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reset failed attempts
|
|
||||||
await _userManager.ResetAccessFailedCountAsync(user);
|
await _userManager.ResetAccessFailedCountAsync(user);
|
||||||
}
|
}
|
||||||
protected async Task<IActionResult> HandleFailedLogin(AppsUsers user,
|
protected async Task<IActionResult> HandleFailedLogin(AppsUsers user,
|
||||||
Microsoft.AspNetCore.Identity.SignInResult signInResult)
|
Microsoft.AspNetCore.Identity.SignInResult signInResult)
|
||||||
{
|
{
|
||||||
// Increment failed attempts
|
|
||||||
await _userManager.AccessFailedAsync(user);
|
await _userManager.AccessFailedAsync(user);
|
||||||
|
|
||||||
if (user.AccessFailedCount > 3 || signInResult.IsLockedOut)
|
if (user.AccessFailedCount > 3 || signInResult.IsLockedOut)
|
||||||
|
|||||||
@ -15,92 +15,24 @@ namespace LSFE.API.Controllers
|
|||||||
{
|
{
|
||||||
private readonly IWebHostEnvironment _env;
|
private readonly IWebHostEnvironment _env;
|
||||||
private readonly IUnitOfWork _unitOfWork;
|
private readonly IUnitOfWork _unitOfWork;
|
||||||
// public IConfiguration _configuration;
|
|
||||||
public BaseController(IUnitOfWork unitOfWork,
|
public BaseController(IUnitOfWork unitOfWork,
|
||||||
IWebHostEnvironment env)
|
IWebHostEnvironment env)
|
||||||
{
|
{
|
||||||
_unitOfWork = unitOfWork;
|
_unitOfWork = unitOfWork;
|
||||||
_env = env;
|
_env = env;
|
||||||
// _configuration = configuration;
|
|
||||||
}
|
}
|
||||||
/* [NonAction]
|
|
||||||
[AllowAnonymous]
|
|
||||||
[HttpPost("{EMailTemplate}")]
|
|
||||||
public string EMailTemplate(string relativePath, string emailTemplate)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
string templateFolderPath = Path.Combine(_webHostEnvironment.ContentRootPath, relativePath);
|
|
||||||
string templateFilePath = Path.Combine(templateFolderPath, emailTemplate);
|
|
||||||
|
|
||||||
if (System.IO.File.Exists(templateFilePath))
|
|
||||||
{
|
|
||||||
string body = System.IO.File.ReadAllText(templateFilePath);
|
|
||||||
return body;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Console.WriteLine($"File not found: {templateFilePath}");
|
|
||||||
return "Template file not found";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
var errorMessage = ex.ToString() ?? ex.InnerException.ToString();
|
|
||||||
*//* PostErrorMessage(errorMessage, "WebApi");*//*
|
|
||||||
throw;
|
|
||||||
}
|
|
||||||
}*/
|
|
||||||
/* [NonAction]
|
|
||||||
[AllowAnonymous]
|
|
||||||
[HttpPost("{GetRelativePath}")]
|
|
||||||
public string GetRelativePath(string relativePath)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
string templateFolderPath = Path.Combine(_webHostEnvironment.ContentRootPath, relativePath);
|
|
||||||
return templateFolderPath;
|
|
||||||
}
|
|
||||||
catch (Exception)
|
|
||||||
{
|
|
||||||
throw;
|
|
||||||
}
|
|
||||||
}*/
|
|
||||||
/* [NonAction]
|
|
||||||
[HttpPost("{ErrMessage}")]
|
|
||||||
public async Task PostErrorMessage(string errMessage, string appName)
|
|
||||||
{
|
|
||||||
var errorMessage = new ErrorMessage
|
|
||||||
{
|
|
||||||
CreatedDate = DateTime.Now,
|
|
||||||
Message = errMessage,
|
|
||||||
Application = appName,
|
|
||||||
CreatedBy = appName
|
|
||||||
|
|
||||||
};
|
|
||||||
await ErrorMessageService.PostErrorMessage(errorMessage);
|
|
||||||
}*/
|
|
||||||
[NonAction]
|
[NonAction]
|
||||||
[HttpPost("{ErrorHandling}")]
|
[HttpPost("{ErrorHandling}")]
|
||||||
protected async Task<IActionResult> ExecuteWithErrorHandling<T>(
|
protected async Task<IActionResult> ExecuteWithErrorHandling<T>(
|
||||||
Func<Task<T>> operation, string methodName, bool isPost)
|
Func<Task<T>> operation, string methodName, bool isPost)
|
||||||
{
|
{
|
||||||
try
|
var result = await operation();
|
||||||
|
if (isPost)
|
||||||
{
|
{
|
||||||
var result = await operation();
|
return Ok(new { success = true, messCode = 1, message = "Operation completed successfully", data = result });
|
||||||
if (isPost)
|
|
||||||
{
|
|
||||||
return Ok(new { success = true, messCode = 1, message = "Operation completed successfully", data = result });
|
|
||||||
}
|
|
||||||
return Ok(result);
|
|
||||||
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
var errorMessage = ex.InnerException?.ToString() ?? ex.Message.ToString();
|
|
||||||
// await PostErrorMessage(errorMessage, $"WebApi {methodName}");
|
|
||||||
return BadRequest(new { success = false, messCode = 0, message = errorMessage });
|
|
||||||
}
|
}
|
||||||
|
return Ok(result);
|
||||||
}
|
}
|
||||||
[NonAction]
|
[NonAction]
|
||||||
public async Task<IActionResult> LogAndReturnBadRequest(string message, string? userId)
|
public async Task<IActionResult> LogAndReturnBadRequest(string message, string? userId)
|
||||||
|
|||||||
@ -110,21 +110,12 @@ namespace LSFE.API.Controllers
|
|||||||
[HttpGet("inventory")]
|
[HttpGet("inventory")]
|
||||||
public async Task<IActionResult> GetInventory([FromQuery] InventoryDto dto)
|
public async Task<IActionResult> GetInventory([FromQuery] InventoryDto dto)
|
||||||
{
|
{
|
||||||
try
|
var inventory = await _unitOfWork.Inventory.GetAllAsync();
|
||||||
{
|
var filtered = dto.UserRole == "ADMIN" || dto.UserRole == "DSM"
|
||||||
var inventory = await _unitOfWork.Inventory.GetAllAsync();
|
? inventory.Where(i => i.IsActive)
|
||||||
var filtered = dto.UserRole == "ADMIN" || dto.UserRole == "DSM"
|
: inventory.Where(i => i.IsActive && i.MedRepName == dto.UpdatedBy);
|
||||||
? inventory.Where(i => i.IsActive)
|
|
||||||
: inventory.Where(i => i.IsActive && i.MedRepName == dto.UpdatedBy);
|
|
||||||
|
|
||||||
return Ok(filtered);
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
ex.ToString();
|
|
||||||
throw;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
return Ok(filtered);
|
||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
}
|
}
|
||||||
|
|||||||
@ -99,10 +99,8 @@ namespace LSFE.API.Controllers
|
|||||||
}
|
}
|
||||||
else if (dto.ProductId == 0 || dto.ProductId == null)
|
else if (dto.ProductId == 0 || dto.ProductId == null)
|
||||||
{
|
{
|
||||||
// Only generate GUID for new products without file
|
|
||||||
dto.ProductLink = Guid.NewGuid().ToString();
|
dto.ProductLink = Guid.NewGuid().ToString();
|
||||||
}
|
}
|
||||||
// For updates without new file, keep existing ProductLink
|
|
||||||
|
|
||||||
var response = await _unitOfWork.Products.AddOrUpdateAsync(dto);
|
var response = await _unitOfWork.Products.AddOrUpdateAsync(dto);
|
||||||
if (response.Success)
|
if (response.Success)
|
||||||
@ -215,32 +213,22 @@ namespace LSFE.API.Controllers
|
|||||||
}
|
}
|
||||||
|
|
||||||
[HttpGet("productFile/{fileName}")]
|
[HttpGet("productFile/{fileName}")]
|
||||||
[ResponseCache(Duration = 3600)] // Cache for 1 hour
|
[ResponseCache(Duration = 3600)]
|
||||||
public async Task<IActionResult> GetProductFile(string fileName)
|
public async Task<IActionResult> GetProductFile(string fileName)
|
||||||
{
|
{
|
||||||
try
|
if (string.IsNullOrWhiteSpace(fileName) || fileName.Contains(".."))
|
||||||
{
|
{
|
||||||
// Validate filename
|
return BadRequest("Invalid file name");
|
||||||
if (string.IsNullOrWhiteSpace(fileName) || fileName.Contains(".."))
|
|
||||||
{
|
|
||||||
return BadRequest("Invalid file name");
|
|
||||||
}
|
|
||||||
|
|
||||||
var uploadsPath = Path.Combine(_env.WebRootPath, "Content/Uploads", "Materials");
|
|
||||||
var filePath = Path.Combine(uploadsPath, fileName);
|
|
||||||
|
|
||||||
ContentTypeHelper.ValidateFile(filePath, uploadsPath);
|
|
||||||
|
|
||||||
// Stream the file instead of loading entirely into memory
|
|
||||||
var fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read);
|
|
||||||
var contentType = ContentTypeHelper.GetContentType(fileName);
|
|
||||||
|
|
||||||
return File(fileStream, contentType, fileName, enableRangeProcessing: true);
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
return StatusCode(500, "Error retrieving file");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var uploadsPath = Path.Combine(_env.WebRootPath, "Content/Uploads", "Materials");
|
||||||
|
var filePath = Path.Combine(uploadsPath, fileName);
|
||||||
|
|
||||||
|
ContentTypeHelper.ValidateFile(filePath, uploadsPath);
|
||||||
|
var fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read);
|
||||||
|
var contentType = ContentTypeHelper.GetContentType(fileName);
|
||||||
|
|
||||||
|
return File(fileStream, contentType, fileName, enableRangeProcessing: true);
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpGet("areas/{id:int}")]
|
[HttpGet("areas/{id:int}")]
|
||||||
|
|||||||
@ -1,6 +1,5 @@
|
|||||||
using LSFE.Domain.Contracts;
|
using LSFE.Domain.Contracts;
|
||||||
using LSFE.Domain.Helpers;
|
using LSFE.Domain.Helpers;
|
||||||
using LSFE.Infrastructure.Dto;
|
|
||||||
using LSFE.Infrastructure.Dto.Reports;
|
using LSFE.Infrastructure.Dto.Reports;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
|
||||||
|
|||||||
@ -18,6 +18,7 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\LSFE.Application\LSFE.Application.csproj" />
|
||||||
<ProjectReference Include="..\LSFE.Domain\LSFE.Domain.csproj" />
|
<ProjectReference Include="..\LSFE.Domain\LSFE.Domain.csproj" />
|
||||||
<ProjectReference Include="..\LSFE.Infrastructure\LSFE.Infrastructure.csproj" />
|
<ProjectReference Include="..\LSFE.Infrastructure\LSFE.Infrastructure.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|||||||
80
LSFE/Middleware/GlobalExceptionMiddleware.cs
Normal file
80
LSFE/Middleware/GlobalExceptionMiddleware.cs
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
using LSFE.Application.Common.Exceptions;
|
||||||
|
using LSFE.Application.Common.Models;
|
||||||
|
using System.Security.Claims;
|
||||||
|
using System.Text.Json;
|
||||||
|
|
||||||
|
namespace LSFE.API.Middleware
|
||||||
|
{
|
||||||
|
public class GlobalExceptionMiddleware
|
||||||
|
{
|
||||||
|
private readonly RequestDelegate _next;
|
||||||
|
private readonly ILogger<GlobalExceptionMiddleware> _logger;
|
||||||
|
private readonly IHostEnvironment _env;
|
||||||
|
|
||||||
|
public GlobalExceptionMiddleware(
|
||||||
|
RequestDelegate next,
|
||||||
|
ILogger<GlobalExceptionMiddleware> logger,
|
||||||
|
IHostEnvironment env)
|
||||||
|
{
|
||||||
|
_next = next;
|
||||||
|
_logger = logger;
|
||||||
|
_env = env;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task InvokeAsync(HttpContext context)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await _next(context);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_logger.LogError(ex, "Unhandled exception: {Message}", ex.Message);
|
||||||
|
await HandleExceptionAsync(context, ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task HandleExceptionAsync(HttpContext context, Exception ex)
|
||||||
|
{
|
||||||
|
var (statusCode, message, errors) = ex switch
|
||||||
|
{
|
||||||
|
ValidationException e => (StatusCodes.Status422UnprocessableEntity,
|
||||||
|
e.Message, e.Errors),
|
||||||
|
|
||||||
|
NotFoundException e => (StatusCodes.Status404NotFound,
|
||||||
|
e.Message, null),
|
||||||
|
|
||||||
|
UnauthorizedException e => (StatusCodes.Status401Unauthorized,
|
||||||
|
e.Message, null),
|
||||||
|
|
||||||
|
ForbiddenException e => (StatusCodes.Status403Forbidden,
|
||||||
|
e.Message, null),
|
||||||
|
|
||||||
|
BusinessRuleException e => (StatusCodes.Status409Conflict,
|
||||||
|
e.Message, null),
|
||||||
|
|
||||||
|
UnauthorizedAccessException e => (StatusCodes.Status401Unauthorized,
|
||||||
|
e.Message, null),
|
||||||
|
|
||||||
|
OperationCanceledException _ => (StatusCodes.Status499ClientClosedRequest,
|
||||||
|
"Request was cancelled.", null),
|
||||||
|
|
||||||
|
_ => (StatusCodes.Status500InternalServerError,
|
||||||
|
"An unexpected error occurred. Please try again later.", null)
|
||||||
|
};
|
||||||
|
|
||||||
|
var response = new ErrorResponse
|
||||||
|
{
|
||||||
|
StatusCode = statusCode,
|
||||||
|
Message = message,
|
||||||
|
Errors = errors,
|
||||||
|
StackTrace = _env.IsDevelopment() ? ex.StackTrace : null
|
||||||
|
};
|
||||||
|
|
||||||
|
context.Response.ContentType = "application/json";
|
||||||
|
context.Response.StatusCode = statusCode;
|
||||||
|
|
||||||
|
await context.Response.WriteAsJsonAsync(response);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue
Block a user