HeyGuys
我正在处理一个WebApi项目,该项目接收来自客户端的请求,并将这些请求重定向到其他不能直接访问的服务。
默认情况下,.Net会自动序列化和反序列化Json请求参数,因此我需要在调用适当的服务之前重新序列化它们。在接收服务响应时也会出现同样的问题。在将响应发送给用户之前,我需要对其进行反序列化;否则.Net框架将再次对其进行序列化,从而产生"Json of Json“响应。
我发现了this answer,但它似乎不适用于.NetCore;所以我尝试创建自己的ModelBinder,它只读取Json对象并返回它。
class JsonUnformatterBinderProvider : Microsoft.AspNetCore.Mvc.ModelBinding.IModelBinderProvider
{
public IModelBinder GetBinder(ModelBinderProviderContext context)
{
return new JsonUnformatterBinder(new SimpleTypeModelBinder(context.Metadata.ModelType));
}
}和
class JsonUnformatterBinder : IModelBinder
{
private readonly IModelBinder _fallbackBinder;
public JsonUnformatterBinder(IModelBinder fallbackBinder)
{
_fallbackBinder = fallbackBinder;
}
public Task BindModelAsync(ModelBindingContext bindingContext)
{
string currMethod = bindingContext.ActionContext.HttpContext.Request.Method;
if ("POST".Equals(currMethod) || "PUT".Equals(currMethod))
{
string strData = new StreamReader(bindingContext.ActionContext.HttpContext.Request.Body).ReadToEnd();
bindingContext.Result = ModelBindingResult.Success(strData);
return Task.CompletedTask;
}
return _fallbackBinder.BindModelAsync(bindingContext);
}
}这段代码非常简单,这是我第一次尝试,它对我的目的很有效。然而,当我接受第二个服务答案并返回给用户时,我仍然遇到了"Json of Json“问题。
我基本上不知道我能做些什么来克服这个问题,所以这里欢迎任何变通方法。
发布于 2017-07-15 02:05:22
如果您只需要不加修改地重定向请求,您可以直接从输入流中读取它,并将其发送到内部服务。您也可以使用这种方法从内部服务读取响应。
//1. Set empty parameter list in action then neither serializator nor model binder are not invoked.
public async Task<ContentResult> ProxyAction(/*empty parameter list*/)
{
var newUrl = @"https://stackoverflow.com";
var data = this.Request.Body;
using (var client = new HttpClient())
{
//2. Read request body from input stream.
var reader = new StreamReader(data);
var json = reader.ReadToEnd();
using (var content = new StringContent(json))
{
//3. Set correct content type
content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue(this.Request.ContentType);
//4. Post request to inner service
var response = await client.PostAsync(newUrl, content);
//5. Read response without deserialization
var innerResponse = await response.Content.ReadAsStringAsync();
var contentType = response.Content.Headers.ContentType.ToString();
var statusCode = response.StatusCode;
//6. Return inner response without serialization
var outerResponse = this.Content(innerResponse, contentType);
outerResponse.StatusCode = (int)statusCode;
return outerResponse;
}
}
}https://stackoverflow.com/questions/45059853
复制相似问题