C# DecoderFallbackException:无法将索引75处的字节[BF]从指定的代码页转换为Unicode

C# DecoderFallbackException:无法将索引75处的字节[BF]从指定的代码页转换为Unicode,c#,character-encoding,asp.net-core-webapi,C#,Character Encoding,Asp.net Core Webapi,在我正在处理的.NET Core 2.1 Web API上,我有一个POST方法接收一个只有一个属性的JSON对象,如下所示: { "longURL": "http://foo.example.com/path/path/path/path/path/pfad" } { "longURL": "http://foo.example.com/path/path/path/path/path/pfad¿" } public class DecoderFallbackExcepti

在我正在处理的.NET Core 2.1 Web API上,我有一个POST方法接收一个只有一个属性的JSON对象,如下所示:

{
    "longURL": "http://foo.example.com/path/path/path/path/path/pfad"
}
{
    "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());
        }
}
和方法的标题:

public async Task<ActionResult<ShortenerOutputDto>> CreateAsync([FromBody] 
ShortenerInputDto input)
请注意,最后一个(?)是冒犯的角色。 我得到的例外是:

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)
问题是在进入controllers方法之前抛出异常

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

更新

根据@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()));
但如果请求中有特殊字符,则不会命中ReadJson或WriteJson

所以,似乎在内核尝试转换输入之前,解码或解码就发生了。真奇怪

更新II

原始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¿"
}

最后,我添加了一个异常过滤器,如下所示:

{
    "longURL": "http://foo.example.com/path/path/path/path/path/pfad"
}
{
    "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());
        });
也许这不是我最初期望的解决方案,但它很有效,让我能够控制我应该为每个案例采取的任何行动

此外,我可以再次向该方法添加输入参数,并重新启用单元测试。

顺便说一句,这种行为在ASP.NET Core 3.0中似乎会得到增强。

使用http,您需要使用System.Net.WebUtility.HtmlCode(字符串)/System.Net.WebUtility.HtmlCode(字符串)进行编码/解码。请参见wiki:@jdweng请求来自外部世界,因此我无法对其标题进行编码或添加任何内容。请求必须进行编码/解码以删除特殊字符,否则请求将失败。它应该已经被编码/解码,如果不是,则发送消息的应用程序有错误。很可能是编码的,在发送到JSON之前您已经解码了。请看:@jdweng谢谢。请看我的更新。我不认为这是unicode编码。它应该是一个窗口编码。请参阅发布:。unicode从何而来?它不在发布代码中。向上投票!对于偶然发现这一点的人:
在索引X
X
指的是请求主体中的位置
bytes[X]
X
是该系统的十六进制字符。文本正在尝试解码。