ASP.NET Web API返回GUID时应设置什么Content-Type?
问题背景
我实现了一个验证凭证并返回GUID的接口,当返回类型定义为ActionResult<Guid>时,在Swagger页面调用会返回406错误。如果改成ActionResult<string>并返回sessionGuid.ToString()则能正常运行,但从API使用者角度,指定精确的GUID返回类型更具参考价值。
生成的swagger.json已经正确识别该类型:
"content": { "text/plain": { "schema": { "type": "string", "format": "uuid" } } }
Swagger界面也会显示专门的GUID示例,而非通用的"string"占位符。但由于没有对应GUID的MIME类型,导致接口调用时出现406错误,求可行的解决办法。
接口代码如下:
[Consumes("application/json")] [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status401Unauthorized)] [Produces("text/plain")] [HttpPost] public ActionResult<Guid> Authenticate([FromBody] Credentials credentials) { Guid sessionGuid; try { sessionGuid = _database.CreateApiSession(credentials); } catch (BaseRecordNotFoundException) { return Unauthorized(); } catch (BaseInvalidDataException) { return Unauthorized(); } return Ok(sessionGuid); }
解决办法
1. 自定义GUID文本格式化器
ASP.NET Core默认没有针对Guid类型的text/plain输出格式化器,导致无法正确序列化返回值,触发406错误。可以自定义一个格式化器来处理:
public class GuidPlainTextFormatter : TextOutputFormatter { public GuidPlainTextFormatter() { SupportedMediaTypes.Add(MediaTypeHeaderValue.Parse("text/plain")); SupportedEncodings.Add(Encoding.UTF8); SupportedEncodings.Add(Encoding.Unicode); } protected override bool CanWriteType(Type type) { return type == typeof(Guid) || type == typeof(Guid?); } public override Task WriteResponseBodyAsync(OutputFormatterWriteContext context, Encoding selectedEncoding) { var guid = (Guid)context.Object; return context.HttpContext.Response.WriteAsync(guid.ToString("D"), selectedEncoding); } }
然后在Program.cs中注册这个格式化器:
builder.Services.AddControllers(options => { options.OutputFormatters.Insert(0, new GuidPlainTextFormatter()); });
注册后,框架会自动用这个格式化器将Guid序列化为标准字符串格式,Swagger依然能识别uuid类型,保证文档准确性。
2. 直接返回指定内容类型的ObjectResult
不需要额外添加格式化器,在返回结果时手动包装成ObjectResult,指定内容类型并序列化GUID:
return new ObjectResult(sessionGuid.ToString("D")) { StatusCode = StatusCodes.Status200OK, ContentTypes = { "text/plain" } };
这种方式简单直接,同时Swagger文档仍会保持对GUID类型的识别。
3. 切换Produces特性为application/json
将[Produces("text/plain")]改为[Produces("application/json")],此时GUID会被序列化为JSON字符串,Swagger依然会识别为uuid格式,且不会出现406错误。不过这种方式返回的是JSON格式的字符串,而非纯文本,需根据API设计需求选择。
内容的提问来源于stack exchange,提问作者PaulH567

