我在MVC项目中开发了一个web api。我在post方法中返回一个JToken对象。通常我的api工作正常但有时在特定数据中我得到这个错误:
"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."
这是我的帖子方法
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));
}
}
有什么问题?!
答案 0 :(得分:2)
这是表情符号修饰符。您可能在解析输入的表情符号后可能会看到它(可以将其拆分为多个\ u ####实例)。
答案 1 :(得分:1)
你的问题是U+D83C
is not a valid unicode character以某种方式进入returnSearch
对象中的一个字符串。然后,asp.net-mvc框架抛出异常,试图将这样的字符编码为utf-8。
您需要做的是确定此角色如何进入returnSearch
结果并解决潜在问题。由于您已经手动将返回的结果转换为JObject
,为了使调试更容易,您可以将所有字符串测试编码为utf-8,并在出现问题时抛出异常,使用以下转换器: / p>
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);
}
}
然后修改您的Post()
方法以捕获并记录EncoderFallbackException
并处理问题,这似乎是可取的。例如,以下版本的方法在记录后用?
字符替换无效字符:
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));
}
请注意,对每个字符串进行测试编码会产生负面的性能影响,因此一旦修复了基础问题,就应该删除此解决方法。
顺便说一句,您可以JObject.Parse(JsonConvert.SerializeObject(returnSearch))
JToken
而不是function WebUI() {
this.updateLoadingMessage = function (message) {
$("#loading-header").html(message);
};
addAlertInfo = function (message) {
};
addAlertWarning = function (message) {
};
addAlertDanger = function (message) {
};
addAlertSuccess = function (message) {
};
};
。此方法直接写入WebUI.addAlertInfo("testing");
层次结构而没有中间字符串表示,因此应具有更好的性能。