[英]ReadAsAsync calling a WebAPI not reconstituting json to class
[英]WebApi Formatter that is using ReadAsAsync and WriteToStreamAsync - Json gets truncated while xml works fine
我正在使用C#
和WebAPI 2
並出現奇怪的行為。
我有調用Controller的服務,有時可以作為Json發送內容,而作為用於進行調用的XML機制可以發送其他內容,如下所示:
using (var client = new HttpClient())
{
var pricingControllerUrl = CreateEndpoint(apiUrl);
using (var response = (int)request.Metadata.InputType >= 3 ? client.PostAsJsonAsync(pricingControllerUrl, request) : client.PostAsXmlWithSerializerAsync(pricingControllerUrl, request))
{
if (response.Result.IsSuccessStatusCode)
{
var session = response.Result.Content.ReadAsAsync<Session>(new List<MediaTypeFormatter>() { new XmlMediaTypeFormatter { UseXmlSerializer = true }, new JsonMediaTypeFormatter() }).Result;
return session;
}
}
}
public static class HttpExtensions
{
public static Task<HttpResponseMessage> PostAsXmlWithSerializerAsync<T>(this HttpClient client, string requestUri, T value)
{
return client.PostAsync(new Uri(requestUri), value,
new XmlMediaTypeFormatter { UseXmlSerializer = true }
);
}
}
在接收端(控制器),
public async Task<IHttpActionResult> PostSession([FromBody] Session session)
{
//do the calculations
return Content(HttpStatusCode.OK, sessionResponse, new ReducedSessionFormatter(), this.Request.Content.Headers.ContentType);
}
必須通過在發送信息之前刪除一些信息來減少響應,以下格式化程序可簡化此操作:
public class ReducedSessionFormatter : MediaTypeFormatter
{
public ReducedSessionFormatter()
{
SupportedMediaTypes.Add(new MediaTypeHeaderValue("text/json"));
SupportedMediaTypes.Add(new MediaTypeHeaderValue("text/xml"));
SupportedMediaTypes.Add(new MediaTypeHeaderValue("application/xml"));
}
public ReducedSessionFormatter(MediaTypeFormatter formatter) : base(formatter)
{
}
public override bool CanReadType(Type type)
{
return false;
}
public override bool CanWriteType(Type type)
{
return type.IsAssignableFrom(typeof (Session));
}
protected XDocument ReduceXml(XDocument doc)
{
//removing stuff from xml
return doc;
}
protected JObject ReduceJson(JObject serializedJson)
{
//removing stuff from json
return serializedJson;
}
public override Task WriteToStreamAsync(Type type, object value, Stream writeStream, HttpContent content, TransportContext transportContext)
{
if (content.Headers.ContentType.MediaType.Contains("xml"))
{
var doc = SerializeToXmlDocument(type, value).ToXDocument();
doc = ReduceXml(doc);
var settings = new XmlWriterSettings {Encoding = new UTF8Encoding(false)};
using (XmlWriter w = XmlWriter.Create(writeStream, settings))
{
doc.Save(w);
}
}
else
{
var json = new JavaScriptSerializer().Serialize(value);
var serializedJson = (JObject)JsonConvert.DeserializeObject(json);
var serializedJsonString = ReduceJson(serializedJson).ToString(Newtonsoft.Json.Formatting.None);
var writer = new StreamWriter(writeStream);
writer.Write(serializedJsonString);
}
var tcs = new TaskCompletionSource<object>();
tcs.SetResult(null);
return tcs.Task;
}
public XmlDocument SerializeToXmlDocument(Type type, object value)
{
var serializer = new XmlSerializer(type);
XmlDocument xmlDocument = null;
using (var memoryStream = new MemoryStream())
{
serializer.Serialize(memoryStream, value);
memoryStream.Position = 0;
using (var xtr = XmlReader.Create(memoryStream, new XmlReaderSettings {IgnoreWhitespace = true}))
{
xmlDocument = new XmlDocument();
xmlDocument.Load(xtr);
}
}
return xmlDocument;
}
}
public static class XmlExtensions
{
public static XDocument ToXDocument(this XmlDocument xmlDocument)
{
using (var nodeReader = new XmlNodeReader(xmlDocument))
{
nodeReader.MoveToContent();
return XDocument.Load(nodeReader);
}
}
}
public static class JsonExtensions
{
public static bool IsNullOrEmpty(this JToken token)
{
return (token == null) ||
(token.Type == JTokenType.Array && !token.HasValues) ||
(token.Type == JTokenType.Object && !token.HasValues) ||
(token.Type == JTokenType.String && token.ToString() == String.Empty) ||
(token.Type == JTokenType.Null);
}
}
當在格式化程序中聚合時,xml和json均有效且良好,如果在不使用格式化程序的情況下將數據發送回,則一切正常
奇怪的東西:當我使用格式化程序並發回Json時,它會被截斷,而與長度無關。 即使是非常小的對象(長度小於10k的對象)也總是在同一位置處被切斷,但對於不同的對象卻以不同的長度被切斷,並且僅適用於json,對於xml來說也可以正常工作...
如果json沒有像這樣被toStringed,它也會失敗:
var writer = new StreamWriter(writeStream);
writer.Write(ReduceJson(serializedJson));
我添加了最小的解決方案來顯示問題
這里發生了什么? 為什么使用格式化程序截斷Json的響應內容而不截斷XML?
好的,我發現了問題所在是Task .Result的使用。 在
var session = response.Result.Content.ReadAsAsync<Session>(new List<MediaTypeFormatter>() { new XmlMediaTypeFormatter { UseXmlSerializer = true }, new JsonMediaTypeFormatter() }).Result;
(以及問題中未列出的其他一些機制)應await
。
一旦將.Result
替換為await
並將鏈中的所有方法標記為async
-我開始獲得完整的響應。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.