在 ASP.NET Core Web API 中格式化回應資料
ASP.NET Core MVC 支援使用指定格式或回應用戶端要求的回應資料格式化。
格式特定動作結果
某些動作結果類型是特定格式所特有的,例如 JsonResult 和 ContentResult。 動作可以傳回一律使用指定格式的結果,忽略用戶端的不同格式要求。 例如,傳回 JsonResult
會傳回 JSON 格式的資料,且傳回 ContentResult
會傳回純文字格式的字串資料。
不需要動作即可傳回任何特定型別。 ASP.NET Core 支援任何物件傳回值。 使用適當的 IOutputFormatter 實作來序列化回傳物件不是 IActionResult 型別的動作結果。 如需詳細資訊,請參閱 ASP.NET Core Web API 中的控制器動作傳回型別。
根據預設,內建協助程式方法 ControllerBase.Ok 會傳回 JSON 格式資料:
[HttpGet]
public IActionResult Get() =>
Ok(_todoItemStore.GetList());
範例程式碼會傳回 ToDo 項目清單。 使用 F12 瀏覽器開發人員工具或 http-repl 搭配先前的程式碼會顯示:
- 含有 content-type:
application/json; charset=utf-8
的回應標頭。 - 要求標頭。 例如,
Accept
標頭。 上述程式碼會忽略Accept
標頭。
若要傳回純文字格式化資料,請使用 ContentResult 和 Content 協助程式:
[HttpGet("Version")]
public ContentResult GetVersion() =>
Content("v1.0.0");
在上述程式碼中,傳回的 Content-Type
是 text/plain
。
若動作使用多種傳回型別,則會傳回 IActionResult
。 例如,根據作業結果,傳回不同的 HTTP 狀態碼時。
內容交涉
用戶端指定 Accept 標頭時,即會發生內容交涉。 ASP.NET Core 使用的預設格式是 JSON。 內容交涉是:
- 由 ObjectResult 實作。
- 內建到從協助程式方法傳回的狀態碼特定動作結果。 動作結果協助程式方法是以
ObjectResult
為基礎。
傳回模型型別時,傳回型別為 ObjectResult
。
下列動作方法使用 Ok
和 NotFound
協助程式方法:
[HttpGet("{id:long}")]
public IActionResult GetById(long id)
{
var todo = _todoItemStore.GetById(id);
if (todo is null)
{
return NotFound();
}
return Ok(todo);
}
根據預設,ASP.NET Core 支援下列媒體型別:
application/json
text/json
text/plain
Fiddler 或 curl 之類的工具可以設定 Accept
要求標頭來指定傳回格式。 當 Accept
標頭包含伺服器支援的型別時,即會傳回該型別。 下節說明如何新增其他格式器。
控制器動作可以傳回 POCO (純舊 CLR 物件)。 傳回 POCO 時,執行階段會自動建立包裝該物件的 ObjectResult
。 用戶端會取得經過格式化的序列化物件。 如果傳回的物件是 null
,則會傳回 204 No Content
回應。
下列範例傳回物件類型:
[HttpGet("{id:long}")]
public TodoItem? GetById(long id) =>
_todoItemStore.GetById(id);
在上述程式碼中,有效 ToDo 項目的要求傳回 200 OK
回應。 無效 Todo 項目的要求傳回 204 No Content
回應。
Accept 標頭
當 Accept
標頭出現在要求中時,即會發生「內容交涉」。 當要求包含 Accept 標頭時,ASP.NET Core:
- 依喜好設定順序在 Accept 標頭中列舉媒體型別。
- 嘗試尋找格式器,以其中一種指定格式產生回應。
如果找不到符合用戶端要求的格式器,ASP.NET Core:
- 如果 MvcOptions.ReturnHttpNotAcceptable 設為
true
,則傳回406 Not Acceptable
,或者 - 嘗試尋找第一個可產生回應的格式器。
如果未針對所要求的格式來設定格式器,則會使用可以格式化物件的第一個格式器。 如果要求中沒有出現任何 Accept
標頭:
- 使用者以處理該物件的第一個格式器來序列化回應。
- 不會發生任何交涉。 伺服器會決定要傳回的格式。
如果 Accept 標頭包含 */*
,則除非 MvcOptions 上的 RespectBrowserAcceptHeader
設定為 true,否則會忽略標頭。
瀏覽器和內容交涉
與一般 API 用戶端不同,網頁瀏覽器會提供 Accept
標頭。 網頁瀏覽器會指定許多格式,包括萬用字元。 根據預設,當架構偵測到要求是來自於瀏覽器時:
- 會忽略
Accept
標頭。 - 除非另有設定,否則內容會以 JSON 傳回。
此方法會在取用 API 時,提供更一致的瀏覽器體驗。
若要將應用程式設定為遵守瀏覽器 Accept 標頭,請將 RespectBrowserAcceptHeader 屬性設定為 true
:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllers(options =>
{
options.RespectBrowserAcceptHeader = true;
});
設定格式器
需要支援額外格式的應用程式可以新增適當的 NuGet 套件並設定支援。 輸入和輸出有個別的格式器。 輸入格式器由模型繫結使用。 輸出格式器可用來格式化回應。 如需建立自訂格式器的相關資訊,請參閱自訂格式器。
新增 XML 格式支援
若要設定使用 XmlSerializer 實作的 XML 格式器,請呼叫 AddXmlSerializerFormatters:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllers()
.AddXmlSerializerFormatters();
使用上述程式碼時,控制器方法會根據要求的 Accept
標頭傳回適當的格式。
設定 System.Text.Json
型格式器
若要設定 System.Text.Json
型格式器的功能,請使用 Microsoft.AspNetCore.Mvc.JsonOptions.JsonSerializerOptions。 下列醒目提示的程式碼會設定 PascalCase 格式設定,而不是預設的 camelCase 格式設定:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllers()
.AddJsonOptions(options =>
{
options.JsonSerializerOptions.PropertyNamingPolicy = null;
});
下列動作方法會呼叫 ControllerBase.Problem 以建立 ProblemDetails 回應:
[HttpGet("Error")]
public IActionResult GetError() =>
Problem("Something went wrong.");
ProblemDetails
回應一律為 camelCase,即使應用程式將格式設定為 PascalCase 也一樣。 ProblemDetails
遵循 RFC 7807 中指定小寫的規範。
若要設定特定動作的輸出序列化選項,請使用 JsonResult
。 例如:
[HttpGet]
public IActionResult Get() =>
new JsonResult(
_todoItemStore.GetList(),
new JsonSerializerOptions
{
PropertyNamingPolicy = null
});
新增 Newtonsoft.Json
型 JSON 格式支援
預設 JSON 格式器使用 System.Text.Json
。 若要使用 Newtonsoft.Json
型格式器,請安裝 Microsoft.AspNetCore.Mvc.NewtonsoftJson
NuGet 套件並在 Program.cs
中設定:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllers()
.AddNewtonsoftJson();
在上述程式碼中,呼叫 AddNewtonsoftJson
以將下列 Web API、MVC 和 Razor Pages 功能設定為使用 Newtonsoft.Json
:
- 讀取和寫入 JSON 的輸入和輸出格式器
- JsonResult
- JSON 修補檔
- IJsonHelper
- TempData
某些功能可能無法搭配 System.Text.Json
型格式器使用,而且需要 Newtonsoft.Json
型格式器的參考。 當應用程式有下列情況時,繼續使用 Newtonsoft.Json
型格式器:
- 使用
Newtonsoft.Json
屬性。 例如,[JsonProperty]
或[JsonIgnore]
。 - 自訂序列化設定。
- 依賴
Newtonsoft.Json
提供的功能。
若要設定 Newtonsoft.Json
型格式器的功能,請使用 SerializerSettings:
builder.Services.AddControllers()
.AddNewtonsoftJson(options =>
{
options.SerializerSettings.ContractResolver = new DefaultContractResolver();
});
若要設定特定動作的輸出序列化選項,請使用 JsonResult
。 例如:
[HttpGet]
public IActionResult GetNewtonsoftJson() =>
new JsonResult(
_todoItemStore.GetList(),
new JsonSerializerSettings
{
ContractResolver = new DefaultContractResolver()
});
指定格式
若要限制回應格式,請套用 [Produces]
篩選。 與大部分篩選類似,動作、控制器或全域範圍都可以套用 [Produces]
:
[ApiController]
[Route("api/[controller]")]
[Produces("application/json")]
public class TodoItemsController : ControllerBase
上述 [Produces]
篩選:
- 強制控制器內的所有動作傳回 POCO (純舊 CLR 物件) 的 JSON 格式化回應或 ObjectResult 及其衍生型別。
- 即使已設定其他格式器,且用戶端指定了不同格式,仍會傳回 JSON 格式化回應。
如需詳細資訊,請參閱篩選。
特殊案例格式器
有些特殊案例是使用內建格式器所實作。 根據預設,string
傳回型別的格式設定為 text/plain (如果透過 Accept
標頭發出要求,則為 text/html)。 移除 StringOutputFormatter,即可刪除此行為。 格式器要在 Program.cs
中移除。 傳回 null
時,擁有模型物件傳回型別的動作會傳回 204 No Content
。 移除 HttpNoContentOutputFormatter,即可刪除此行為。 下列程式碼會移除 StringOutputFormatter
和 HttpNoContentOutputFormatter
。
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllers(options =>
{
// using Microsoft.AspNetCore.Mvc.Formatters;
options.OutputFormatters.RemoveType<StringOutputFormatter>();
options.OutputFormatters.RemoveType<HttpNoContentOutputFormatter>();
});
如果沒有 StringOutputFormatter
,則內建的 JSON 格式器會格式化 string
傳回型別。 如果移除內建的 JSON 格式器,而且可以使用 XML 格式器,則 XML 格式器會格式化 string
傳回型別。 否則,string
傳回型別會傳回 406 Not Acceptable
。
如果沒有 HttpNoContentOutputFormatter
,則會使用已設定的格式器來格式化 Null 物件。 例如:
- JSON 格式器會傳回具有
null
本文的回應。 - XML 格式器會傳回已設定
xsi:nil="true"
屬性的空白 XML 元素。
回應格式 URL 對應
用戶端可以要求 URL 的一部分採用特定格式,例如:
- 在查詢字串或路徑的一部分。
- 使用格式專用的副檔名,例如 .xml 或 .json。
應該在 API 所使用的路由中指定要求路徑的對應。 例如:
[ApiController]
[Route("api/[controller]")]
[FormatFilter]
public class TodoItemsController : ControllerBase
{
private readonly TodoItemStore _todoItemStore;
public TodoItemsController(TodoItemStore todoItemStore) =>
_todoItemStore = todoItemStore;
[HttpGet("{id:long}.{format?}")]
public TodoItem? GetById(long id) =>
_todoItemStore.GetById(id);
上述路由允許使用選用的副檔名來指定要求的格式。 [FormatFilter]
屬性會檢查 RouteData
中是否有格式值,並在建立回應時將回應格式對應至適當的格式器。
路由 | 格式器 |
---|---|
/api/todoitems/5 |
預設輸出格式器 |
/api/todoitems/5.json |
JSON 格式器 (如果已設定) |
/api/todoitems/5.xml |
XML 格式器 (如果已設定) |
多型還原序列化
內建功能提供有限的多形序列化範圍,但完全不支援還原序列化。 還原序列化需要自訂轉換器。 如需多型還原序列化的完整範例,請參閱多型還原序列化。
其他資源
- 檢視或下載範例程式碼 \(英文\) (如何下載)
ASP.NET Core MVC 支援格式化回應資料。 回應資料可以使用特定格式或回應用戶端要求的格式進行格式化。
檢視或下載範例程式碼 \(英文\) (如何下載)
格式特定動作結果
某些動作結果類型是特定格式所特有的,例如 JsonResult 和 ContentResult。 不論用戶端喜好設定為何,動作都可以傳回以特定格式格式化的結果。 例如,傳回 JsonResult
會傳回 JSON 格式資料。 傳回 ContentResult
或字串會傳回純文字格式的字串資料。
不需要動作即可傳回任何特定型別。 ASP.NET Core 支援任何物件傳回值。 使用適當的 IOutputFormatter 實作來序列化回傳物件不是 IActionResult 型別的動作結果。 如需詳細資訊,請參閱 ASP.NET Core Web API 中的控制器動作傳回型別。
內建的協助程式方法 Ok 會傳回 JSON 格式資料:
// GET: api/authors
[HttpGet]
public ActionResult Get()
{
return Ok(_authors.List());
}
範例下載會傳回作者清單。 使用 F12 瀏覽器開發人員工具或 http-repl 搭配先前的程式碼:
- 顯示含有 content-type:
application/json; charset=utf-8
的回應標頭。 - 隨即顯示要求標頭。 例如,
Accept
標頭。 上述程式碼會忽略Accept
標頭。
若要傳回純文字格式化資料,請使用 ContentResult 和 Content 協助程式:
// GET api/authors/about
[HttpGet("About")]
public ContentResult About()
{
return Content("An API listing authors of docs.asp.net.");
}
在上述程式碼中,傳回的 Content-Type
是 text/plain
。 傳回字串會傳遞 text/plain
的 Content-Type
:
// GET api/authors/version
[HttpGet("version")]
public string Version()
{
return "Version 1.0.0";
}
若動作使用多種傳回型別,則會傳回 IActionResult
。 例如,根據執行的作業結果,傳回不同的 HTTP 狀態碼。
內容交涉
用戶端指定 Accept 標頭時,即會發生內容交涉。 ASP.NET Core 使用的預設格式是 JSON。 內容交涉是:
- 由 ObjectResult 實作。
- 內建到從協助程式方法傳回的狀態碼特定動作結果。 動作結果協助程式方法是以
ObjectResult
為基礎。
傳回模型型別時,傳回型別為 ObjectResult
。
下列動作方法使用 Ok
和 NotFound
協助程式方法:
// GET: api/authors/search?namelike=th
[HttpGet("Search")]
public IActionResult Search(string namelike)
{
var result = _authors.GetByNameSubstring(namelike);
if (!result.Any())
{
return NotFound(namelike);
}
return Ok(result);
}
根據預設,ASP.NET Core 支援 application/json
、text/json
和 text/plain
媒體型別。 Fiddler 或 http-repl 之類的工具可以設定 Accept
要求標頭來指定傳回格式。 當 Accept
標頭包含伺服器支援的型別時,即會傳回該型別。 下節說明如何新增其他格式器。
控制器動作可以傳回 POCO (純舊 CLR 物件)。 傳回 POCO 時,執行階段會自動建立包裝該物件的 ObjectResult
。 用戶端會取得經過格式化的序列化物件。 如果傳回的物件是 null
,則會傳回 204 No Content
回應。
傳回物件類型:
// GET api/authors/RickAndMSFT
[HttpGet("{alias}")]
public Author Get(string alias)
{
return _authors.GetByAlias(alias);
}
在上述程式碼中,有效作者別名的要求會傳回含有作者資料的 200 OK
回應。 無效別名的要求會傳回 204 No Content
回應。
Accept 標頭
當 Accept
標頭出現在要求中時,即會發生「內容交涉」。 當要求包含 Accept 標頭時,ASP.NET Core:
- 依喜好設定順序在 Accept 標頭中列舉媒體型別。
- 嘗試尋找格式器,以其中一種指定格式產生回應。
如果找不到符合用戶端要求的格式器,ASP.NET Core:
- 如果 MvcOptions.ReturnHttpNotAcceptable 設為
true
,則傳回406 Not Acceptable
,或者 - 嘗試尋找第一個可產生回應的格式器。
如果未針對所要求的格式來設定格式器,則會使用可以格式化物件的第一個格式器。 如果要求中沒有出現任何 Accept
標頭:
- 使用者以處理該物件的第一個格式器來序列化回應。
- 不會發生任何交涉。 伺服器會決定要傳回的格式。
如果 Accept 標頭包含 */*
,則除非 MvcOptions 上的 RespectBrowserAcceptHeader
設定為 true,否則會忽略標頭。
瀏覽器和內容交涉
與一般 API 用戶端不同,網頁瀏覽器會提供 Accept
標頭。 網頁瀏覽器會指定許多格式,包括萬用字元。 根據預設,當架構偵測到要求是來自於瀏覽器時:
- 會忽略
Accept
標頭。 - 除非另有設定,否則內容會以 JSON 傳回。
此方法會在取用 API 時,提供更一致的瀏覽器體驗。
若要將應用程式設定為使用瀏覽器 Accept 標頭,請將 RespectBrowserAcceptHeader 設定為 true
:
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers(options =>
{
options.RespectBrowserAcceptHeader = true; // false by default
});
}
設定格式器
需要支援其他格式的應用程式可以新增適當的 NuGet 套件並設定支援。 輸入和輸出有個別的格式器。 輸入格式器由模型繫結使用。 輸出格式器可用來格式化回應。 如需建立自訂格式器的相關資訊,請參閱自訂格式器。
新增 XML 格式支援
若要設定使用 XmlSerializer 實作的 XML 格式器,請呼叫 AddXmlSerializerFormatters:
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers()
.AddXmlSerializerFormatters();
}
上述程式碼會使用 XmlSerializer
來序列化結果。
使用上述程式碼時,控制器方法會根據要求的 Accept
標頭傳回適當的格式。
設定 System.Text.Json
型格式器
您可以使用 Microsoft.AspNetCore.Mvc.JsonOptions.JsonSerializerOptions 來設定 System.Text.Json
型格式器的功能。 預設格式設定為 camelCase。 下列醒目提示的程式碼會設定 PascalCase 格式設定:
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers()
.AddJsonOptions(options =>
options.JsonSerializerOptions.PropertyNamingPolicy = null);
}
下列動作方法會呼叫 ControllerBase.Problem 以建立 ProblemDetails 回應:
[HttpGet("error")]
public IActionResult GetError()
{
return Problem("Something went wrong!");
}
在上述程式碼中:
https://localhost:5001/WeatherForecast/temperature
會傳回 PascalCase。https://localhost:5001/WeatherForecast/error
會傳回 camelCase。 錯誤回應一律為 camelCase,即使應用程式將格式設定為 PascalCase 也一樣。ProblemDetails
遵循 RFC 7807 中指定小寫的規範
下列程式碼會設定 PascalCase 並新增自訂轉換器:
services.AddControllers().AddJsonOptions(options =>
{
// Use the default property (Pascal) casing.
options.JsonSerializerOptions.PropertyNamingPolicy = null;
// Configure a custom converter.
options.JsonSerializerOptions.Converters.Add(new MyCustomJsonConverter());
});
您可以按照每個動作,使用 JsonResult
來設定輸出序列化選項。 例如:
public IActionResult Get()
{
return Json(model, new JsonSerializerOptions
{
WriteIndented = true,
});
}
新增 Newtonsoft.Json 型 JSON 格式支援
預設的 JSON 格式器是以 System.Text.Json
為基礎。 在 Startup.ConfigureServices
中安裝及設定 Microsoft.AspNetCore.Mvc.NewtonsoftJson
NuGet 套件後,即可使用 Newtonsoft.Json
型格式器和功能支援。
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers()
.AddNewtonsoftJson();
}
在上述程式碼中,呼叫 AddNewtonsoftJson
以將下列 Web API、MVC 和 Razor Pages 功能設定為使用 Newtonsoft.Json
:
- 讀取和寫入 JSON 的輸入和輸出格式器
- JsonResult
- JSON 修補檔
- IJsonHelper
- TempData
某些功能可能無法搭配 System.Text.Json
型格式器使用,而且需要 Newtonsoft.Json
型格式器的參考。 當應用程式有下列情況時,繼續使用 Newtonsoft.Json
型格式器:
- 使用
Newtonsoft.Json
屬性。 例如,[JsonProperty]
或[JsonIgnore]
。 - 自訂序列化設定。
- 依賴
Newtonsoft.Json
提供的功能。
您可以使用 Microsoft.AspNetCore.Mvc.MvcNewtonsoftJsonOptions.SerializerSettings
來設定 Newtonsoft.Json
型格式器的功能:
services.AddControllers().AddNewtonsoftJson(options =>
{
// Use the default property (Pascal) casing
options.SerializerSettings.ContractResolver = new DefaultContractResolver();
// Configure a custom converter
options.SerializerSettings.Converters.Add(new MyCustomJsonConverter());
});
您可以按照每個動作,使用 JsonResult
來設定輸出序列化選項。 例如:
public IActionResult Get()
{
return Json(model, new JsonSerializerSettings
{
Formatting = Formatting.Indented,
});
}
指定格式
若要限制回應格式,請套用 [Produces]
篩選。 與大部分篩選類似,動作、控制器或全域範圍都可以套用 [Produces]
:
[ApiController]
[Route("[controller]")]
[Produces("application/json")]
public class WeatherForecastController : ControllerBase
{
上述 [Produces]
篩選:
- 強制控制器內的所有動作傳回 POCO (純舊 CLR 物件) 的 JSON 格式化回應或 ObjectResult 及其衍生型別。
- 如果已設定其他格式器,且用戶端指定了不同格式,則會傳回 JSON。
如需詳細資訊,請參閱篩選。
特殊案例格式器
有些特殊案例是使用內建格式器所實作。 根據預設,string
傳回型別的格式設定為 text/plain (如果透過 Accept
標頭發出要求,則為 text/html)。 移除 StringOutputFormatter,即可刪除此行為。 您可以使用 ConfigureServices
方法移除格式器。 傳回 null
時,擁有模型物件傳回型別的動作會傳回 204 No Content
。 移除 HttpNoContentOutputFormatter,即可刪除此行為。 下列程式碼會移除 StringOutputFormatter
和 HttpNoContentOutputFormatter
。
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers(options =>
{
// requires using Microsoft.AspNetCore.Mvc.Formatters;
options.OutputFormatters.RemoveType<StringOutputFormatter>();
options.OutputFormatters.RemoveType<HttpNoContentOutputFormatter>();
});
}
如果沒有 StringOutputFormatter
,則內建的 JSON 格式器會格式化 string
傳回型別。 如果移除內建的 JSON 格式器,而且可以使用 XML 格式器,則 XML 格式器會格式化 string
傳回型別。 否則,string
傳回型別會傳回 406 Not Acceptable
。
如果沒有 HttpNoContentOutputFormatter
,則會使用已設定的格式器來格式化 Null 物件。 例如:
- JSON 格式器會傳回具有
null
本文的回應。 - XML 格式器會傳回已設定
xsi:nil="true"
屬性的空白 XML 元素。
回應格式 URL 對應
用戶端可以要求 URL 的一部分採用特定格式,例如:
- 在查詢字串或路徑的一部分。
- 使用格式專用的副檔名,例如 .xml 或 .json。
應該在 API 所使用的路由中指定要求路徑的對應。 例如:
[Route("api/[controller]")]
[ApiController]
[FormatFilter]
public class ProductsController : ControllerBase
{
[HttpGet("{id}.{format?}")]
public Product Get(int id)
{
上述路由允許將要求的格式指定為選用的副檔名。 [FormatFilter]
屬性會檢查 RouteData
中是否有格式值,並在建立回應時將回應格式對應至適當的格式器。
路由 | 格式器 |
---|---|
/api/products/5 |
預設輸出格式器 |
/api/products/5.json |
JSON 格式器 (如果已設定) |
/api/products/5.xml |
XML 格式器 (如果已設定) |
ASP.NET Core MVC 支援使用指定格式或回應用戶端要求的回應資料格式化。
格式特定動作結果
某些動作結果類型是特定格式所特有的,例如 JsonResult 和 ContentResult。 動作可以傳回一律使用指定格式的結果,忽略用戶端的不同格式要求。 例如,傳回 JsonResult
會傳回 JSON 格式的資料,且傳回 ContentResult
會傳回純文字格式的字串資料。
不需要動作即可傳回任何特定型別。 ASP.NET Core 支援任何物件傳回值。 使用適當的 IOutputFormatter 實作來序列化回傳物件不是 IActionResult 型別的動作結果。 如需詳細資訊,請參閱 ASP.NET Core Web API 中的控制器動作傳回型別。
根據預設,內建協助程式方法 ControllerBase.Ok 會傳回 JSON 格式資料:
[HttpGet]
public IActionResult Get()
=> Ok(_todoItemStore.GetList());
範例程式碼會傳回 ToDo 項目清單。 使用 F12 瀏覽器開發人員工具或 http-repl 搭配先前的程式碼會顯示:
- 含有 content-type:
application/json; charset=utf-8
的回應標頭。 - 要求標頭。 例如,
Accept
標頭。 上述程式碼會忽略Accept
標頭。
若要傳回純文字格式化資料,請使用 ContentResult 和 Content 協助程式:
[HttpGet("Version")]
public ContentResult GetVersion()
=> Content("v1.0.0");
在上述程式碼中,傳回的 Content-Type
是 text/plain
。
若動作使用多種傳回型別,則會傳回 IActionResult
。 例如,根據作業結果,傳回不同的 HTTP 狀態碼時。
內容交涉
用戶端指定 Accept 標頭時,即會發生內容交涉。 ASP.NET Core 使用的預設格式是 JSON。 內容交涉是:
- 由 ObjectResult 實作。
- 內建到從協助程式方法傳回的狀態碼特定動作結果。 動作結果協助程式方法是以
ObjectResult
為基礎。
傳回模型型別時,傳回型別為 ObjectResult
。
下列動作方法使用 Ok
和 NotFound
協助程式方法:
[HttpGet("{id:long}")]
public IActionResult GetById(long id)
{
var todo = _todoItemStore.GetById(id);
if (todo is null)
{
return NotFound();
}
return Ok(todo);
}
根據預設,ASP.NET Core 支援下列媒體型別:
application/json
text/json
text/plain
Fiddler 或 http-repl 之類的工具可以設定 Accept
要求標頭來指定傳回格式。 當 Accept
標頭包含伺服器支援的型別時,即會傳回該型別。 下節說明如何新增其他格式器。
控制器動作可以傳回 POCO (純舊 CLR 物件)。 傳回 POCO 時,執行階段會自動建立包裝該物件的 ObjectResult
。 用戶端會取得經過格式化的序列化物件。 如果傳回的物件是 null
,則會傳回 204 No Content
回應。
下列範例傳回物件類型:
[HttpGet("{id:long}")]
public TodoItem? GetById(long id)
=> _todoItemStore.GetById(id);
在上述程式碼中,有效 ToDo 項目的要求傳回 200 OK
回應。 無效 Todo 項目的要求傳回 204 No Content
回應。
Accept 標頭
當 Accept
標頭出現在要求中時,即會發生「內容交涉」。 當要求包含 Accept 標頭時,ASP.NET Core:
- 依喜好設定順序在 Accept 標頭中列舉媒體型別。
- 嘗試尋找格式器,以其中一種指定格式產生回應。
如果找不到符合用戶端要求的格式器,ASP.NET Core:
- 如果 MvcOptions.ReturnHttpNotAcceptable 設為
true
,則傳回406 Not Acceptable
,或者 - 嘗試尋找第一個可產生回應的格式器。
如果未針對所要求的格式來設定格式器,則會使用可以格式化物件的第一個格式器。 如果要求中沒有出現任何 Accept
標頭:
- 使用者以處理該物件的第一個格式器來序列化回應。
- 不會發生任何交涉。 伺服器會決定要傳回的格式。
如果 Accept 標頭包含 */*
,則除非 MvcOptions 上的 RespectBrowserAcceptHeader
設定為 true,否則會忽略標頭。
瀏覽器和內容交涉
與一般 API 用戶端不同,網頁瀏覽器會提供 Accept
標頭。 網頁瀏覽器會指定許多格式,包括萬用字元。 根據預設,當架構偵測到要求是來自於瀏覽器時:
- 會忽略
Accept
標頭。 - 除非另有設定,否則內容會以 JSON 傳回。
此方法會在取用 API 時,提供更一致的瀏覽器體驗。
若要將應用程式設定為遵守瀏覽器 Accept 標頭,請將 RespectBrowserAcceptHeader 屬性設定為 true
:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllers(options =>
{
options.RespectBrowserAcceptHeader = true;
});
設定格式器
需要支援額外格式的應用程式可以新增適當的 NuGet 套件並設定支援。 輸入和輸出有個別的格式器。 輸入格式器由模型繫結使用。 輸出格式器可用來格式化回應。 如需建立自訂格式器的相關資訊,請參閱自訂格式器。
新增 XML 格式支援
若要設定使用 XmlSerializer 實作的 XML 格式器,請呼叫 AddXmlSerializerFormatters:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllers()
.AddXmlSerializerFormatters();
使用上述程式碼時,控制器方法會根據要求的 Accept
標頭傳回適當的格式。
設定 System.Text.Json
型格式器
若要設定 System.Text.Json
型格式器的功能,請使用 Microsoft.AspNetCore.Mvc.JsonOptions.JsonSerializerOptions。 下列醒目提示的程式碼會設定 PascalCase 格式設定,而不是預設的 camelCase 格式設定:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllers()
.AddJsonOptions(options =>
{
options.JsonSerializerOptions.PropertyNamingPolicy = null;
});
若要設定特定動作的輸出序列化選項,請使用 JsonResult。 例如:
[HttpGet]
public IActionResult Get()
=> new JsonResult(
_todoItemStore.GetList(),
new JsonSerializerOptions { PropertyNamingPolicy = null });
新增 Newtonsoft.Json
型 JSON 格式支援
預設 JSON 格式器使用 System.Text.Json
。 若要使用 Newtonsoft.Json
型格式器,請安裝 Microsoft.AspNetCore.Mvc.NewtonsoftJson
NuGet 套件並在 Program.cs
中設定:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllers()
.AddNewtonsoftJson();
在上述程式碼中,呼叫 AddNewtonsoftJson
以將下列 Web API、MVC 和 Razor Pages 功能設定為使用 Newtonsoft.Json
:
- 讀取和寫入 JSON 的輸入和輸出格式器
- JsonResult
- JSON 修補檔
- IJsonHelper
- TempData
某些功能可能無法搭配 System.Text.Json
型格式器使用,而且需要 Newtonsoft.Json
型格式器的參考。 當應用程式有下列情況時,繼續使用 Newtonsoft.Json
型格式器:
- 使用
Newtonsoft.Json
屬性。 例如,[JsonProperty]
或[JsonIgnore]
。 - 自訂序列化設定。
- 依賴
Newtonsoft.Json
提供的功能。
若要設定 Newtonsoft.Json
型格式器的功能,請使用 SerializerSettings:
builder.Services.AddControllers()
.AddNewtonsoftJson(options =>
{
options.SerializerSettings.ContractResolver = new DefaultContractResolver();
});
若要設定特定動作的輸出序列化選項,請使用 JsonResult
。 例如:
[HttpGet]
public IActionResult GetNewtonsoftJson()
=> new JsonResult(
_todoItemStore.GetList(),
new JsonSerializerSettings { ContractResolver = new DefaultContractResolver() });
格式 ProblemDetails
和 ValidationProblemDetails
回應
下列動作方法會呼叫 ControllerBase.Problem 以建立 ProblemDetails 回應:
[HttpGet("Error")]
public IActionResult GetError()
=> Problem("Something went wrong.");
ProblemDetails
回應一律為 camelCase,即使應用程式將格式設定為 PascalCase 也一樣。 ProblemDetails
遵循 RFC 7807 中指定小寫的規範。
當 [ApiController]
屬性套用至控制器類別時,控制器會在模型驗證失敗時建立 ValidationProblemDetails 回應。 此回應所含的字典未變更,該字典使用模型的屬性名稱作為錯誤索引鍵。 例如,下列模型包含需要驗證的單一屬性:
public class SampleModel
{
[Range(1, 10)]
public int Value { get; set; }
}
根據預設,傳回的 ValidationProblemDetails
回應會在 Value
屬性無效時使用 Value
的錯誤索引鍵,如下列範例所示:
{
"type": "https://tools.ietf.org/html/rfc7231#section-6.5.1",
"title": "One or more validation errors occurred.",
"status": 400,
"traceId": "00-00000000000000000000000000000000-000000000000000-00",
"errors": {
"Value": [
"The field Value must be between 1 and 10."
]
}
}
若要格式化用作錯誤索引鍵的屬性名稱,請將 IMetadataDetailsProvider 的實作新增至 MvcOptions.ModelMetadataDetailsProviders 集合。 下列範例會新增 System.Text.Json
型實作 SystemTextJsonValidationMetadataProvider
,將屬性名稱格式設定預設為 camelCase:
builder.Services.AddControllers();
builder.Services.Configure<MvcOptions>(options =>
{
options.ModelMetadataDetailsProviders.Add(
new SystemTextJsonValidationMetadataProvider());
});
SystemTextJsonValidationMetadataProvider
也接受在其建構函式中實作 JsonNamingPolicy,以指定用來格式化屬性名稱的自訂命名原則。
若要設定模型內屬性的自訂名稱,請在屬性中使用 [JsonPropertyName] 屬性:
public class SampleModel
{
[Range(1, 10)]
[JsonPropertyName("sampleValue")]
public int Value { get; set; }
}
針對上述模型傳回的 ValidationProblemDetails
回應會在 Value
屬性無效時使用 sampleValue
的錯誤索引鍵,如下列範例所示:
{
"type": "https://tools.ietf.org/html/rfc7231#section-6.5.1",
"title": "One or more validation errors occurred.",
"status": 400,
"traceId": "00-00000000000000000000000000000000-000000000000000-00",
"errors": {
"sampleValue": [
"The field Value must be between 1 and 10."
]
}
}
若要使用 Newtonsoft.Json
格式化 ValidationProblemDetails
回應,請使用 NewtonsoftJsonValidationMetadataProvider
:
builder.Services.AddControllers()
.AddNewtonsoftJson();
builder.Services.Configure<MvcOptions>(options =>
{
options.ModelMetadataDetailsProviders.Add(
new NewtonsoftJsonValidationMetadataProvider());
});
根據預設,NewtonsoftJsonValidationMetadataProvider
會將屬性名稱格式化為 camelCase。 NewtonsoftJsonValidationMetadataProvider
也接受在其建構函式中實作 NamingPolicy
,以指定用來格式化屬性名稱的自訂命名原則。 若要設定模型內屬性的自訂名稱,請使用 [JsonProperty]
屬性。
指定格式
若要限制回應格式,請套用 [Produces]
篩選。 與大部分篩選類似,動作、控制器或全域範圍都可以套用 [Produces]
:
[ApiController]
[Route("api/[controller]")]
[Produces("application/json")]
public class TodoItemsController : ControllerBase
上述 [Produces]
篩選:
- 強制控制器內的所有動作傳回 POCO (純舊 CLR 物件) 的 JSON 格式化回應或 ObjectResult 及其衍生型別。
- 即使已設定其他格式器,且用戶端指定了不同格式,仍會傳回 JSON 格式化回應。
如需詳細資訊,請參閱篩選。
特殊案例格式器
有些特殊案例是使用內建格式器所實作。 根據預設,string
傳回型別的格式設定為 text/plain (如果透過 Accept
標頭發出要求,則為 text/html)。 移除 StringOutputFormatter,即可刪除此行為。 格式器要在 Program.cs
中移除。 傳回 null
時,擁有模型物件傳回型別的動作會傳回 204 No Content
。 移除 HttpNoContentOutputFormatter,即可刪除此行為。 下列程式碼會移除 StringOutputFormatter
和 HttpNoContentOutputFormatter
。
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllers(options =>
{
// using Microsoft.AspNetCore.Mvc.Formatters;
options.OutputFormatters.RemoveType<StringOutputFormatter>();
options.OutputFormatters.RemoveType<HttpNoContentOutputFormatter>();
});
如果沒有 StringOutputFormatter
,則內建的 JSON 格式器會格式化 string
傳回型別。 如果移除內建的 JSON 格式器,而且可以使用 XML 格式器,則 XML 格式器會格式化 string
傳回型別。 否則,string
傳回型別會傳回 406 Not Acceptable
。
如果沒有 HttpNoContentOutputFormatter
,則會使用已設定的格式器來格式化 Null 物件。 例如:
- JSON 格式器會傳回具有
null
本文的回應。 - XML 格式器會傳回已設定
xsi:nil="true"
屬性的空白 XML 元素。
回應格式 URL 對應
用戶端可以要求 URL 的一部分採用特定格式,例如:
- 在查詢字串或路徑的一部分。
- 使用格式專用的副檔名,例如 .xml 或 .json。
應該在 API 所使用的路由中指定要求路徑的對應。 例如:
[ApiController]
[Route("api/[controller]")]
[FormatFilter]
public class TodoItemsController : ControllerBase
{
private readonly TodoItemStore _todoItemStore;
public TodoItemsController(TodoItemStore todoItemStore)
=> _todoItemStore = todoItemStore;
[HttpGet("{id:long}.{format?}")]
public TodoItem? GetById(long id)
=> _todoItemStore.GetById(id);
上述路由允許使用選用的副檔名來指定要求的格式。 [FormatFilter]
屬性會檢查 RouteData
中是否有格式值,並在建立回應時將回應格式對應至適當的格式器。
路由 | 格式器 |
---|---|
/api/todoitems/5 |
預設輸出格式器 |
/api/todoitems/5.json |
JSON 格式器 (如果已設定) |
/api/todoitems/5.xml |
XML 格式器 (如果已設定) |
多型還原序列化
內建功能提供有限的多形序列化範圍,但完全不支援還原序列化。 還原序列化需要自訂轉換器。 如需多型還原序列化的完整範例,請參閱多型還原序列化。
其他資源
- 檢視或下載範例程式碼 \(英文\) (如何下載)