.NET Core WebAPI中ArgumentNullException致程序崩溃,原因是什么?
Let's tackle both of your questions step by step—first the unexpected crash with ArgumentNullException, then the confusing behavior of String.Format.
1. Why Does ArgumentNullException Crash Your App Instead of Showing the Developer Exception Page?
First, let's confirm the behavior you're seeing: when you throw new Exception("One") (case 1), the ASP.NET Core request pipeline correctly catches the exception, triggers the VS Code debugger, and returns the developer exception page. But when you throw ArgumentNullException (case 2) or hit the String.Format(template, "UH OH") line (case 4), the app crashes immediately without debugger interaction.
This is likely tied to a combination of .NET Core 2.x's exception handling quirks and how your VS Code debugger is configured:
- .NET Core 2.1 is an end-of-life version, and it had known bugs where certain argument-related exceptions could bypass the ASP.NET Core exception middleware (like
UseDeveloperExceptionPage) and cause the Kestrel server to crash directly. These issues were fixed in later supported versions (3.1+ and .NET 5+). - Your older VS Code debugger (1.23.1) might not be set to break on
ArgumentNullExceptionby default. If the debugger doesn't catch the exception, the runtime treats it as unhandled and terminates the process.
Fixes to Try:
- Upgrade Your .NET Core SDK: The most reliable long-term fix is moving to a supported version of .NET Core/.NET, as these exception handling bugs were addressed in newer releases.
- Configure Debugger to Break on
ArgumentNullException: In VS Code, open the Debug panel, click the gear icon to editlaunch.json, and add an exception breakpoint for this type:"exceptionBreakpointFilters": [ { "name": "System.ArgumentNullException", "enabled": true } ] - Temporary Workaround: If you can't upgrade immediately, wrap the exception in a try-catch block in your controller to ensure it's handled by the pipeline:
case 2: try { throw new ArgumentNullException(nameof(id), "Two"); } catch (ArgumentNullException ex) { return StatusCode(500, ex.Message); }
2. Why Do the Two String.Format Calls Behave Differently?
This boils down to C# overload resolution—the compiler picks different String.Format methods based on the parameters you pass:
For
String.Format(null, "UH OH"):- This matches the overload
public static string Format(IFormatProvider provider, string format, params object[] args). - The
nullhere is passed as theIFormatProviderparameter (which accepts null, falling back to the default format provider). The"UH OH"is the valid format string, so the method just returns it as-is.
- This matches the overload
For
String.Format(template, "UH OH")wheretemplateisnull:- This matches the overload
public static string Format(string format, params object[] args). - This overload requires a non-null
formatstring to work. Since you're passingnullfor this parameter, it throws anArgumentNullExceptionas documented.
- This matches the overload
If you wanted to replicate the exception behavior in case 3, you'd need to explicitly cast null to a string to force the compiler to pick the second overload:
// This will throw ArgumentNullException result = String.Format((string)null, "UH OH");
Final Notes
The crash issue is almost certainly a bug fixed in newer .NET versions, so upgrading is the best permanent solution. For the String.Format behavior, it's just a matter of understanding which overload the compiler selects based on your parameter types.
内容的提问来源于stack exchange,提问作者Xorcist

