所以我正在为我们需要在.NET Core API中使用的自定义数据格式构建一个自定义内容协商格式化程序。
using Microsoft.AspNetCore.Mvc.Formatters;
using Microsoft.AspNetCore.Http;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using System.Text;
using CustomFormatterDemo.Models;
using Microsoft.Net.Http.Headers;
using System.Reflection;
using Microsoft.Extensions.Logging;
namespace CustomFormatterDemo.Formatters
{
#region classdef
public class VcardOutputFormatter : TextOutputFormatter
#endregion
{
#region ctor
public VcardOutputFormatter()
{
SupportedMediaTypes.Add(MediaTypeHeaderValue.Parse("text/vcard"));
SupportedEncodings.Add(Encoding.UTF8);
SupportedEncodings.Add(Encoding.Unicode);
}
#endregion
#region canwritetype
protected override bool CanWriteType(Type type)
{
if (typeof(Contact).IsAssignableFrom(type)
|| typeof(IEnumerable<Contact>).IsAssignableFrom(type))
{
return base.CanWriteType(type);
}
return false;
}
#endregion
#region writeresponse
public override async Task WriteResponseBodyAsync(OutputFormatterWriteContext context, Encoding selectedEncoding)
{
IServiceProvider serviceProvider = context.HttpContext.RequestServices;
var logger = serviceProvider.GetService(typeof(ILogger<VcardOutputFormatter>)) as ILogger;
var response = context.HttpContext.Response;
var buffer = new StringBuilder();
if (context.Object is IEnumerable<Contact>)
{
foreach (Contact contact in context.Object as IEnumerable<Contact>)
{
FormatVcard(buffer, contact, logger);
}
}
else
{
var contact = context.Object as Contact;
FormatVcard(buffer, contact, logger);
}
await response.WriteAsync(buffer.ToString());
}
private static void FormatVcard(StringBuilder buffer, Contact contact, ILogger logger)
{
buffer.AppendLine("BEGIN:VCARD");
buffer.AppendLine("VERSION:2.1");
buffer.AppendFormat($"N:{contact.LastName};{contact.FirstName}rn");
buffer.AppendFormat($"FN:{contact.FirstName} {contact.LastName}rn");
buffer.AppendFormat($"UID:{contact.ID}rn");
buffer.AppendLine("END:VCARD");
logger.LogInformation("Writing {FirstName} {LastName}", contact.FirstName, contact.LastName);
}
#endregion
}
}
显然,我可以做类似throw new Exception("this doesn't work")
的事情,但这只会给 API 消费者一个 500 的响应。好奇我如何使用特定代码抛出更优雅的错误,或者至少是 500 状态的错误详细信息。
HttpResponse
类具有StatusCode
属性,因此您可以设置它。然后,如果需要,可以将正文设置为某种错误消息。
状态代码可能应该反映问题所在。因此,如果请求只是有错误的数据,您可以返回400 Bad Request
:
context.HttpContext.Response.StatusCode = 400;