ASP.NET 5 MVC 6 XML-заголовок ответа
У меня есть контроллер, который возвращает пользовательскую строку XML, потому что приложение, которое использует API, нуждается в определенном формате без каких-либо атрибутов и без <?xml ... />
тег поверх стандартных XML-строк. РЕДАКТИРОВАТЬ: у потребителя также нет заголовка запроса, который запрашивает "text/xml".
Мои ConfigureServices в моем Startup.cs выглядят так:
public void ConfigureServices(IServiceCollection services)
{
// Add framework services.
var mvc = services.AddMvc();
mvc.AddMvcOptions(options =>
{
options.InputFormatters.Remove(new JsonInputFormatter());
options.OutputFormatters.Remove(new JsonOutputFormatter());
});
mvc.AddXmlDataContractSerializerFormatters();
}
В моем контроллере я попробовал некоторые решения, которые я нашел в Интернете (закомментировано), но ни одно из них не дает мне XML-контент с заголовком ответа "Content-Type: application/xml" в chrome devtools:
[HttpGet("{ssin}")]
[Produces("application/xml")]
public string Get(string ssin)
{
var xmlString = "";
using (var stream = new StringWriter())
{
var xml = new XmlSerializer(person.GetType());
xml.Serialize(stream, person);
xmlString = stream.ToString();
}
var doc = XDocument.Parse(xmlString);
doc.Root.RemoveAttributes();
doc.Descendants("PatientId").FirstOrDefault().Remove();
doc.Descendants("GeslachtId").FirstOrDefault().Remove();
doc.Descendants("GeboorteDatumUur").FirstOrDefault().Remove();
doc.Descendants("OverledenDatumUur").FirstOrDefault().Remove();
Response.ContentType = "application/xml";
Response.Headers["Content-Type"] = "application/xml";
/*var response = new HttpResponseMessage
{
Content = new StringContent(doc.ToString(), Encoding.UTF8, "application/xml"),
};*/
return doc.ToString(); //new HttpResponseMessage { Content = new StringContent(doc., Encoding.UTF8, "application/xml") };
}
Что я могу попытаться заставить его ответить с приложением / XML?
EDIT1 (после ответа Луки Герси): Startup.cs:
public Startup(IHostingEnvironment env)
{
// Set up configuration sources.
var builder = new ConfigurationBuilder()
.AddJsonFile("appsettings.json")
.AddEnvironmentVariables();
Configuration = builder.Build();
}
public IConfigurationRoot Configuration { get; set; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
// Add framework services.
var mvc = services.AddMvc(config => {
config.RespectBrowserAcceptHeader = true;
config.InputFormatters.Add(new XmlSerializerInputFormatter());
config.OutputFormatters.Add(new XmlSerializerOutputFormatter());
});
mvc.AddMvcOptions(options =>
{
options.InputFormatters.Remove(new JsonInputFormatter());
options.OutputFormatters.Remove(new JsonOutputFormatter());
});
//mvc.AddXmlDataContractSerializerFormatters();
}
/*
* Preconfigure if the application is in a subfolder/subapplication on IIS
* Temporary fix for issue: https://github.com/aspnet/IISIntegration/issues/14
*/
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
app.Map("/rrapi", map => ConfigureApp(map, env, loggerFactory));
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void ConfigureApp(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
loggerFactory.AddConsole(Configuration.GetSection("Logging"));
loggerFactory.AddDebug();
//app.UseIISPlatformHandler();
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
});
}
// Entry point for the application.
public static void Main(string[] args) => WebApplication.Run<Startup>(args);
контроллер:
[HttpGet("{ssin}")]
[Produces("application/xml")]
public IActionResult Get(string ssin)
{
var patient = db.Patienten.FirstOrDefault(
p => p.Rijksregisternummer.Replace(".", "").Replace("-", "").Replace(" ", "") == ssin
);
var postcode = db.Postnummers.FirstOrDefault(p => p.PostnummerId == db.Gemeentes.FirstOrDefault(g =>
g.GemeenteId == db.Adressen.FirstOrDefault(a =>
a.ContactId == patient.PatientId && a.ContactType == "pat").GemeenteId
).GemeenteId
).Postcode;
var person = new person
{
dateOfBirth = patient.GeboorteDatumUur.Value.ToString(""),
district = postcode,
gender = (patient.GeslachtId == 101 ? "MALE" : "FEMALE"),
deceased = (patient.OverledenDatumUur == null ? "FALSE" : "TRUE"),
firstName = patient.Voornaam,
inss = patient.Rijksregisternummer.Replace(".", "").Replace("-", "").Replace(" ", ""),
lastName = patient.Naam
};
var xmlString = "";
using (var stream = new StringWriter())
{
var opts = new XmlWriterSettings { OmitXmlDeclaration = true };
using (var xw = XmlWriter.Create(stream, opts))
{
var xml = new XmlSerializer(person.GetType());
xml.Serialize(xw, person);
}
xmlString = stream.ToString();
}
var doc = XDocument.Parse(xmlString);
doc.Root.RemoveAttributes();
doc.Descendants("PatientId").FirstOrDefault().Remove();
doc.Descendants("GeslachtId").FirstOrDefault().Remove();
doc.Descendants("GeboorteDatumUur").FirstOrDefault().Remove();
doc.Descendants("OverledenDatumUur").FirstOrDefault().Remove();
return Ok(doc.ToString());
2 ответа
Создать XmlWriter
Параметры заполнения, чтобы заблокировать создание декларации XML. Затем используйте один из XmlSerializer.Serialize
перегрузки, которые принимают XmlWriter
, XmlWriter
Можно записать в строку (см. здесь):
using (var sw = new StringWriter()) {
var opts = new XmlWriterSettings { OmitXmlDeclaration = true };
using (var xw = XmlWriter.Create(sw, opts) {
xml.Serialize(xw, person);
}
xmlString = sw.ToString();
}
NB Вы уже настраиваете Response.ContentType
поэтому что-то еще, если переопределить это. Проверьте фильтры и модули, которые могут переопределять ваши настройки.
Похоже, эта статья - то, что вы ищете. Вместо того, чтобы пытаться сделать это вручную, вы должны попробовать форматтер XML, например так:
// Add framework services.
services.AddMvc(config =>
{
// Add XML Content Negotiation
config.RespectBrowserAcceptHeader = true;
config.InputFormatters.Add(new XmlSerializerInputFormatter());
config.OutputFormatters.Add(new XmlSerializerOutputFormatter());
});
Этот outputFormatter зависит от:
"Microsoft.AspNet.Mvc.Formatters.Xml": "6.0.0-rc1-final"
Также вам нужно уйти [Produces("application/xml")]
как атрибут метода, как подробно описано в этом ответе.
Посмотрите также эту чрезвычайно подробную статью о форматерах в MVC 6. Это обновленная версия. Я думаю, это будет полезно.
Чтобы изменить способ генерирования ответа, вы можете использовать объект параметров XmlWriterSettings, например так (подробнее здесь):
var settings = new XmlWriterSettings { OmitXmlDeclaration = true };
config.OutputFormatters.Add(new XmlSerializerOutputFormatter(settings);
Надеюсь, поможет!