I'm trying to create a Web-Api based on asp.net core. My requirement is that, it should support xml serialization by default and not json.
I added
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1)
.AddXmlSerializerFormatters();
But still, the default serializer is json.
I need it to return xml without the client having to specify
{"Accept":"application/xml"}
As said here, you must force your application to produce XML instead of JSON:
services.AddMvc(opt =>
{
opt.Filters.Add(new ProducesAttribute("application/xml"));
}).SetCompatibilityVersion(CompatibilityVersion.Version_2_2)
.AddXmlSerializerFormatters();
For changing default serializer, you could try
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc(options => {
options.OutputFormatters.Insert(0, new XmlDataContractSerializerOutputFormatter());
}).SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
}
Related
I am using the following to accept XML serialized in my Core API App.
services.AddMvc(options =>
{
// allow xml format for input
options.InputFormatters.Add(new XmlSerializerInputFormatter());
}).SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
After updating to ASP.NET Core 2.1 I receive the following warning:
'XmlSerializerInputFormatter.XmlSerializerInputFormatter()' is obsolete: 'This constructor is obsolete and will be removed in a future version.'
What is the new way to handle this?
According to the source code, there's a constructor that has not been marked as Obsolete:
public XmlSerializerInputFormatter(MvcOptions options)
This constructor takes an instance of MvcOptions, so you can pass through your existing options argument:
services.AddMvc(options =>
{
// allow xml format for input
options.InputFormatters.Add(new XmlSerializerInputFormatter(options));
}) ...
As of ASP.NET Core 3.0, this constructor is the only one available. Those that were marked obsolete have now been removed.
With .NET Core 2.2 or later XmlSerializerInputFormatter should be marked as deprecated.
Instead a of explicitly defining XML serializers as we did before, in the .NET Core 2.2 we can add them simply by calling AddXmlSerializerFormatters() method which will do the job now. Read here why it has been deprecated
Here is how you can do it.
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc(config =>
{
config.RespectBrowserAcceptHeader = true;
config.ReturnHttpNotAcceptable = true;
config.OutputFormatters.Add(new CsvOutputFormatter());
}).AddXmlSerializerFormatters().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
}
I'm using Asp.net Core Razor Pages and I'm returning json. I need the json to be in camel casing across the board, therefore I tried to set the resolver in Startup.cs like this
services.AddMvc()
.AddJsonOptions(options => {
options.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
});
However this does not work, the razor page is still returning json in Pascal casing. How do I correct the issue? Thank you.
When you use AddJsonOptions, you are configuring an instance of JsonSerializerSettings that is specific to ASP.NET Core MVC. When you use JsonConvert.SerializeObject, you're using a different instance of JsonSerializerSettings. In order to affect that instance, you can use JsonConvert.DefaultSettings, like so:
JsonConvert.DefaultSettings = () => new JsonSerializerSettings
{
ContractResolver = new CamelCasePropertyNamesContractResolver()
};
Unfortunately, changes you make to DefaultSettings do not apply to the instance that's configured via AddJsonOptions - You'll need to configure those separately. You can see how that is a separate instance that gets created by a JsonSerializerSettingsProvider in the source, if you're interested.
REST services should provide content negotiation. This means that clients send an Accept header that contains the desired content type of the response. If the service does not support this media type, it should respond with status code 406 (Not Acceptable).
I try to map this behavior to ASP.NET Core. ASP.NET core returns a JSON document, if it doesn't recognize the media type in the Accept header. In previous versions of the framework the behavior described above could be achieved by adding a special output formatter to the configuration:
public void ConfigureServices(IServiceCollection services) {
services.AddMvc(options => {
options.OutputFormatters.Insert(0, new HttpNotAcceptableOutputFormatter());
});
}
Unfortunately, HttpNotAcceptableOutputFormatter was removed from the ASP.NET Core framework after RC1. Is there any replacement for this class in the current version of the framework?
I had this before:
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc();
}
Then I change it to AddMvcCore() instead of AddMvc()
public void ConfigureServices(IServiceCollection services)
{
services.AddMvcCore();
}
Finally I had that issue with the Response 406 so what I did was to add .AddJsonFormatters() to services.AddMVCCore() and my API worked again.
public void ConfigureServices(IServiceCollection services)
{
services.AddMvcCore()
.AddJsonFormatters();
}
In such cases, it’s a good idea to find the commit that removed the functionality, to see what it likely got replaced with. In this case, HttpNotAcceptableOutputFormatter was removed with this commit to fix issue #4612:
Alter content negotiation algorithm so that it can be configured (via MvcOptions) to always respect an explicit Accept header.
What it was replaced with is MvcOptions.ReturnHttpNotAcceptable, which is a setting on the MvcOptions that you configure when adding MVC with AddMvc.
So your code should become like this:
services.AddMvc(options =>
{
options.ReturnHttpNotAcceptable = true;
});
You add this to the ConfigureService method in the Startup class.
services.AddMvc(options =>
{
options.ReturnHttpNotAcceptable = true;
// If you need to add support for XML
// options.OutputFormatters.Add(new XmlDataContractSerializerOutputFormatter());
});
None of the above answer worked for me , finally this worked
Adding the following line in ConfigureServices of Startup.cs
public void ConfigureServices(IServiceCollection services)
{
services.AddMvcCore().AddJsonFormatters().AddApiExplorer();
}
I am building a Web API in which I can add input/outut formatters in the start up class. This works for XML but its not working for Json. I know Json is added by default but it seems to choose XML if the Accept header is not specified.
public void ConfigureServices(IServiceCollection services)
{
//Add framework services.
services.AddMvc(options =>
{
options.RequireHttpsPermanent = true;
options.RespectBrowserAcceptHeader = true;
options.ReturnHttpNotAcceptable = true;
options.OutputFormatters.Add(new XmlDataContractSerializerOutputFormatter());
options.InputFormatters.Add(new XmlDataContractSerializerInputFormatter());
});
services.AddDbContext<CustomerManagerContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection"))
);
services.AddScoped<IUnitOfWork, UnitOfWork>();
}
In the configure services method I added the xmlSerializer however this does not work for Json:
options.OutputFormatters.Add(new JsonOutputFormatter());
The default formatter is the first one added to the list of formatters. I would like to add the Json formatters before the XML so it would become the default. What am I missing? How do I properly add the Json formatter so it is first in the list of formatters?
I'm assuming the Accept header of the request is set for XML instead of JSON. Negotiations are only done if the Accept header of the request specifies a format, otherwise the default is used (JSON by default), and if that can't meet the request, the server decides.
If you're getting XML all the time, my guess is the request from the consumer is asking for XML.
I've just swapped our project from ASP .Net Core 1.0.0-rc2-final to 1.0.0. Our website and client have stopped working because of the capitalization of JSON properties. For example, this line of JavaScript now fails
for (var i = 0; i < collection.Items.length; i++){
because the controller now calls the array "items" instead of "Items". I have made no changes beyond installing the updated packages and editing the project.json file. I have not changed the C# model files which still capitalize their properties.
Why have the ASP.Net Core controllers started returning JSON with lower-cased properties? How do I go back to them honoring the case of the property names from the model?
MVC now serializes JSON with camel case names by default
Use this code to avoid camel case names by default
services.AddMvc()
.AddJsonOptions(options => options.SerializerSettings.ContractResolver = new DefaultContractResolver());
Source:
https://github.com/aspnet/Announcements/issues/194
In case you found this from Google and looking for a solution for Core 3.
Core 3 uses System.Text.Json, which by default does not preserve the case. As mentioned with this GitHub issue, setting the PropertyNamingPolicy to null will fix the problem.
public void ConfigureServices(IServiceCollection services)
{
...
services.AddControllers()
.AddJsonOptions(opts => opts.JsonSerializerOptions.PropertyNamingPolicy = null);
and if you don't want to change the global settings, for one action only it's like this:
return Json(obj, new JsonSerializerOptions { PropertyNamingPolicy = null });
You can change the behavior like this:
services
.AddMvc()
.AddJsonOptions(options => options.SerializerSettings.ContractResolver = new DefaultContractResolver());
See the announcement here: https://github.com/aspnet/Announcements/issues/194
For those who migrated to Core 3.1 and have Core MVC project can use following setup code in Startup.cs:
public void ConfigureServices(IServiceCollection services)
{
...
services.AddControllersWithViews().AddJsonOptions(opts => opts.JsonSerializerOptions.PropertyNamingPolicy = null);
...
}
This will fix it in dotnet core 3 webapi, so that it doesn't change your property names at all, and you return to your client exactly what you intended to.
In Startup.cs:
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers().AddJsonOptions(options => options.JsonSerializerOptions.PropertyNamingPolicy = null);
services.AddHttpClient();
}
For someone who does not want to set it globally, it is possible to use ContractResolver also to return as Json result:
public IActionResult MyMethod()
{
var obj = new {myValue = 1};
return Json(obj, new JsonSerializerSettings {ContractResolver = new DefaultContractResolver()});
}
For some one who is using ASP.net WEB API ( rather than ASP.NET Core).
Add this line in your WebApiConfig.
//Comment this jsonFormatter.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
jsonFormatter.SerializerSettings.ContractResolver = new DefaultContractResolver();
Adding this as an answer here because this comes up first in google search for web api as well.
For ASP MVC Core 6 Web API , Add below code into Program.cs file will make sure JSON propreties name follow C# model properties name in right casing. No 3rd party package require
using Microsoft.AspNetCore.Mvc;
builder.Services.Configure<JsonOptions>(options =>
{
options.JsonSerializerOptions.PropertyNamingPolicy = null;
});
For Core 2.x versions, using this code you can avoid camel case names by default. You need to add following code inside the ConfigureServices method of Startup.cs file.
services.AddMvc()
.AddJsonOptions(o =>
{
if (o.SerializerSettings.ContractResolver != null)
{
var castedResolver = o.SerializerSettings.ContractResolver
as DefaultContractResolver;
castedResolver.NamingStrategy = null;
}
});
Recently had this issue with .Net6
The solution turned out to be that I needed to install
Microsoft.AspNetCore.Mvc.NewtonsoftJson 6.0.0.x (Note, use 7.x for .Net 7)
Found this out from Mason's post:
Microsoft.AspNetCore.Mvc.NewtonsoftJson 6.0.2 is not compatible with net5.0
Install
Microsoft.AspNetCore.Mvc.NewtonsoftJson
For .net 6 you should select this version: 6.0.13
and then go to Program.cs and configure it like this
builder.Services
.AddControllersWithViews()
.AddNewtonsoftJson(options => options.SerializerSettings.ContractResolver = new DefaultContractResolver());