HeyGuys
我正在开发一个WebApi项目,该项目接收来自客户端的请求,并将这些请求重定向到其他未开放供直接访问的服务。
默认情况下,.Net自动序列化和反序列化Json请求参数,因此我需要在调用适当的服务之前重新序列化它们。收到服务响应时会出现同样的问题。我需要在将响应发送给用户之前对其进行反序列化;否则.Net框架会再次序列化它,导致Json" 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" Json of Json"当我接受第二个服务答案并返回给用户时出现问题。
我基本上不知道我能做些什么来克服这个问题,所以欢迎任何解决方法。
答案 0 :(得分:0)
如果您只是需要重定向请求而不进行修改,您可以直接从输入流中读取它并将其发送到内部服务。您也可以使用这种方法从内部服务中读取响应。
//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;
}
}
}