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