.NET backend engineer · Software engineer

Complex ideas.
Clean solutions.

I’m Raghad Hanon. I turn complex workflows into connected, maintainable backends with C#, ASP.NET Core, and a thoughtful approach to software design.

Raghad Hanon
Raghad Hanon.NET Backend Engineer
Palestine · Building for what’s nextOpen to junior backend rolesA little further down
1stCollege of Engineering
& Technology · PTUK
93.21Academic average
out of 100
918+Codeforces problems
solved
CSEComputer Systems
Engineering · Class of 2026
01 / Selected work

From requirements
to working systems.

A graduation platform, a full-stack learning project, and an internship API. Three different contexts for putting backend engineering into practice.

02 / Under the surface

The thinking
behind the code.

Small decisions shape the whole system. Explore twelve examples of how I approach domain rules, data boundaries, and the details that connect them.

Explore the list, or choose a theme above.

TentantMiddleware.csCollabrium / C#
Security / The decision

Respect the boundary.

The tenant middleware compares the authenticated user’s tenant with the resolved organization before assigning a scoped context. Tenant-aware queries and project policies build on that context.

Why it mattersOrganization membership becomes an explicit precondition for the protected request path.
if (!string.Equals(user.TenantId, tenant.Id, StringComparison.Ordinal))
{
    throw new UnauthorizedAccessException("The authenticated user does not belong to this tenant.");
}

tenantContext.TenantId = tenant.Id;
tenantContext.CurrentTenant = tenant;
Source excerpt · reformatted for readabilityRead the full implementation
UserStory.csCollabrium / C#
Domain / The decision

Keep the rules close.

The UserStory model checks linked work before allowing testing, release, or completion. Completing a story checks that linked tasks and bugs are done and linked test cases have passed.

Why it mattersA status change reflects the state of the underlying work. The rule lives with the domain model, so the UI cannot be the only place enforcing it.
if (target == WorkItemStatus.Done)
{
    Guard.Against(!allTasksDone,
        "Cannot complete UserStory until all linked Tasks are Done.");

    Guard.Against(!noOpenBugs,
        "Cannot complete UserStory while there are open Bugs.");

    Guard.Against(!allTestsPassed,
        "Cannot complete UserStory until all linked TestCases are Passed.");
}
Source excerpt · reformatted for readabilityRead the full implementation
CommentHub.csActify / C#
Real-time / The decision

Connect the right people.

Actify routes a comment through its application command, then broadcasts the returned comment to the activity’s SignalR group. Existing comments load for the connecting client.

Why it mattersA discussion stays attached to its activity, while the client receives live updates without refreshing the page.
var comment = await mediator.Send(
    new AddComment.Command {
        CreateCommentDto = createCommentDto
    });

await Clients.Group(createCommentDto.ActivityId)
    .SendAsync("ReceiveComment", comment.Value);
Source excerpt · reformatted for readabilityRead the full implementation
UnitOfWork.csCollabrium / C#
Architecture / The decision

Commit the whole change.

The Unit of Work runs the use case, saves its changes, and commits. If the operation throws, it rolls the database transaction back. Work-item creation uses this to coordinate its record, project counter, and history.

Why it mattersRelated database updates can succeed or roll back together, keeping the use case’s persistence boundary visible.
await using var tx = await _dbContext.Database.BeginTransactionAsync(cancellationToken);
try
{
    await action(cancellationToken);

    await _dbContext.SaveChangesAsync(cancellationToken);
    await tx.CommitAsync(cancellationToken);
}
catch
{
    await tx.RollbackAsync(cancellationToken);
    throw;
}
Source excerpt · reformatted for readabilityRead the full implementation
WorkItemsReadModel.csCollabrium / C#
Architecture / The decision

Ask for the data you need.

A dedicated read model filters by work item, project, and tenant, then projects only the code and title. AsNoTracking makes the read intent explicit.

Why it mattersThe caller gets the value it needs without materializing the full work-item domain graph for this lookup.
return await _dbContext.WorkItems
.AsNoTracking()
.Where(workItem =>
    workItem.Id == wId &&
    workItem.ProjectId == pId &&
    workItem.Project.TenantId == tId)
.Select(workItem =>
    workItem.Code + " - " + workItem.Title)
.FirstOrDefaultAsync(cancellationToken);
Source excerpt · reformatted for readabilityRead the full implementation
IdentityService.csCollabrium / C#
Security / The decision

Give refresh tokens a lifecycle.

IdentityService checks the stored token’s active state. A successful refresh records revocation, links the replacement token, and persists the new token with an expiry.

Why it mattersRefresh credentials have an explicit lifecycle in persistence, with rotation and revocation represented in the model.
storedToken.RevokedAtUtc = DateTime.UtcNow;
storedToken.ReplacedByToken = newRefreshToken;

var newRefreshTokenEntity = new RefreshTokenEntity
{
    Token = newRefreshToken,
    UserId = user.Id,
    CreatedAtUtc = DateTime.UtcNow,
    ExpiresAtUtc = DateTime.UtcNow.AddDays(7)
};

_dbContext.RefreshTokens.Add(newRefreshTokenEntity);
await _dbContext.SaveChangesAsync(cancellationToken);
Source excerpt · reformatted for readabilityRead the full implementation
WorkItemFieldsSuggestionService.csCollabrium / C#
Reliability / The decision

Make AI output earn trust.

Generated work-item fields go through JSON extraction, typed deserialization, normalization, and usability checks. Invalid output feeds a repair prompt, with bounded attempts and fallback suggestions.

Why it mattersThe model’s text passes through application rules before it becomes a usable suggestion. The normal command path still validates the user’s final choice.
NormalizeSuggestion(workItemType, suggestion, summary);

if (!IsSuggestionUsable(workItemType, suggestion, out error))
    return false;

return true;
Source excerpt · reformatted for readabilityRead the full implementation
ProjectHistoryRecorder.csCollabrium / C#
Reliability / The decision

Record the change that matters.

The history recorder compares old and new property values, skips unchanged values and ignored technical fields, and resolves related identifiers into display text before recording a change.

Why it mattersProject history explains what changed in terms a teammate can understand, alongside who made the change.
var oldRawValue =
    property.GetValue(oldObject)?.ToString();

var newRawValue =
    property.GetValue(newObject)?.ToString();

if (string.Equals(
        oldRawValue,
        newRawValue,
        StringComparison.Ordinal))
{
    continue;
}
Source excerpt · reformatted for readabilityRead the full implementation
CompleteSprint.csCollabrium / C#
Domain / The decision

Preserve the meaning of a sprint.

Completing a sprint moves only incomplete work back to the backlog. Completed items remain associated with that sprint, while the lifecycle update and history are committed together.

Why it mattersHistorical sprint reports can continue to describe the work delivered in that sprint after the remaining scope moves on.
await workItemsRepository
    .MoveIncompleteWorkItemsFromSprintToBacklogAsync(
        tenantId,
        sprint.Id,
        sprint.ProjectId,
        transactionCancellationToken);

sprint.Complete();
Source excerpt · reformatted for readabilityRead the full implementation
PatchHelpers.csCollabrium / C#
Domain / The decision

Make editing intent explicit.

PatchHelpers gives string updates three meanings: null leaves the existing value alone, whitespace clears it, and supplied text sets a trimmed value. Work-item updates use these decisions explicitly.

Why it mattersA partial edit can distinguish an omitted field from a deliberate request to remove its value.
public static PatchStringDecision DecideStringPatch(string? input)
{
    return input is null
        ? new PatchStringDecision(PatchStringAction.Ignore, null)
        : string.IsNullOrWhiteSpace(input)
        ? new PatchStringDecision(PatchStringAction.Clear, null)
        : new PatchStringDecision(PatchStringAction.Set, input.Trim());
}
Source excerpt · reformatted for readabilityRead the full implementation
SprintStatusChangedNotificationHandler.csCollabrium / C#
Architecture / The decision

Let each response own its job.

Sprint completion publishes a domain-relevant application event. A dedicated handler derives distinct recipients from the team snapshot and creates their notifications; a separate handler owns email delivery.

Why it mattersThe command describes the business change, while each follow-up handler owns its delivery responsibility. These are in-process MediatR events.
var recipientUserIds = notification.TeamMembers
    .Select(m => m.Id)
    .Where(id => !string.IsNullOrWhiteSpace(id))
    .Distinct()
    .ToList();
Source excerpt · reformatted for readabilityRead the full implementation
EventReminderBackgroundService.csCollabrium / C#
Reliability / The decision

Schedule work with a lifecycle.

The event reminder worker uses PeriodicTimer and the host’s stopping token. Each run creates a dependency-injection scope, finds due events, targets attendees, and marks processed reminders.

Why it mattersTimed work has an explicit owner in the application host. The implementation is an in-process worker, with persistent queueing a possible next step.
using var timer = new PeriodicTimer(CheckInterval);

while (await timer.WaitForNextTickAsync(stoppingToken))
{
    await ProcessAsync(stoppingToken);
}
Source excerpt · reformatted for readabilityRead the full implementation

Examples from Collabrium, the four-person graduation platform I led, and Actify, a course-based implementation. Each source link opens the exact version reviewed.

More inside the Collabrium case study

Backend & data

C# · .NET · ASP.NET Core Web API
EF Core · SQL Server · LINQ

Design & security

Clean Architecture · CQRS · MediatR
Identity · JWT · Multi-tenancy

Testing & delivery

xUnit · Git · GitHub Actions CI
Swagger · Postman · Azure deployment

Full-stack support

React · TypeScript · JavaScript
SignalR · HTML · CSS · MUI

03 / A little about me

Curiosity at the core.
Care in the details.

I’m a Computer Systems Engineering graduate from Palestine Technical University — Kadoorie, where I graduated first in the College of Engineering & Technology with an average of 93.21/100.

I’m drawn to the work behind the interface: turning requirements into domain rules, deciding where responsibilities belong, and connecting features into a coherent system.

Competitive programming taught me to reason carefully. Training and team projects taught me to translate that reasoning into software other people can use and build on.

Experience & education

TAP Program Trainee

TAP — Job Hunting Program

Selected for a sponsored place in TAP’s Job Hunting Program. Participating in career coaching, interview preparation, professional networking, and a structured job-search plan for international software engineering opportunities.

Interview preparationCareer developmentProfessional communication

Backend Intern

Foothill Technology Solutions, LLC

Structured backend training in C#, ASP.NET Core, EF Core, clean code, SOLID, architecture, and automated testing. Delivered the Hotel Booking API as the final project, with GitHub Actions CI and hands-on Azure deployment.

Full Stack Intern

Knowledge Academy

Built and consumed REST APIs using C#, ASP.NET, and relational databases. Developed responsive React interfaces and integrated them with backend functionality.

B.Sc. Computer Systems Engineering

Palestine Technical University — Kadoorie

Ranked 1st in the College of Engineering & Technology. Graduated with a 93.21/100 average and led the four-person Collabrium graduation project team.

Still learning. Always building.Continuing to deepen .NET backend engineering, testing, and deployment skills through hands-on project work and focused study.
04 / Recognition & milestones

A habit of showing up
and solving problems.

Academic achievement, team competitions, and years of algorithm practice have shaped how I approach unfamiliar challenges.

Academic distinction / 2026
1st

College of Engineering
& Technology

Palestine Technical University — Kadoorie.
93.21/100 graduating average.

View education & honors
GirlsACPC / 2023
25th

ICPC Africa & Arab
Collegiate Contest for Girls

Regional placement in a team programming contest across Africa and the Arab region.

View recognition
ICPC Palestine / 2022
20th

Palestinian Collegiate
Programming Contest

Nationwide placement, solving algorithmic problems through team collaboration.

View recognition
918+Codeforces problems solvedAlgorithms, data structures, and persistence.
120+LeetCode problems solvedContinuing to sharpen problem-solving skills.C++
More competitions, events & learning milestones
Hebron Code-Jam — 9th nationwide

Competed with the 3Geeks team. Our team also placed 1st in the qualification contest.

Read the event post
Palestine Science & Technology Fair — 5th place

An early milestone in exploring practical ideas through science and technology.

Meta Hacker Cup

Participation listed among my LinkedIn certifications.

Intel International Science & Technology Fair

Participation listed among my LinkedIn certifications.

Palestine Mobile Apps Fair — 5th nationwide

An early experience turning an idea into a technology project.

Complete Guide to .NET Core & React

Course-based full-stack development practice that informed Actify.

Front-end with React — Knowledge Academy

HTML, CSS, JavaScript, Bootstrap, and React.

Java Data Structures & Algorithms

Udemy course with LeetCode exercises.

English Access Microscholarship Program

Language learning and communication development.

Palestine FIRST LEGO League

Participation listed among my LinkedIn certifications.

TAP — Job Hunting Program

Career development and preparation for international opportunities.

Explore certificates on LinkedIn
05 / Inside the product

A closer look at the work.

Real workflows, original recordings, and the documents behind Collabrium. Explore the finished product and the thinking that shaped it.

01 / Watch

The platform in motion.

View the case study
Original recording / 01

Project & work-item delivery

Follow project planning, work items, and the delivery workflow.

Original recording / 02

Tenant, users & teams

Explore the organization workspace and the people and teams inside it.

Original recording / 03

Reports & analytics

See the reporting workflow and the analytical views of project work.

Original recording / 04

Learning Hub

Explore roadmaps, courses, assignments, and shared learning resources.

Original recording / 05

Multi-Tenant Architecture

A visual overview of Collabrium’s tenant structure and role hierarchy.

Use the player’s full-screen control to inspect the interface in detail. Recordings play on request.

02 / Explore

The interface, up close.

Meet the project
AuthThe sign-in interface for entering the Collabrium workspace.
SuperAdminThe platform tenant directory and administration overview.
TenantAdminThe tenant profile, organizational totals, and contact information.
UserThe personal profile and account information interface.
UsersManagementThe tenant user directory and employee administration overview.
TeamManagementThe teams overview with membership, capacity, and activity status.
TeamsThe team workspace with its member-management dialog. This folder contains team action screens.
ProjectManagementThe project directory organized by delivery status.
SprintManagementThe sprint overview within a project, including lifecycle and delivery totals.
WorkItemManagementThe project board with work items organized by workflow status.
LearningHubThe course catalog and learning interface.
CommunityHubThe shared community feed with announcements and upcoming events.
ReportsThe analytics interface showing the tenant information report.
AIThe roadmap generation interface with its AI generation option selected.

Categories match the folders in the original screens archive. Select a module to see its overview, then open the image for a closer look.

Explore all 202 screens
03 / Read

The research behind the build.

Final project thesis cover
272 pages / PDF

Final project thesis

Requirements, system design, domain models, and the implementation walkthrough.

Read the thesis9.1 MB
Graduation project presentation cover
53 slides / PowerPoint

Graduation project presentation

The updated graduation presentation, including platform workflows and product demonstrations.

Download the presentation196.3 MB
The next good thing starts here

Let’s build
something that matters.

I’m open to junior .NET backend and software engineering opportunities. Have a role or a problem in mind? I’d love to hear about it.

Start a conversation
GitHubLinkedInCodeforcesBASED IN PALESTINE · OPEN TO REMOTE WORK