Lecture thumbnail 0:03 / 12:20 In ASP.NET Core, content negotiation is about the interaction between client and server

about the content that is present in the request body and response body.

For example, when the browser makes a request to server, it can include a request header

that is content type. So it contains the type of the content that is present in the request body.

For example, if the request body contains JSON information, then the request header contains

content type equal to application by JSON, which means that the browser ensuring the

server that the request body contains the JSON data. Then when the server receives the request,

it can either accept or reject the same. In case if the server rejects that particular

content type in the request body, it returns HTTP 415 response. The 415 unsupported media type

informs the client that, hey browser or client, this particular content type in the request body

is not allowed or supported by the particular server. Okay, this is about request body.

Similarly, there can be some interaction between client and server about response body. When the

browser makes a request to server, it can again include another request header saying that

except and that is equal to the main type of request body type.

For example, if the browser expects the response in the form of JSON, it can include a request

header that is except with appropriate main type that is JSON, I mean application by JSON.

Then server reads that request header except equal to application by JSON.

Then the server will try to convert the data into the appropriate content type that is present in

the except request header. In case if the server don’t want to do that, means if it is not supported

by the particular action method, it can provide the response in the form of any other desired

format. For example, the server might give the response in the form of application by XML.

But the server should and will inform the same as a part of the response headers. For example,

the request header is except application by JSON. That means the browser wants the response in the

form of JSON. But suppose the server reads it, but it wants to give the response in the form of XML

instead of JSON. Then the server converts the data into XML, I mean response body is filled

with XML data. And accordingly, it adds a response header that is content type equal to application

by XML, which means, hey browser, yes, you have asked for JSON information, but I’m not giving

the same. But the data in the response body is XML data. So content type equal to application

by XML. Like this, there will be conversation between client and server about request body

as well as response body. So how do you handle the same in Web API? Particularly in ASP.NET Core,

by default, both request body as well as response body is assumed as JSON information.

But the practical problem is, if you notice the open API specification, that is JSON file,

it says that every endpoint may give the information, I mean response in different

content types. For example, for this get request API slash cities, the response content type can be

either text by plain, or application by JSON, or text by JSON. It can be either of these,

that is the default content types supported by Web API. But suppose assume that we are clear that

we want to give the information only in application by JSON. Of course, practically,

either of these three doesn’t make any difference. If the response contains only JSON information,

if the schema is same, you may give the response in JSON format in either of the content types.

But we want to provide the clarity to the client that we want to give the response

only in the form of application by JSON. I mean, we want to remove the other two.

How do you mention the same? You can do that by using a predefined filter called produces.

There is an attribute cum filter that is produces attribute, which can be applied to a particular

action method, controller, or even globally to specify the appropriate content type that is

supported by the action methods. For example, let me apply the same globally. In order to apply

global filters, locate the add controllers method and write a lambda expression options

and in these options, you can add a filter. I mean, a global filter. A new instance of

produces attribute that is imported from that is present in Microsoft.aspnet core.mvc namespace.

So, in this particular constructor, you can specify the appropriate content type

that is by default available on all the action methods of all the controllers in the entire

application because we are applying the same globally. So, from now onwards, the default

content type of all action methods is application by JSON without ambiguity. Let us see the effect

of the same. I did not make any changes in the controller. So, now if you notice the open API

specification, again if you notice the same endpoint, api slash cities get, now the response

would contain only one content type because we have mentioned the same by using produces attribute.

We clearly mentioned that all the action methods would produce only the content in the form of

application by JSON. Since we have applied globally, it affects all action methods,

not only for get request but also for post request. For example, for post request,

that is here as well. See, we are talking about only response type, not about request type.

Since we have not mentioned anything particularly for request body, by default, it is taken as either

of the three, text by JSON, application by JSON or application by star JSON. Okay. Practically,

there would be no difference between among these three, but the browser can mention anything of

this in the content type in the request header. But suppose we wanted to provide the clarity that

we would like to support only application by JSON, not other two, that is for request body also.

In order to mention the same, we have another attribute. So most similarly, we have consumes

attribute. The consumes specifies about request body content type and the produces attribute

specifies about response body content type. We have mentioned both as application by JSON

and see the effect. If you notice the same JSON document, now, the response content type is already

mentioned as application by JSON. But now, for the post request, even the request body also is

strictly mentioned as application by JSON. So if any other client mentions content type as other

than this application by JSON in the request body, that would not be accepted. And then the

client gets 415 unsupported media type response. Okay, that’s fine. But how do you customize the

same for particular controller or particular action method? For example, the particular

get endpoint, I mean, get cities endpoint in the cities controller wants to provide the information

in the form of XML instead of JSON, means globally for all the action methods, application by JSON,

that’s okay. For a particular action method, I would like to customize the same. Then obviously,

for that particular action method, you can apply produces or consumes whatever you want.

I mean, depending on you’re talking about request body type or response body type.

Particularly, I would like to talk about response content type. So produces, for example, application

by XML, I would like to give this cities information in the form of XML. But XML serialization by

default not enabled in ASP.NET Core, we have to enable the same explicitly. And it’s not that

difficult. Simply go to the program.cs file. After this add controllers, add a method called

add XML serializer formatters. So this enables the XML serialization for the particular action

methods where you mentioned produces as application by XML. So only for this particular action method,

response would be application by XML. But for all the remaining methods, response would be

application by JSON. Let’s run. Now check it out. If you notice the XML specification

for the particular get request API slash cities, the response content type is mentioned as

application by XML, still the same schema. The same schema at the bottom would contain

the same properties, no change, because this reflects the model class,

city ID and city name. And if you try to test by sending a request,

click on get request, write out, execute. We make the request right now. And the response now would

contain XML format. Of course, nowadays, most of all types of client applications, including

mobile applications, web applications, even desktop applications require the response in

the form of JSON only. It is pretty rare to use XML as response content type, since it occupies

large amount of memory, since there are too many number of characters for each property.

Just for demonstration, we have enabled XML serialization, but in practical, it’s pretty

rare to use XML formatting for response. So overall, produces attribute specifies about

response content type and consumes attribute specifies about request body content type.

You can mention them either action method level or controller level or even global level,

where the controller level attribute can override the setting of global level and action method

level attribute can override the setting of either global level or controller level.

Okay, for proceeding for further examples,

let’s comment out this produces application by XML. That’s fine.

Play Play Stop Play Play Play Start Start Start