在 ASP.NET Core 中返回带有自定义状态代码的 JSON 结果

        控制 ASP.NET Core 响应的格式,并了解如何通过格式化程序的帮助或直接从操作返回带有自定义状态代码的 JSON 结果。

        创建 HTTP API 时,您希望能够控制如何响应请求,包括更改状态代码和正文格式。在这篇博文中,我们将研究如何通过在 ASP.NET Core 中自定义状态代码来控制 JSON 响应。

ASP.NET Core 如何决定响应格式

        首先让我们看一下 ASP.NET Core 实际上是如何生成 JSON 结果的,这将有助于我们理解响应格式背后的机制。当我们使用以下 dotnet CLI 命令使用 Web API 配置构建 ASP.NET Core 项目时:

dotnet new webapi --no-https --auth=None

我们的 startup.cs 文件如下所示:

public class Startup
{
    public Startup(IConfiguration configuration)
    {
        Configuration = configuration;
    }

    public IConfiguration Configuration { get; }

    // This method gets called by the runtime. Use this method to add services to the container.
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddControllers();
    }

    // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }

        app.UseRouting();

        app.UseAuthorization();

        app.UseEndpoints(endpoints =>
        {
            endpoints.MapControllers();
        });
    }
}

我们还有一个名为的示例控制器文件WeatherForecastController.cs,其形状如下: 

[ApiController]
[Route("[controller]")]
public class WeatherForecastController : ControllerBase
{
    private static readonly string[] Summaries = new[]
    {
        "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
    };

    private readonly ILogger<WeatherForecastController> _logger;

    public WeatherForecastController(ILogger<WeatherForecastController> logger)
    {
        _logger = logger;
    }

    [HttpGet]
    public IEnumerable<WeatherForecast> Get()
    {
        var rng = new Random();
        return Enumerable.Range(1, 5).Select(index => new WeatherForecast
        {
            Date = DateTime.Now.AddDays(index),
            TemperatureC = rng.Next(-20, 55),
            Summary = Summaries[rng.Next(Summaries.Length)]
        })
        .ToArray();
    }
}

这些是我们可以借鉴的基础知识,以便我们了解响应在格式和状态代码方面是如何形成的。

当我们使用 配置 ASP.NET Core 时services.AddControllers,这会添加内置的OutputFormatters,用于将对象写入输出流:

  • Microsoft.AspNetCore.Mvc.Formatters.HttpNoContentOutputFormatter
  • Microsoft.AspNetCore.Mvc.Formatters.StringOutputFormatter
  • Microsoft.AspNetCore.Mvc.Formatters.StreamOutputFormatter
  • Microsoft.AspNetCore.Mvc.Formatters.SystemTextJsonOutputFormatter

这些输出格式化程序允许操作返回任何对象返回值。此处通过称为内容协商的过程选择格式化程序,该过程在客户端指定 Accept 标头时发生。

让我们通过一个例子来看一下。通过以下修改,我们将 XML 输出格式化程序添加到支持的格式化程序列表中:

public void ConfigureServices(IServiceCollection services)
{
    services.AddControllers().AddXmlSerializerFormatters();
}

现在,我们将看到,当我们指定想要通过 Accept 标头以 XML 形式接收响应主体时,响应将以 XML 形式编写: 

curl -v -H "Accept: application/xml" http://localhost:5000/WeatherForecast
*   Trying ::1...
* TCP_NODELAY set
* Connected to localhost (::1) port 5000 (#0)
> GET /WeatherForecast HTTP/1.1
> Host: localhost:5000
> User-Agent: curl/7.54.0
> Accept: application/xml

< HTTP/1.1 200 OK
< Date: Mon, 13 Jan 2020 21:06:32 GMT
< Content-Type: application/xml; charset=utf-8
< Server: Kestrel
< Content-Length: 829

* Connection #0 to host localhost left intact
<ArrayOfWeatherForecast xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"><WeatherForecast><Date>2020-01-14T21:06:32.786281+00:00</Date><TemperatureC>3</TemperatureC><Summary>Hot</Summary></WeatherForecast><WeatherForecast><Date>2020-01-15T21:06:32.794902+00:00</Date><TemperatureC>36</TemperatureC><Summary>Mild</Summary></WeatherForecast><WeatherForecast><Date>2020-01-16T21:06:32.794907+00:00</Date><TemperatureC>-14</TemperatureC><Summary>Scorching</Summary></WeatherForecast><WeatherForecast><Date>2020-01-17T21:06:32.794908+00:00</Date><TemperatureC>5</TemperatureC><Summary>Chilly</Summary></WeatherForecast><WeatherForecast><Date>2020-01-18T21:06:32.794908+00:00</Date><TemperatureC>-13</TemperatureC><Summary>Scorching</Summary></WeatherForecast></ArrayOfWeatherForecast> 

当我们将 Accept 标头指定为 application/json 时,响应将采用 JSON 格式: 

curl -v -H "Accept: application/json" http://localhost:5000/WeatherForecast
*   Trying ::1...
* TCP_NODELAY set
* Connected to localhost (::1) port 5000 (#0)
> GET /WeatherForecast HTTP/1.1
> Host: localhost:5000
> User-Agent: curl/7.54.0
> Accept: application/json

< HTTP/1.1 200 OK
< Date: Mon, 13 Jan 2020 21:09:05 GMT
< Content-Type: application/json; charset=utf-8
< Server: Kestrel
< Transfer-Encoding: chunked

* Connection #0 to host localhost left intact
[{"date":"2020-01-14T21:09:05.635107+00:00","temperatureC":4,"temperatureF":39,"summary":"Hot"},{"date":"2020-01-15T21:09:05.635279+00:00","temperatureC":-8,"temperatureF":18,"summary":"Scorching"},{"date":"2020-01-16T21:09:05.635281+00:00","temperatureC":42,"temperatureF":107,"summary":"Balmy"},{"date":"2020-01-17T21:09:05.635281+00:00","temperatureC":27,"temperatureF":80,"summary":"Chilly"},{"date":"2020-01-18T21:09:05.635282+00:00","temperatureC":44,"temperatureF":111,"summary":"Warm"}]%  

除了返回 POCO(普通旧 CLR 对象)并让内容协商决定选择哪种输出格式化程序之外,您还可以从控制器操作返回 IActionResult 它定义了表示操作方法结果的契约,这可以让您直接控制返回类型。例如,内置助手 IActionResult 实现JsonResult返回 JSON 格式的数据,而不管 Accept 标头如何。

[HttpGet]
public IActionResult Get()
{
    var rng = new Random();
    var result = Enumerable.Range(1, 5).Select(index => new WeatherForecast
    {
        Date = DateTime.Now.AddDays(index),
        TemperatureC = rng.Next(-20, 55),
        Summary = Summaries[rng.Next(Summaries.Length)]
    })
    .ToArray();

    return new JsonResult(result);
}

curl -v -H "Accept: application/xml" http://localhost:5000/WeatherForecast
*   Trying ::1...
* TCP_NODELAY set
* Connected to localhost (::1) port 5000 (#0)
> GET /WeatherForecast HTTP/1.1
> Host: localhost:5000
> User-Agent: curl/7.54.0
> Accept: application/xml

< HTTP/1.1 200 OK
< Date: Mon, 13 Jan 2020 21:18:39 GMT
< Content-Type: application/json; charset=utf-8
< Server: Kestrel
< Transfer-Encoding: chunked

* Connection #0 to host localhost left intact
[{"date":"2020-01-14T21:18:40.678848+00:00","temperatureC":12,"temperatureF":53,"summary":"Scorching"},{"date":"2020-01-15T21:18:40.685278+00:00","temperatureC":23,"temperatureF":73,"summary":"Chilly"},{"date":"2020-01-16T21:18:40.685283+00:00","temperatureC":24,"temperatureF":75,"summary":"Cool"},{"date":"2020-01-17T21:18:40.685284+00:00","temperatureC":-10,"temperatureF":15,"summary":"Hot"},{"date":"2020-01-18T21:18:40.685284+00:00","temperatureC":-5,"temperatureF":24,"summary":"Bracing"}]% 

更改响应状态代码

现在,让我们看看如何更改响应状态代码。对于上面提到的所有情况,我们可以Response.StatusCode在返回结果之前简单地设置为我们想要响应的适当状态代码:

[HttpGet]
public IActionResult Get()
{
    var rng = new Random();
    var result = Enumerable.Range(1, 5).Select(index => new WeatherForecast
    {
        Date = DateTime.Now.AddDays(index),
        TemperatureC = rng.Next(-20, 55),
        Summary = Summaries[rng.Next(Summaries.Length)]
    })
    .ToArray();

    Response.StatusCode = StatusCodes.Status400BadRequest;
    return new JsonResult(result);
}

您可以在下面的请求示例中看到我们收到了 400 状态代码的响应: 

curl -v -H "Accept: application/json" http://localhost:5000/WeatherForecast
*   Trying ::1...
* TCP_NODELAY set
* Connected to localhost (::1) port 5000 (#0)
> GET /WeatherForecast HTTP/1.1
> Host: localhost:5000
> User-Agent: curl/7.54.0
> Accept: application/json

< HTTP/1.1 400 Bad Request
< Date: Mon, 13 Jan 2020 21:34:53 GMT
< Content-Type: application/json; charset=utf-8
< Server: Kestrel
< Transfer-Encoding: chunked

* Connection #0 to host localhost left intact
[{"date":"2020-01-14T21:34:54.415857+00:00","temperatureC":21,"temperatureF":69,"summary":"Sweltering"},{"date":"2020-01-15T21:34:54.4239+00:00","temperatureC":-6,"temperatureF":22,"summary":"Freezing"},{"date":"2020-01-16T21:34:54.423907+00:00","temperatureC":9,"temperatureF":48,"summary":"Mild"},{"date":"2020-01-17T21:34:54.423907+00:00","temperatureC":51,"temperatureF":123,"summary":"Freezing"},{"date":"2020-01-18T21:34:54.423908+00:00","temperatureC":49,"temperatureF":120,"summary":"Hot"}]% 

除了这种设置状态代码的简单方法之外,ControllerBase 对象上还有一些辅助方法,使我们能够塑造响应。例如,  Conflict 方法创建一个 ConflictObjectResult,该结果会产生Status409Conflict响应。 

[HttpGet]
public IActionResult Get()
{
    var rng = new Random();
    var result = Enumerable.Range(1, 5).Select(index => new WeatherForecast
    {
        Date = DateTime.Now.AddDays(index),
        TemperatureC = rng.Next(-20, 55),
        Summary = Summaries[rng.Next(Summaries.Length)]
    })
    .ToArray();

    return Conflict(result);
}

curl -v -H "Accept: application/json" http://localhost:5000/WeatherForecast
*   Trying ::1...
* TCP_NODELAY set
* Connected to localhost (::1) port 5000 (#0)
> GET /WeatherForecast HTTP/1.1
> Host: localhost:5000
> User-Agent: curl/7.54.0
> Accept: application/json

< HTTP/1.1 409 Conflict
< Date: Mon, 13 Jan 2020 21:38:03 GMT
< Content-Type: application/json; charset=utf-8
< Server: Kestrel
< Transfer-Encoding: chunked

* Connection #0 to host localhost left intact
[{"date":"2020-01-14T21:38:04.665259+00:00","temperatureC":-19,"temperatureF":-2,"summary":"Chilly"},{"date":"2020-01-15T21:38:04.673328+00:00","temperatureC":47,"temperatureF":116,"summary":"Bracing"},{"date":"2020-01-16T21:38:04.673334+00:00","temperatureC":28,"temperatureF":82,"summary":"Chilly"},{"date":"2020-01-17T21:38:04.673335+00:00","temperatureC":17,"temperatureF":62,"summary":"Warm"},{"date":"2020-01-18T21:38:04.673335+00:00","temperatureC":49,"temperatureF":120,"summary":"Bracing"}]%   

在这种情况下,无论我们Response.StatusCode在操作中设置什么,它都会被Conflict辅助方法覆盖。

如果您喜欢此文章,请收藏、点赞、评论,谢谢,祝您快乐每一天。

<think>我们正在讨论的是如何在命令提示行中运行ASP.NET Core应用程序并传递参数。注意,ASP.NET Core应用程序通常是通过`dotnet`命令运行的,而不是直接运行.exe文件(尽管在发布为独立应用时可以运行.exe)。因此,我们需要区分两种运行方式:依赖框架和独立发布。 ### 方法1: 依赖框架运行(使用dotnet命令) 这是最常见的方式,需要目标机器安装.NET Core运行时。运行命令的基本格式为: ```bash dotnet <程序集名称>.dll [参数] ``` 其中,参数直接跟在.dll文件名后面。 **步骤:** 1. **发布应用程序**(如果不在项目目录中运行,需要先发布): ```bash dotnet publish -c Release ``` 发布后的文件在`bin/Release/netX.0/publish/`目录下。 2. **运行并传递参数**: 打开命令提示符,导航到发布目录(或项目目录,如果直接运行未发布的程序),然后执行: ```bash dotnet YourAppAssembly.dll arg1 arg2 "arg with space" ``` 参数会传递到程序的`Main`方法中,通过`args`数组接收。 ### 方法2: 独立发布运行(运行可执行文件) 如果发布为独立应用(自包含),则生成一个可执行文件(.exe或平台对应的可执行文件),可以直接运行该文件并传递参数。 **步骤:** 1. **发布为独立应用**(指定运行时标识符): ```bash dotnet publish -c Release -r win-x64 --self-contained true ``` 这里以Windows x64为例,其他平台如linux-x64等。 2. **运行可执行文件并传递参数**: ```bash bin\Release\netX.0\win-x64\publish\YourAppName.exe arg1 arg2 "arg with space" ``` ### 如何在ASP.NET Core应用程序中接收参数? 在ASP.NET Core应用程序中,通常有一个`Program.cs`文件,其中包含`Main`方法。参数通过`Main`方法的`args`参数传递。 示例`Program.cs`: ```csharp public class Program { public static void Main(string[] args) { // 打印传递的参数 Console.WriteLine("命令行参数:"); foreach (var arg in args) { Console.WriteLine(arg); } CreateHostBuilder(args).Build().Run(); } public static IHostBuilder CreateHostBuilder(string[] args) => Host.CreateDefaultBuilder(args) .ConfigureWebHostDefaults(webBuilder => { webBuilder.UseStartup<Startup>(); }); } ``` 但是,注意ASP.NET Core应用程序在启动Web主机后可能会忽略这些参数(除非在配置主机时使用)。通常,命令行参数用于配置主机,例如指定URL或环境。ASP.NET Core内置支持使用命令行参数来覆盖配置。 ### 使用命令行参数配置ASP.NET Core主机 ASP.NET Core允许在命令行中传递特定的参数来配置应用程序,例如: ```bash dotnet MyApp.dll --urls "http://*:5000;https://*:5001" ``` 这些参数会被主机配置系统捕获,用于设置Web主机。 ### 自定义参数处理 如果您的应用程序需要处理自定义命令行参数,可以使用以下方法: 1. **在`CreateHostBuilder`之前解析参数**:在`Main`方法中解析`args`,然后根据参数执行不同的操作(如设置变量,然后传递给`CreateHostBuilder`)。 2. **使用配置提供程序**:ASP.NET Core的配置系统支持命令行配置提供程序。在`CreateHostBuilder`中默认已经添加了命令行配置源,所以您可以在其他地方通过配置系统读取参数。 例如,在`appsettings.json`中定义一个配置项,然后在命令行中覆盖它: ```bash dotnet MyApp.dll --MySetting "CustomValue" ``` 在代码中可以通过`IConfiguration`对象访问`MySetting`。 ### 注意事项 - **参数顺序**:参数顺序不重要,因为ASP.NET Core使用键值对形式(例如`--key value`或`--key=value`)来解析命令行参数。 - **自定义参数解析**:对于复杂的参数解析,可以使用如`System.CommandLine`(目前处于预览阶段)或第三方库(如CommandLineParser)来解析。 ### 示例:自定义参数解析 以下是一个在`Main`方法中解析自定义参数的示例: ```csharp public static void Main(string[] args) { // 解析自定义参数 string inputFile = null; for (int i = 0; i < args.Length; i++) { if (args[i] == "--input" && i + 1 < args.Length) { inputFile = args[i + 1]; } } // 构建主机,可以将解析的参数传递给Startup或其他地方 CreateHostBuilder(args).Build().Run(); } ``` ### 引用说明 - 引用[1]提到在ASP.NET Core中使用Razor帮助程序方法,虽然不直接相关,但提醒我们ASP.NET Core应用程序通常运行在Web环境中,命令行参数主要用于配置Web主机[^1]。 - 引用[2]介绍了使用Docker部署ASP.NET Core应用,这是一种避免在服务器上安装运行时的好方法,但命令行参数传递方式与直接运行类似[^2]。 - 引用[3]中提到了命令行交互中回车符的问题,这在编写需要与命令行交互的应用程序时需要注意[^3]。 ### 总结 1. **依赖框架运行**:使用`dotnet <dll>`后跟参数。 2. **独立发布运行**:直接运行可执行文件并传递参数。 3. **在程序中接收**:通过`Main`方法的`args`参数接收,并在程序中使用或配置主机。 4. **内置配置支持**:ASP.NET Core支持使用命令行参数配置主机(如`--urls`)。 ### 相关问题 1. 如何在ASP.NET Core应用程序中处理自定义命令行参数? 2. 如何将命令行参数传递给ASP.NET Core主机配置? 3. 如何在Docker容器中运行ASP.NET Core应用并传递参数?[^2] </think>### ASP.NET Core 应用程序在命令提示行带参数运行的方法 在 ASP.NET Core 应用程序中,命令行参数的传递和接收方式与控制台程序类似,但涉及 Web 主机的配置。以下是详细操作步骤: --- ### 方法 1:启动时传递参数(推荐) **核心原理**:参数通过 `dotnet run` 或可执行文件传递,在 `Program.cs` 的 `Main` 方法中接收,并用于配置 Web 主机。 1. **程序入口接收参数** 在 `Program.cs` 中通过 `Main(string[] args)` 接收参数: ```csharp public class Program { public static void Main(string[] args) { // 打印所有参数 Console.WriteLine($"收到 {args.Length} 个参数:"); foreach (var arg in args) Console.WriteLine($"- {arg}"); CreateHostBuilder(args).Build().Run(); } public static IHostBuilder CreateHostBuilder(string[] args) => Host.CreateDefaultBuilder(args) .ConfigureWebHostDefaults(webBuilder => { webBuilder.UseStartup<Startup>(); }); } ``` 2. **命令行运行方式** - **开发环境**(依赖 .NET SDK): ```bash dotnet run --arg1=value1 --arg2="value with space" --port=8080 ``` - **生产环境**(独立可执行文件): ```bash # Windows MyApp.exe --urls=http://*:5000 --env=Production # Linux/macOS ./MyApp --urls=http://*:5000 --env=Production ``` 3. **参数格式说明** - 键值对参数:`--key=value` - 位置参数:直接传递值(按顺序接收) - 含空格参数:用双引号包裹 `"value with space"` - 内置参数(如 `--urls`)会被 ASP.NET Core 自动识别[^1] --- ### 方法 2:通过环境变量传递 **适用场景**:容器化部署或需要隔离参数时(如 Docker)。 1. **启动时设置环境变量** ```bash # Windows set ASPNETCORE_ENVIRONMENT=Production && dotnet run # Linux/macOS ASPNETCORE_URLS="http://*:8080" dotnet run ``` 2. **代码中读取环境变量** ```csharp public class Startup { public void ConfigureServices(IServiceCollection services) { var env = Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT"); var port = Environment.GetEnvironmentVariable("PORT") ?? "5000"; } } ``` --- ### 方法 3:特殊参数的使用 ASP.NET Core 内置支持以下命令行参数: | **参数** | **作用** | **示例** | |------------------------|----------------------------------|-----------------------------| | `--urls` | 绑定监听的 URL | `--urls=http://*:8080` | | `--environment` | 设置运行环境 | `--environment=Staging` | | `--contentRoot` | 设置内容根目录路径 | `--contentRoot=/app/data` | | `--webRoot` | 设置静态文件路径 | `--webRoot=wwwroot-custom` | --- ### Docker 容器中的参数传递 在 Docker 部署时(如引用[2]提到的场景),通过 `ENTRYPOINT` 传递参数: ```dockerfile FROM mcr.microsoft.com/dotnet/aspnet:7.0 COPY ./publish /app ENTRYPOINT ["dotnet", "/app/MyApp.dll", "--urls=http://*:80", "--env=Production"] ``` 运行容器时追加参数: ```bash docker run myapp-image --port=8080 ``` --- ### 注意事项 1. **参数优先级**:命令行参数 > 环境变量 > appsettings.json 配置[^1] 2. **空格处理**:包含空格的参数必须用双引号包裹,避免被拆分为多个参数[^3] 3. **安全验证**:对敏感参数(如端口、路径)进行校验 4. **跨平台差异**:Linux/macOS 对参数大小写敏感(推荐使用小写) --- ### 示例场景 **运行 Web 服务并指定端口**: ```bash dotnet run --urls="http://*:8080" ``` 程序输出: ``` 收到 1 个参数: - --urls=http://*:8080 现在监听端口: 8080... ```
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

hefeng_aspnet

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值