AspNetCore.Docs/aspnet/web-api/overview/formats-and-model-binding/content-negotiation.md

106 lines
5.9 KiB
Markdown
Raw Normal View History

merge aspnetmigration to master (#2668) * Initial aspnet migration * Updating legacy urls * Clearing .gitignore file Clearing .gitignore file because this isnt a normal .net application where we want to strip away debug files, etc. We want to include everything under these folders. * Updating webhooks toc reference * Removing header debug links * Updating webhooks toc * Updating double quotes in metadata to use single quotes * Moving all code blocks to external files * Updating newlines for step-by-step * Fixing indent problem on some code blocks * Fixing newlines in alt attribute for images; Fixing some missing code block references * Resyncing with live content * Refreshing content from production * Trying to get pdf to generate for our aspnetmigration branch * Update .openpublishing.publish.config.json * Refresh from prod; Removing some legacy urls for pages that shouldnt have it * Updating index pages and removing legacy urls * Updating warning and caution notes * Removing downloads * remove aspnet from exclude list (#2549) * First pass at language detection * Updating author and adding in msc.type * Updating code blocks * Updating note styles * Fixing note styles * Updating docfx.json file to allow pdfs and gifs * Fixing note stylings for bold notes * Updating docfx.json to allow exe, zip and wmv files * Fixing note styles with period; Fixing downloads links * Fixing code blocks for razor cs and vb * Fixing more downloads links; Fixing a few code blocks * Removing   html entity * Fixing some more note stylings * Syncing with prod * Fixing issues with content * Rebuilding toc file * Adding back in files accidentally deleted * Fixing some security notes * Fixing some note styles * Updating unknown code blocks * Updating article * Fixing link * Fixing link * Fixing link * Fixing invalid characters * preliminary toc changes * update toc * fix toc folder with only one link * Fixing extra heading * Fixing articles * Reworking ajax pages * Fixing encoding issues * Updating markup in articles * Fixing space * Fixing spacing issues with links * Fixing note styles * Fixing inline note styles * Fixing missing image * Adding space * Rolling back gitignore file and adding a new one for /aspnet * Fixing some code blocks * Updating code block language * Renaming file * Updating code language * Fixing code blocks * Fixing code blocks * Fixing spaces before 'using' * Fixing cs to js * Changing Note type * Updating broken reference * Replacing headings with bolds under notes/tips, etc * Fixing markdown for pipes * Another attempted to fix pipe characters * Fixing markdown for pipes * remove text about being thread-safe (#2630) * Fixing spacing issue with list * Trying to fix pipe issue * new how to choose doc * move choose doc to core folder * add api ref * fix link * Adding in ms.assetid * Removing \ufeff * fix link * link to mvc intro instead of webhooks * add scenarios * put core first, vertical orientation for scenarios * reorganize toc, make overview work like core version * fix yaml * fix broken links * Adding space * add download link * tweak tables * eliminate images * eliminate images 2 * tweak scenario section headings * add link to core in asp.net overview * Removing gears * Updating table * Updating code block languages * fix urls (#2663) * Removing embedded in-article TOC from top of articles * fix urls (#2666) * fix urls * fix urls * Removing embedded in-article TOC from top of articles * Revert "Removing embedded in-article TOC from top of articles" This reverts commit ff1c3ccdf1cf2d705e0bb040144a10fa130796f6. * Revert "Removing embedded in-article TOC from top of articles" This reverts commit 17c37c726d930ec6854b545bab076dffda486ebe.
2017-02-04 05:40:22 +08:00
---
uid: web-api/overview/formats-and-model-binding/content-negotiation
merge aspnetmigration to master (#2668) * Initial aspnet migration * Updating legacy urls * Clearing .gitignore file Clearing .gitignore file because this isnt a normal .net application where we want to strip away debug files, etc. We want to include everything under these folders. * Updating webhooks toc reference * Removing header debug links * Updating webhooks toc * Updating double quotes in metadata to use single quotes * Moving all code blocks to external files * Updating newlines for step-by-step * Fixing indent problem on some code blocks * Fixing newlines in alt attribute for images; Fixing some missing code block references * Resyncing with live content * Refreshing content from production * Trying to get pdf to generate for our aspnetmigration branch * Update .openpublishing.publish.config.json * Refresh from prod; Removing some legacy urls for pages that shouldnt have it * Updating index pages and removing legacy urls * Updating warning and caution notes * Removing downloads * remove aspnet from exclude list (#2549) * First pass at language detection * Updating author and adding in msc.type * Updating code blocks * Updating note styles * Fixing note styles * Updating docfx.json file to allow pdfs and gifs * Fixing note stylings for bold notes * Updating docfx.json to allow exe, zip and wmv files * Fixing note styles with period; Fixing downloads links * Fixing code blocks for razor cs and vb * Fixing more downloads links; Fixing a few code blocks * Removing   html entity * Fixing some more note stylings * Syncing with prod * Fixing issues with content * Rebuilding toc file * Adding back in files accidentally deleted * Fixing some security notes * Fixing some note styles * Updating unknown code blocks * Updating article * Fixing link * Fixing link * Fixing link * Fixing invalid characters * preliminary toc changes * update toc * fix toc folder with only one link * Fixing extra heading * Fixing articles * Reworking ajax pages * Fixing encoding issues * Updating markup in articles * Fixing space * Fixing spacing issues with links * Fixing note styles * Fixing inline note styles * Fixing missing image * Adding space * Rolling back gitignore file and adding a new one for /aspnet * Fixing some code blocks * Updating code block language * Renaming file * Updating code language * Fixing code blocks * Fixing code blocks * Fixing spaces before 'using' * Fixing cs to js * Changing Note type * Updating broken reference * Replacing headings with bolds under notes/tips, etc * Fixing markdown for pipes * Another attempted to fix pipe characters * Fixing markdown for pipes * remove text about being thread-safe (#2630) * Fixing spacing issue with list * Trying to fix pipe issue * new how to choose doc * move choose doc to core folder * add api ref * fix link * Adding in ms.assetid * Removing \ufeff * fix link * link to mvc intro instead of webhooks * add scenarios * put core first, vertical orientation for scenarios * reorganize toc, make overview work like core version * fix yaml * fix broken links * Adding space * add download link * tweak tables * eliminate images * eliminate images 2 * tweak scenario section headings * add link to core in asp.net overview * Removing gears * Updating table * Updating code block languages * fix urls (#2663) * Removing embedded in-article TOC from top of articles * fix urls (#2666) * fix urls * fix urls * Removing embedded in-article TOC from top of articles * Revert "Removing embedded in-article TOC from top of articles" This reverts commit ff1c3ccdf1cf2d705e0bb040144a10fa130796f6. * Revert "Removing embedded in-article TOC from top of articles" This reverts commit 17c37c726d930ec6854b545bab076dffda486ebe.
2017-02-04 05:40:22 +08:00
title: "Content Negotiation in ASP.NET Web API | Microsoft Docs"
author: MikeWasson
description: "Describes how ASP.NET Web API implements HTTP content negotiation."
ms.author: aspnetcontent
manager: wpickett
ms.date: 05/20/2012
ms.topic: article
ms.assetid: 0dd51b30-bf5a-419f-a1b7-2817ccca3c7d
ms.technology: dotnet-webapi
ms.prod: .net-framework
msc.legacyurl: /web-api/overview/formats-and-model-binding/content-negotiation
msc.type: authoredcontent
---
Content Negotiation in ASP.NET Web API
====================
by [Mike Wasson](https://github.com/MikeWasson)
This article describes how ASP.NET Web API implements content negotiation.
The HTTP specification (RFC 2616) defines content negotiation as "the process of selecting the best representation for a given response when there are multiple representations available." The primary mechanism for content negotiation in HTTP are these request headers:
- **Accept:** Which media types are acceptable for the response, such as "application/json," "application/xml," or a custom media type such as "application/vnd.example+xml"
- **Accept-Charset:** Which character sets are acceptable, such as UTF-8 or ISO 8859-1.
- **Accept-Encoding:** Which content encodings are acceptable, such as gzip.
- **Accept-Language:** The preferred natural language, such as "en-us".
The server can also look at other portions of the HTTP request. For example, if the request contains an X-Requested-With header, indicating an AJAX request, the server might default to JSON if there is no Accept header.
In this article, we'll look at how Web API uses the Accept and Accept-Charset headers. (At this time, there is no built-in support for Accept-Encoding or Accept-Language.)
## Serialization
If a Web API controller returns a resource as CLR type, the pipeline serializes the return value and writes it into the HTTP response body.
For example, consider the following controller action:
[!code-csharp[Main](content-negotiation/samples/sample1.cs)]
A client might send this HTTP request:
[!code-console[Main](content-negotiation/samples/sample2.cmd)]
In response, the server might send:
[!code-console[Main](content-negotiation/samples/sample3.cmd)]
In this example, the client requested either JSON, Javascript, or "anything" (\*/\*). The server responsed with a JSON representation of the `Product` object. Notice that the Content-Type header in the response is set to "application/json".
A controller can also return an **HttpResponseMessage** object. To specify a CLR object for the response body, call the **CreateResponse** extension method:
[!code-csharp[Main](content-negotiation/samples/sample4.cs)]
This option gives you more control over the details of the response. You can set the status code, add HTTP headers, and so forth.
The object that serializes the resource is called a *media formatter*. Media formatters derive from the **MediaTypeFormatter** class. Web API provides media formatters for XML and JSON, and you can create custom formatters to support other media types. For information about writing a custom formatter, see [Media Formatters](media-formatters.md).
## How Content Negotiation Works
First, the pipeline gets the **IContentNegotiator** service from the **HttpConfiguration** object. It also gets the list of media formatters from the **HttpConfiguration.Formatters** collection.
Next, the pipeline calls **IContentNegotiatior.Negotiate**, passing in:
- The type of object to serialize
- The collection of media formatters
- The HTTP request
The **Negotiate** method returns two pieces of information:
- Which formatter to use
- The media type for the response
If no formatter is found, the **Negotiate** method returns **null**, and the client recevies HTTP error 406 (Not Acceptable).
The following code shows how a controller can directly invoke content negotiation:
[!code-csharp[Main](content-negotiation/samples/sample5.cs)]
This code is equivalent to the what the pipeline does automatically.
## Default Content Negotiator
The **DefaultContentNegotiator** class provides the default implementation of **IContentNegotiator**. It uses several criteria to select a formatter.
First, the formatter must be able to serialize the type. This is verified by calling **MediaTypeFormatter.CanWriteType**.
Next, the content negotiator looks at each formatter and evaluates how well it matches the HTTP request. To evaluate the match, the content negotiator looks at two things on the formatter:
- The **SupportedMediaTypes** collection, which contains a list of supported media types. The content negotiator tries to match this list against the request Accept header. Note that the Accept header can include ranges. For example, "text/plain" is a match for text/\* or \*/\*.
- The **MediaTypeMappings** collection, which contains a list of **MediaTypeMapping** objects. The **MediaTypeMapping** class provides a generic way to match HTTP requests with media types. For example, it could map a custom HTTP header to a particular media type.
If there are multiple matches, the match with the highest quality factor wins. For example:
[!code-console[Main](content-negotiation/samples/sample6.cmd)]
In this example, application/json has an implied quality factor of 1.0, so it is preferred over application/xml.
If no matches are found, the content negotiator tries to match on the media type of the request body, if any. For example, if the request contains JSON data, the content negotiator looks for a JSON formatter.
If there are still no matches, the content negotiator simply picks the first formatter that can serialize the type.
## Selecting a Character Encoding
2017-03-14 04:55:57 +08:00
After a formatter is selected, the content negotiator chooses the best character encoding by looking at the **SupportedEncodings** property on the formatter, and matching it against the Accept-Charset header in the request (if any).