{"id":15091024,"url":"https://github.com/nigje/ups","last_synced_at":"2026-02-07T22:32:16.410Z","repository":{"id":116577644,"uuid":"405714960","full_name":"Nigje/UPS","owner":"Nigje","description":".NET 5, ASP.NET Core, EF Core, SQL Server, Autofac, Swagger, Automapper, xUnit (Moq), Docker, Windows Form (.NET 5)","archived":false,"fork":false,"pushed_at":"2021-09-12T17:58:40.000Z","size":394,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-03-22T10:15:44.431Z","etag":null,"topics":["aspnetcore","autofac","docker","efcore","moq","restapi","sqlserver","windowsforms","xunit"],"latest_commit_sha":null,"homepage":"","language":"C#","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Nigje.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2021-09-12T17:57:37.000Z","updated_at":"2021-09-27T09:55:39.000Z","dependencies_parsed_at":null,"dependency_job_id":"4d2dc72a-3cfe-478c-b43d-fa8b030b6d76","html_url":"https://github.com/Nigje/UPS","commit_stats":{"total_commits":1,"total_committers":1,"mean_commits":1.0,"dds":0.0,"last_synced_commit":"0b6416e48a831b5a5b513b87cc52b0cd767e8eff"},"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/Nigje/UPS","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Nigje%2FUPS","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Nigje%2FUPS/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Nigje%2FUPS/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Nigje%2FUPS/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Nigje","download_url":"https://codeload.github.com/Nigje/UPS/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Nigje%2FUPS/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":268363038,"owners_count":24238548,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-08-02T02:00:12.353Z","response_time":74,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["aspnetcore","autofac","docker","efcore","moq","restapi","sqlserver","windowsforms","xunit"],"created_at":"2024-09-25T10:35:07.741Z","updated_at":"2026-02-07T22:32:16.374Z","avatar_url":"https://github.com/Nigje.png","language":"C#","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Introduction\n\nThis is a Client/Server sample app based on ASP.NET Core and .NET 5 to manage users (based on the document requirements). On the server-side,  ASP.NET Core has been used, and on the client-side, Windows Form. The focus was on requirements such as high-performance, scalability, reliability, extensibility. The following is technologies that have been used. I'm going to regularly update the document in the next commits.\n\nIn the first step, run the `USP.Api` and make sure that the API URL is the same as the `BaseUrl` of the `app.config` in the `UPS.WindowsForm` , and finally run the `UPS.WindowsForm` project (ex: https://localhost:xxxx).\n\n### Technologies:\n\n- .NET 5\n- ASP.NET Core\n- EF Core\n- SQL Server\n- Autofac\n- Swagger\n- Automapper\n- xUnit (Moq)\n- Docker\n- Windows Form (.NET 5)\n\n### Todo:\n\n- Write test in controller level (Integration).\n- Indicate loading logo/text during fetching data in forms.\n- Add docker-compose.yml\n- Add Serilog, Elasticsearch, Kibana, Fluentd, Nginx.\n\n\n\u003cp align=\"center\"\u003e\n  \u003cimg  src=\"UPS.Docs/Client-Server.png\" alt=\"Client-Server\"\u003e\n\u003c/p\u003e\n\n## Server-Side (Web API)\n\nUser's businesses are handled on the server-side and windows form application is an interface for it. On the server-side, there are 6 REST API endpoints to manage users that means easily can migrate to other interface technologies such as WPF, React.js, Blazor, Electron.\n\n```\n- POST\t\t/api/public-api/users \t\t\t\tThis endpoint uses to add new user.\n- PUT\t\t/api/public-api/users/{id} \t\t\tThis endpoint uses to update a user.\n- DELETE\t/api/public-api/users/{id} \t\t\tThis endpoint uses to remove a user.\n- Get\t\t/api/public-api/users/{id} \t\t\tThis endpoint uses to get a user.\n- Get\t\t/api/public-api/users\t \t\t\tThis endpoint uses to get list user.\n- Get\t\t/api/public-api/users/export-csv \tThis endpoint uses to get list user as a csv file.\n```\n\n\n\nFor authorization, all requests need an API token (ACCESS-TOKEN) that is set on the header. I set `afe45081-09a9-4e76-ae50-b4b480ecfbe4` as ACCESS-TOKEN (check config files).\n\n\n\n```powershell\ncurl -i -H \"Accept:application/json\" -H \"Content-Type:application/json\" -H \"Authorization: Bearer ACCESS-TOKEN\" -XGET \"{base-url}/api/public-api/users\"\n```\n\n\n\n\n\n\u003cp align=\"center\"\u003e\n  \u003cimg  src=\"UPS.Docs/Swagger.PNG\" alt=\"Swagger\"\u003e\n\u003c/p\u003e\n\n\n\n### Migrations\n\nBy default, the project uses SQL Express (MSSQLLocalDB) and runs migrations automatically (check Startup.Configure()). To add new models use the following code in command line.\n\n```powershell\ndotnet ef migrations add InitializeModels -s UPS.Api -p UPS.DB\n```\n\nif you got a error like the following message, update your EF tools by `dotnet tool update --global dotnet-ef`\n\n\u003e The Entity Framework tools version 'x.x.x' is older than that of the runtime 'y.y.y'. Update the tools for the latest features and bug fixes.\n\u003e The name 'InitialModels' is used by an existing migration.\n\n```powershell\ndotnet tool update --global dotnet-ef\n```\n\nTo update database use the following code.\n\n```powershell\ndotnet ef database update -s UPS.Api -p UPS.DB\n```\n\n\n\n### Exceptions\n\nWhen an exception occurs in the system the action result will be such as the following object and response HttpStatusCode will be 4xx or 5xx. HttopStatusCode in the range of 4xx shows the exception is because of user behavior (client-side) and 5xx shows it has occurred because of system defects (server-side).\n\n```json\n{\n  \"__unauthorizedRequest\": true,\n  \"__wrapped\": true,\n  \"__traceId\": \"\",\n  \"error\": {\n    \"errorCode\": \"USER_NOT_FOUND\",\n    \"message\": \"User not found.\",\n    \"details\": \"\",\n    \"source\": \"\"\n  }\n}\n```\n\n The above response had HttpStatusCode 404 that shows the not found exception has occured. Depend on the application is running on production or other environments, the `message`, `details`, and `source` can have more details about exceptions. \n\n- **__unauthorizedReques**t: shows the request is authorized or not. In the above example, the request is not authorized.\n- **__wrapped**: shows the result is wrapped or not. Now, by default, all exceptions are wrapped.\n- **__traceId**: TraceId will use to track a request over other systems and services. It is not implemented.\n- **error.errorCode**: ErrorCode shows the exception reason. When a developer throws a `UPSException`, he/she will fill this field.\n- **error.Message**: Message shows the exception reason.  \n- **error.Details**: Details shows details of exceptions such as stack trace and inner exception details. It is always empty in production environment.\n- **error.Source**: The source shows the service that has raised the exception. If you use microservice architecture, It would show the name of the service and its version. The following config is needed in `appsetting. json` (It is always empty in production).\n\n\n\n```json\n{\n  \"ServiceInfo\": {\n    \"Name\": \"Service Name\",\n    \"Description\": \"Service Description\",\n    \"Version\": \"1.0\"\n  }\n}\n```\n\n\n\nThis project has its Exception that is derived from Exception. Also, there are other exceptions that are derived from `UPSException`. Check `GlobalExceptionFilter.cs` class for more details about exceptions.\n\n```c#\npublic class UPSException : Exception \n\n{\n    /// \u003csummary\u003e\n    /// Error code that indicates a summary of error by using some words or numbers.\n    /// \u003c/summary\u003e\n\tpublic string ErrorCode { get; protected set; }\n    \n    /// \u003csummary\u003e\n    /// Technical-details are not allowed to be shown to the user.\n    /// Just log them or use them internally by software-technicians.\n    /// \u003c/summary\u003e\n    public string TechnicalMessage { get; protected set; }\n}\n```\n\n\n\n- **UPSException**: This exception use generally and its HttpStatusCode will be 500.\n\n- **UPSExceptionNotFound**: This exception use to show NotFoundException and HttpStatusCode will be 404.\n\n- **UPSExceptionInvalidParameter**: This exception use to show InvalidParameter and HttpStatusCode will be 422.\n\n- **UPSBusinessException**: This exception use to show BusinessException and HttpStatusCode will be 400 (for exceptions that should be thrown because of a business defect).\n\n- **UPSExceptionAuthenticationFailed**: This exception use to show  unauthorized request and HttpStatusCode will be 403.\n\n- **Exception**:  This exception use generally and its HttpStatusCode will be 500.\n\n  \n\n## Client-Side (Windows Form)\n\nUser's businesses are handled on the server-side and windows form application is an interface for it. There is a base form (TemplateForm) that others derive it. The following is the list of project forms:\n\n- **LoadForm**: It is loaded during the load of MainForm (as a loading page).\n- **MainForm**: It is the main form.\n- **UserForm**: It is used to add and update a users.\n- **MessageForm**: It is used to show errors and normal messages to users.\n- **TemplateForm**: It is a base form for others that derive it and includes base designs.\n\n\n\n**MainForm**\n\u003cp align=\"center\"\u003e\n  \u003cimg  src=\"UPS.Docs/MainForm.PNG\" alt=\"MainForm\"\u003e\n\u003c/p\u003e\n\n\n**UserForm**\n\u003cp align=\"center\"\u003e\n  \u003cimg  src=\"UPS.Docs/AddUser.PNG\" alt=\"AddUser\"\u003e\n   \u003cimg  src=\"UPS.Docs/UpdateUser.PNG\" alt=\"UpdateUser\"\u003e\n\u003c/p\u003e\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnigje%2Fups","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fnigje%2Fups","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnigje%2Fups/lists"}