解码器fallbackexception:无法从指定代码页面转换为Unicode,在索引75处将字节[BF]转换



在.NET Core 2.1 Web API上,我正在处理,我已经接收一个只有一个属性的JSON对象,例如:

{
    "longURL": "http://foo.example.com/path/path/path/path/path/pfad"
}

和方法的标题:

public async Task<ActionResult<ShortenerOutputDto>> CreateAsync([FromBody] 
ShortenerInputDto input)

但是,如果输入JSON包含一些特殊字符,我会得到一个例外,例如:

{
    "longURL": "http://foo.example.com/path/path/path/path/path/pfad¿"
}

请注意,最后一个(»)是有问题的角色。我得到的例外是:

System.Text.DecoderFallbackException: Unable to translate bytes [BF] at index 75 from specified code page to Unicode.
   at System.Text.DecoderExceptionFallbackBuffer.Throw(Byte[] bytesUnknown, Int32 index)
   at System.Text.DecoderExceptionFallbackBuffer.Fallback(Byte[] bytesUnknown, Int32 index)
   at System.Text.DecoderFallbackBuffer.InternalFallback(Byte[] bytes, Byte* pBytes, Char*& chars)
   at System.Text.UTF8Encoding.GetChars(Byte* bytes, Int32 byteCount, Char* chars, Int32 charCount, DecoderNLS baseDecoder)
   at System.Text.DecoderNLS.GetChars(Byte[] bytes, Int32 byteIndex, Int32 byteCount, Char[] chars, Int32 charIndex, Boolean flush)
   at System.Text.DecoderNLS.GetChars(Byte[] bytes, Int32 byteIndex, Int32 byteCount, Char[] chars, Int32 charIndex)
   at Microsoft.AspNetCore.WebUtilities.HttpRequestStreamReader.ReadIntoBuffer()
   at Microsoft.AspNetCore.WebUtilities.HttpRequestStreamReader.Read(Char[] buffer, Int32 index, Int32 count)
   at Newtonsoft.Json.JsonTextReader.ReadData(Boolean append, Int32 charsRequired)
   at Newtonsoft.Json.JsonTextReader.ParseValue()
   at Newtonsoft.Json.JsonTextReader.Read()
   at Newtonsoft.Json.JsonReader.ReadForType(JsonContract contract, Boolean hasConverter)
   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.Deserialize(JsonReader reader, Type objectType, Boolean checkAdditionalContent)

问题是在输入控制器方法之前先抛出了例外。

那么,有没有办法避免这种情况?我想发送一个badrequest,以防输入无法解码。

update

基于 @jdweng的答案,我添加了以下转换器类:

public class HtmlEncodingConverter : JsonConverter
{
        public override bool CanConvert(Type objectType)
        {
            return objectType == typeof(String);
        }
        public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
        {
            return System.Web.HttpUtility.HtmlDecode((string)reader.Value);
        }
        public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
        {
writer.WriteRawValue(System.Web.HttpUtility.HtmlEncode((string)value));
        }
}

并注册为jsonoptions:

services.AddMvc()
    .AddJsonOptions (opt => opt.SerializerSettings.Converters.Add(new HtmlEncodingConverter()));

但是,如果请求某个特殊字符,请读书和写入。

因此,在Core的尝试转换输入之前,解码或解码似乎发生在发生之前。真的很奇怪。

更新II

RAW HTTP请求消息:

POST /create HTTP/1.0
Host: localhost:5000
Content-Length: 80
Content-Type: application/json
{
    "longURL" : "http://foo.example.com/path/path/path/path/path/pfad¿"
}

最后,我最终添加了这样的异常过滤器:

public class DecoderFallbackExceptionFilter : IExceptionFilter
{
        public void OnException(ExceptionContext context)
        {
            if (context.Exception.GetType() == typeof(DecoderFallbackException))
                context.Result = new BadRequestObjectResult(ShortURLResponse.InvalidURL());
        }
}

...并在startup.cs中注册:

services.AddMvc(opt =>
        {
            opt.Filters.Add(new DecoderFallbackExceptionFilter());
        });

也许这不是我最初期望的解决方案,而是奏效的,允许我控制每种情况应采取的任何行动。

此外,我可以再次将输入参数添加到该方法,并重新启用单位测试。https://github.com/aspnet/aspnetcore/issues/8676

顺便说一句,似乎在ASP.NET Core 3.0中增强了这种行为。https://github.com/aspnet/aspnetcore/issues/3959

相关内容

  • 没有找到相关文章

最新更新