2016-07-10 11 views
1

Ich entwickle eine Web-API in MVC-Projekt. Ich gebe ein JToken-Objekt in meiner Post-Methode zurück. Normalerweise meine api richtig funktioniert aber einige Male in bestimmten Daten bekomme ich diesen Fehler:"Fehler beim Konvertieren von Unicode-Zeichen \ uD83C" beim Zurückgeben von JSON aus asp.net POST-Methode

"Message": "An error has occurred.", 
    "ExceptionMessage": "The 'ObjectContent`1' type failed to serialize the response body for content type 'application/json; charset=utf-8'.", 
    "ExceptionType": "System.InvalidOperationException", 
    "StackTrace": null, 
    "InnerException": { 
    "Message": "An error has occurred.", 
    "ExceptionMessage": "Unable to translate Unicode character \\uD83C 
    at index 411 to specified code page." 

Das ist mein post-Methode

public JToken Post([FromBody]Classes.Search search) 
    { 

     Classes.ReturnSearch returnSearch = new Classes.ReturnSearch(); 
     try 
     { 
      string con = System.Configuration.ConfigurationManager.ConnectionStrings["TConnectionString"].ConnectionString; 
      SqlConnection cn = new SqlConnection(con); 
      SqlDataAdapter sqlDataAdapter = new SqlDataAdapter("SP_Searchi", cn); 
      sqlDataAdapter.SelectCommand.CommandType = CommandType.StoredProcedure; 
      sqlDataAdapter.SelectCommand.Parameters.Add(new SqlParameter("@word", search.word)); 

      sqlDataAdapter.SelectCommand.Parameters.Add(new SqlParameter("@num", search.num)); 
      DataSet d = new DataSet(); 
      sqlDataAdapter.Fill(d); 
      DataTable table = d.Tables[0]; 

      foreach(DataRow row in table.Rows) 
      { 
       string result=row[1].ToString(); 

       returnSearch.search_items.Add(new Classes.SearchItem(row[0].ToString(), row[1].ToString(),search.word)); 
      } 
      returnSearch.status = "Success"; 


      return JObject.Parse(JsonConvert.SerializeObject(returnSearch)); 
     } 
     catch (Exception e) 
     { 
      returnSearch.status = "Failed"; 
      returnSearch.search_items = null; 
      ValuesController.Log("Error in Search: "+e.Message); 
      return JObject.Parse(JsonConvert.SerializeObject(returnSearch)); 
     } 


    } 

Was ist Problem ?!

+0

['U + D83C' ist kein gültiges Unicode-Zeichen] (http://www.fileformat.info/info/unicode/char/d83c/index.htm). Wie ist dieses Zeichen in Ihrem zurückgegebenen Objekt überhaupt erschienen? – dbc

+0

Ich ging voran und modifizierte Ihren ursprünglichen Titel * Overlapping Recycling-Ansicht nach der Rotation *, um das Problem mehr zu reflektieren. Fühlen Sie sich frei, um zurück zu ändern, wenn das unerwünscht war. – dbc

Antwort

1

Ihr Problem ist, dass U+D83C is not a valid unicode character, die dennoch irgendwie in einer der Strings in Ihrem returnSearch Objekt gemacht hat. Dann löst das asp.net-mvc-Framework eine Ausnahme aus, die versucht, ein solches Zeichen in utf-8 zu codieren.

Was Sie tun müssen, ist festzustellen, wie dieser Charakter in Ihre returnSearch Ergebnisse gelangt und dieses zugrunde liegende Problem zu beheben. Da Sie bereits Ihre zurückgegebenen Ergebnisse zu einem JObject manuell konvertieren, um das Debugging zu erleichtern können Sie testen, codieren alle Saiten auf utf-8 und eine Ausnahme auslösen, wenn es ein Problem ist, mit dem folgenden Konverter:

public class EncodingValidatingStringConverter : JsonConverter 
{ 
    readonly Encoding encoding; 

    public EncodingValidatingStringConverter() 
     : this(Encoding.GetEncoding(Encoding.UTF8.CodePage, new EncoderReplacementFallback("?"), new DecoderExceptionFallback())) 
    { 
    } 

    public EncodingValidatingStringConverter(Encoding encoding) 
    { 
     if (encoding == null) 
      throw new ArgumentNullException(); 
     this.encoding = encoding; 
    } 

    public override bool CanConvert(Type objectType) 
    { 
     return objectType == typeof(string); 
    } 

    public override bool CanRead { get { return false; } } 

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) 
    { 
     throw new NotImplementedException(); 
    } 

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) 
    { 
     var s = (string)value; 
     var bytes = encoding.GetBytes(s); 
     var sFixed = encoding.GetString(bytes); 

     writer.WriteValue(sFixed); 
    } 
} 

Dann ändern Sie Ihre Post() Methode, um eine EncoderFallbackException zu fangen und zu protokollieren und das Problem zu behandeln, wie es ratsam erscheint. Zum Beispiel ersetzt die folgende Version der Methode ungültige Zeichen mit einem ? Zeichen nach der Protokollierung:

 try 
     { 
      // Fill in the returnSearch 

      // Convert to JObject and return 
      var settings = new JsonSerializerSettings 
      { 
       Converters = new[] { new EncodingValidatingStringConverter(Encoding.GetEncoding(Encoding.UTF8.CodePage, new EncoderExceptionFallback(), new DecoderExceptionFallback())) }, 
      }; 
      return JObject.FromObject(returnSearch, JsonSerializer.CreateDefault(settings)); 
     } 
     catch (EncoderFallbackException ex) 
     { 
      // Log the encoding error for debugging: 
      ValuesController.Log("Encoding exception:\n" + ex.ToString()); 
      // You could log the search parameters or entire search_items list as well if desired. 

      // Return whatever seems most advisable, e.g. replacing the bad character with a fallback if preferred. 
      var settings = new JsonSerializerSettings 
      { 
       Converters = new[] { new EncodingValidatingStringConverter(Encoding.GetEncoding(Encoding.UTF8.CodePage, new EncoderReplacementFallback("?"), new DecoderExceptionFallback())) }, 
      }; 
      return JObject.FromObject(returnSearch, JsonSerializer.CreateDefault(settings)); 
     } 
     catch (Exception ex) 
     { 
      returnSearch.status = "Failed"; 
      returnSearch.search_items = null; 
      ValuesController.Log("Error in Search: " + ex.Message); 
      var settings = new JsonSerializerSettings 
      { 
       Converters = new[] { new EncodingValidatingStringConverter(Encoding.GetEncoding(Encoding.UTF8.CodePage, new EncoderReplacementFallback("?"), new DecoderExceptionFallback())) }, 
      }; 
      return JObject.FromObject(returnSearch, JsonSerializer.CreateDefault(settings)); 
     } 

Beachten Sie, dass Test-kodierenden jede Saite wird negativ Auswirkungen auf die Leistung haben, so dass, sobald Sie das zugrunde liegende Problem behoben haben Sie entfernen sollten diese Problemumgehung.

Übrigens, anstatt JObject.Parse(JsonConvert.SerializeObject(returnSearch)) können Sie JObject.FromObject(returnSearch) tun. Diese Methode schreibt direkt in eine JToken Hierarchie ohne die dazwischenliegende Zeichenfolgendarstellung und sollte daher eine bessere Leistung haben.

2

Dies ist ein Emoji Modifier. Sie sehen es wahrscheinlich nach dem Parsen eines eingegebenen Emoji (das in mehrere Instanzen aufgeteilt werden kann).