{"id":13430491,"url":"https://github.com/JosephWoodward/GlobalExceptionHandlerDotNet","last_synced_at":"2025-03-16T05:30:56.768Z","repository":{"id":62355328,"uuid":"100835926","full_name":"josephwoodward/GlobalExceptionHandlerDotNet","owner":"josephwoodward","description":"Exception handling as a convention in the ASP.NET Core request pipeline","archived":false,"fork":false,"pushed_at":"2022-12-08T06:31:40.000Z","size":1671,"stargazers_count":270,"open_issues_count":13,"forks_count":32,"subscribers_count":21,"default_branch":"master","last_synced_at":"2025-03-12T02:55:21.111Z","etag":null,"topics":["net-core","webapi"],"latest_commit_sha":null,"homepage":"","language":"C#","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/josephwoodward.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2017-08-20T03:33:13.000Z","updated_at":"2024-12-26T13:50:24.000Z","dependencies_parsed_at":"2023-01-24T16:30:52.257Z","dependency_job_id":null,"html_url":"https://github.com/josephwoodward/GlobalExceptionHandlerDotNet","commit_stats":null,"previous_names":[],"tags_count":11,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/josephwoodward%2FGlobalExceptionHandlerDotNet","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/josephwoodward%2FGlobalExceptionHandlerDotNet/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/josephwoodward%2FGlobalExceptionHandlerDotNet/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/josephwoodward%2FGlobalExceptionHandlerDotNet/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/josephwoodward","download_url":"https://codeload.github.com/josephwoodward/GlobalExceptionHandlerDotNet/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":243830912,"owners_count":20354848,"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","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":["net-core","webapi"],"created_at":"2024-07-31T02:00:54.543Z","updated_at":"2025-03-16T05:30:54.148Z","avatar_url":"https://github.com/josephwoodward.png","language":"C#","readme":"# Global Exception Handling for ASP.NET Core\n\n[![Build status](https://ci.appveyor.com/api/projects/status/kdbepiak0m6olxw7?svg=true)](https://ci.appveyor.com/project/JoeMighty/globalexceptionhandlerdotnet)\n\nGlobalExceptionHandler.NET allows you to configure application level exception handling as a convention within your ASP.NET Core application, opposed to explicitly handling exceptions within each controller action.\n\nConfiguring your error handling this way reaps the following benefits:\n\n- Centralised location for handling errors\n- Reduce boilerplate try-catch logic in your controllers\n- Catch and appropriately handle exceptions outside of the ASP.NET Core framework\n- You don't want error codes being visible by consuming APIs (for instance, you want to return 500 for every exception)\n\nThis middleware targets the ASP.NET Core pipeline with an optional dependency on the MVC framework for content negotiation if so desired.\n\n**Note:** GlobalExceptionHandler.NET builds on top of the `app.UseExceptionHandler()` middleware so they cannot be used in tandem. GlobalExceptionHandler.NET turns your exception configuration provided by this library into an ExceptionHandler used within the `UseExceptionHandler` middleware.\n\n## Installation\n\nGlobalExceptionHandler is [available on NuGet](https://www.nuget.org/packages/GlobalExceptionHandler/) and can be installed via the below commands depending on your platform:\n\n```\n$ Install-Package GlobalExceptionHandler\n```\nor via the .NET Core CLI:\n\n```\n$ dotnet add package GlobalExceptionHandler\n```\n\n## Bare Bones Setup\n\n```csharp\n// Startup.cs\n\npublic void Configure(IApplicationBuilder app, IHostingEnvironment env)\n{\n    // app.UseExceptionHandler(); You no longer need this.\n    app.UseGlobalExceptionHandler(x =\u003e {\n        x.ContentType = \"application/json\";\n        x.ResponseBody(s =\u003e JsonConvert.SerializeObject(new\n        {\n            Message = \"An error occurred whilst processing your request\"\n        }));\n    });\n    \n    app.Map(\"/error\", x =\u003e x.Run(y =\u003e throw new Exception()));\n}\n```\n\nAny exception thrown by your application will result in the follow response:\n\n```http\nHTTP/1.1 500 Internal Server Error\nDate: Fri, 24 Nov 2017 09:17:05 GMT\nContent-Type: application/json\nServer: Kestrel\nCache-Control: no-cache\nPragma: no-cache\nTransfer-Encoding: chunked\nExpires: -1\n\n{\n  \"Message\": \"An error occurred whilst processing your request\"\n}\n```\n\n## Handling specific exceptions\n\nYou can explicitly handle exceptions like so:\n\n```csharp\napp.UseGlobalExceptionHandler(x =\u003e {\n    x.ContentType = \"application/json\";\n    x.ResponseBody(s =\u003e JsonConvert.SerializeObject(new\n    {\n        Message = \"An error occurred whilst processing your request\"\n    }));\n\n    x.Map\u003cRecordNotFoundException\u003e().ToStatusCode(StatusCodes.Status404NotFound);\n});\n```\n\n```http\nHTTP/1.1 404 Not Found\nDate: Sat, 25 Nov 2017 01:47:51 GMT\nContent-Type: application/json\nServer: Kestrel\nCache-Control: no-cache\nPragma: no-cache\nTransfer-Encoding: chunked\nExpires: -1\n\n{\n  \"Message\": \"An error occurred whilst processing your request\"\n}\n```\n\n#### Runtime Status Code\n\nIf talking to a remote service, you could optionally choose to forward the status code on, or propagate it via the exception using the following `ToStatusCode(..)` overload:\n\n```csharp\napp.UseGlobalExceptionHandler(x =\u003e\n{\n    x.ContentType = \"application/json\";\n    x.Map\u003cHttpNotFoundException\u003e().ToStatusCode(ex =\u003e ex.StatusCode).WithBody((e, c) =\u003e \"Resource could not be found\");\n    ...\n});\n```\n\n### Per exception responses  \n\nOr provide a custom error response for the exception type thrown:\n\n```csharp\napp.UseGlobalExceptionHandler(x =\u003e {\n    x.ContentType = \"application/json\";\n    x.ResponseBody(s =\u003e JsonConvert.SerializeObject(new\n    {\n        Message = \"An error occurred whilst processing your request\"\n    }));\n\n    x.Map\u003cRecordNotFoundException\u003e().ToStatusCode(StatusCodes.Status404NotFound)\n        .WithBody((ex, context) =\u003e JsonConvert.SerializeObject(new {\n            Message = \"Resource could not be found\"\n        }));\n});\n```\n\nResponse:\n\n```json\nHTTP/1.1 404 Not Found\n...\n{\n  \"Message\": \"Resource could not be found\"\n}\n```\n\nAlternatively you could output the exception content if you prefer:\n\n```csharp\napp.UseGlobalExceptionHandler(x =\u003e {\n    x.ContentType = \"application/json\";\n    x.ResponseBody(s =\u003e JsonConvert.SerializeObject(new\n    {\n        Message = \"An error occurred whilst processing your request\"\n    }));\n\n    x.Map\u003cRecordNotFoundException\u003e().ToStatusCode(StatusCodes.Status404NotFound)\n        .WithBody((ex, context) =\u003e JsonConvert.SerializeObject(new {\n            Message = ex.Message\n        }));\n});\n```\n\n## Content Negotiation\n\nGlobalExceptionHandlerDotNet plugs into the .NET Core pipeline, meaning you can also take advantage of content negotiation provided by the ASP.NET Core MVC framework, enabling the clients to dictate the preferred content type.\n\nTo enable content negotiation against ASP.NET Core MVC you will need to include the [GlobalExceptionHandler.ContentNegotiation.Mvc](https://www.nuget.org/packages/GlobalExceptionHandler.ContentNegotiation.Mvc/) package.\n\nNote: Content negotiation is handled by ASP.NET Core MVC so this takes a dependency on MVC.\n\n```csharp\n//Startup.cs\n\npublic void ConfigureServices(IServiceCollection services)\n{\n    services.AddMvcCore().AddXmlSerializerFormatters();\n}\n\npublic void Configure(IApplicationBuilder app, IHostingEnvironment env)\n{\n    app.UseGlobalExceptionHandler(x =\u003e\n    {\n        x.Map\u003cRecordNotFoundException\u003e().ToStatusCode(StatusCodes.Status404NotFound)\n            .WithBody(e =\u003e new ErrorResponse\n            {\n                Message = e.Message\n            });\n    });\n\n    app.Map(\"/error\", x =\u003e x.Run(y =\u003e throw new RecordNotFoundException(\"Resource could not be found\")));\n}\n```\n\nNow when an exception is thrown and the consumer has provided the `Accept` header:\n\n```http\nGET /api/demo HTTP/1.1\nHost: localhost:5000\nAccept: text/xml\n```\n\nThe response will be formatted according to the `Accept` header value:\n\n```http\nHTTP/1.1 404 Not Found\nDate: Tue, 05 Dec 2017 08:49:07 GMT\nContent-Type: text/xml; charset=utf-8\nServer: Kestrel\nCache-Control: no-cache\nPragma: no-cache\nTransfer-Encoding: chunked\nExpires: -1\n\n\u003cErrorResponse \n  xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" \n  xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\"\u003e\n  \u003cMessage\u003eResource could not be found\u003c/Message\u003e\n\u003c/ErrorResponse\u003e\n```\n\n## Logging\n\nUnder most circumstances you'll want to keep a log of any exceptions thrown in your log aggregator of choice. You can do this via the `OnError` endpoint:\n\n```csharp\nx.OnError((exception, httpContext) =\u003e\n{\n    _logger.Error(exception.Message);\n    return Task.CompletedTask;\n});\n```\n\n## Configuration Options:\n\n- `ContentType`  \nSpecify the returned content type (default is `application/json)`.\n\n- `ResponseBody(...)`  \nSet a default response body that any unhandled exception will trigger.\n\n```csharp\nx.ResponseBody((ex, context) =\u003e {\n    return \"Oops, something went wrong! Check the logs for more information.\";\n});\n```\n\n- `DebugMode`\nEnabling debug mode will cause GlobalExceptionHandlerDotNet to return the full exception thrown. **This is disabled by default and should not be set in production.**\n","funding_links":[],"categories":["Frameworks, Libraries and Tools","Libraries, Frameworks and Tools","框架, 库和工具","Exceptions"],"sub_categories":["Exceptions","异常"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FJosephWoodward%2FGlobalExceptionHandlerDotNet","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FJosephWoodward%2FGlobalExceptionHandlerDotNet","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FJosephWoodward%2FGlobalExceptionHandlerDotNet/lists"}