В .NET есть простой способ скрыть внутреннюю кухню и оставить только то, что важно потребителю API. Атрибут
StackTraceHiddenAttribute помечает методы, которые не должны попадать в публичный стектрейс, при этом логика выполнения не меняется.Пример:
public static class UserService
{
[StackTraceHidden]
private static void ValidateName(string name)
{
if (string.IsNullOrWhiteSpace(name))
throw new ArgumentException("Name cannot be empty");
}
public static void CreateUser(string name)
{
ValidateName(name);
Console.WriteLine("Created user " + name);
}
}
В этом примере при исключении из
ValidateName в стектрейсе вы увидите только вызов UserService.CreateUser. Валидационный хелпер скрыт атрибутом, поэтому внешний разработчик не видит внутренний слой проверки.#sharp_view
Please open Telegram to view this post
VIEW IN TELEGRAM
👍24🥰2❤1
Когда в проекте десятки эндпоинтов, разъезжающий по коду try catch быстро превращается в свалку. Гораздо проще один раз настроить глобальный маппинг исключений в HTTP статус и возвращать нормальные ProblemDetails для всех ошибок.
ASP.NET уже умеет работать с ProblemDetails из коробки, нужно только включить службу и повесить обработчик ошибок.
В примере вся логика перевода исключений в HTTP ответы живет в одном месте:
builder.Services.AddProblemDetails();
var app = builder.Build();
app.UseExceptionHandler(appErr =>
{
appErr.Run(async ctx =>
{
var ex = ctx.Features.Get<IExceptionHandlerFeature>()?.Error;
var (status, title) = ex switch
{
ConcurrencyException => (StatusCodes.Status409Conflict, "Concurrency conflict"),
NotFoundException => (StatusCodes.Status404NotFound, "Resource not found"),
_ => (StatusCodes.Status500InternalServerError, "Server error")
};
ctx.Response.StatusCode = status;
await ctx.Response.WriteAsJsonAsync(new ProblemDetails
{
Status = status,
Title = title,
Detail = app.Environment.IsDevelopment() ? ex?.Message : null,
Instance = ctx.Request.Path
});
});
});
Любые новые исключения добавляются через одну запись в switch, без походов по контроллерам, а все ответы об ошибках приходят в едином формате application/problem+json, что упрощает жизнь фронту и интеграциям.
📍 Навигация: Вакансии • Задачи • Собесы
#sharp_view
Please open Telegram to view this post
VIEW IN TELEGRAM
❤22👍14
⏳ GetElapsedTime вместо ручного Stopwatch шаблона
Многие до сих пор измеряют время в .NET по старинке создают экземпляр Stopwatch, вызывают Start, ждут выполнение и читают Elapsed.
Но есть более простой и аккуратный способ через
Классический шаблон выглядит так:
📍 Навигация: Вакансии • Задачи • Собесы
🐸 Библиотека шарписта
#sharp_view
Многие до сих пор измеряют время в .NET по старинке создают экземпляр Stopwatch, вызывают Start, ждут выполнение и читают Elapsed.
Но есть более простой и аккуратный способ через
Stopwatch.GetTimestamp и Stopwatch.GetElapsedTime.Классический шаблон выглядит так:
long start = Stopwatch.GetTimestamp();
// код, который нужно измерить
await ProcessOrderAsync();
TimeSpan elapsed = Stopwatch.GetElapsedTime(start);
GetElapsedTime вычисляет разницу между текущим timestamp и сохранённым значением и возвращает TimeSpan без создания экземпляра Stopwatch. В результате нет лишней аллокации.📍 Навигация: Вакансии • Задачи • Собесы
#sharp_view
Please open Telegram to view this post
VIEW IN TELEGRAM
👍31❤4🥰4
В официальном .NET блоге появилась большая статья о том как собирать iOS виджеты поверх .NET MAUI не теряя нативности.
Автор делится практическим опытом, который раньше приходилось выкапывать по кускам в доках Apple и чужих репозиториях.
Статья не пошаговый туториал, а набор ключевых шагов и граблей от настроек App Groups и bundle id до интеграции Xcode виджет расширения в MAUI проект.
📍 Навигация: Вакансии • Задачи • Собесы
#sharp_view
Please open Telegram to view this post
VIEW IN TELEGRAM
👍6