OData服務通常是強類型的,因此您必須竭盡全力克服Web API內置的從JSON到CLR類型的映射。
首先,定義一個讀取JTokens的新媒體類型格式程序。請注意正在使用的自定義媒體類型。
public class RawJsonMediaTypeFormatter : MediaTypeFormatter
{
private static readonly MediaTypeHeaderValue _customMediaType =
MediaTypeHeaderValue.Parse("application/prs.adrianm+json");
public RawJsonMediaTypeFormatter() : base()
{
this.Intialize();
}
protected RawJsonMediaTypeFormatter(MediaTypeFormatter formatter) : base(formatter)
{
this.Intialize();
}
protected void Intialize()
{
this.SupportedMediaTypes.Add(_customMediaType);
}
public override MediaTypeFormatter GetPerRequestFormatterInstance(Type type, HttpRequestMessage request, MediaTypeHeaderValue mediaType)
{
if (type == typeof(JToken) && mediaType.MediaType == _customMediaType.MediaType)
{
return this;
}
return base.GetPerRequestFormatterInstance(type, request, mediaType);
}
public override bool CanReadType(Type type)
{
return type == typeof(JToken);
}
public override bool CanWriteType(Type type)
{
return false;
}
public override Task<object> ReadFromStreamAsync(Type type, Stream readStream, HttpContent content, IFormatterLogger formatterLogger)
{
return this.ReadFromStreamAsync(type, readStream, content, formatterLogger, default(CancellationToken));
}
public override Task<object> ReadFromStreamAsync(Type type, Stream readStream, HttpContent content, IFormatterLogger formatterLogger, CancellationToken cancellationToken)
{
object result;
using (var reader = new JsonTextReader(new StreamReader(readStream)))
{
result = JToken.ReadFrom(reader);
}
return Task.FromResult(result);
}
}
隨着Web API註冊的一部分,自定義格式的一個實例添加到HttpConfiguration並宣佈你的OData行動。請注意,動作參數的類型是vanilla object
。
config.Formatters.Clear();
config.Formatters.AddRange(ODataMediaTypeFormatters.Create());
config.Formatters.Add(new RawJsonMediaTypeFormatter());
var builder = new ODataConventionModelBuilder();
var arbitraryJsonAction = builder.Action("ArbitraryJson");
arbitraryJsonAction.Parameter<object>("json");
arbitraryJsonAction.Returns<string>();
爲操作添加控制器方法。
[HttpPost]
[ODataRoute("ArbitraryJson")]
public IHttpActionResult ArbitraryJson(JToken json)
{
return this.Ok(json.ToString());
}
在客戶端,記得設置Content-Type
通過自定義格式處理的自定義介質類型:
POST http://host/ArbitraryJson
Content-Type: application/prs.adrianm+json
[1, 2, {"foo": true }]
響應有效載荷看起來應該像下面這樣:
{
"@odata.context": "http://host/$metadata#Edm.String",
"value": "[\r\n 1,\r\n 2,\r\n {\r\n \"foo\": true\r\n }\r\n]"
}
非常很好的答案。希望我能爲你的努力做更多努力。對於不同的內容類型的需求可能是一種破壞我的情況,但我明確地從你的帖子中學到了很多東西。謝謝。 – adrianm
你可以嘗試使用帶有額外參數的'application/json'。例如,'application/json; format = raw'。 – lencharest