ASP NET Boilerplate > 使用 swagger codegen 工具 (nswag) 生成 C# swagger 客户端不工作
ASP NET Boilerplate > Generating C# swagger client using swagger codegen tool (nswag) not working
我尝试为使用 ASP Net Boilerplate 创建的 API 生成 C# 代码,但响应未正确反序列化。
经调查,似乎 json 响应是使用名为 "AjaxResponse" 的 class 包装的;但是,swagger.json 不在方法响应中包含此类型。
有谁知道如何构建一个解释包装结果的 C# Swagger 客户端?
Aspnet Boilerplate 将真实结果包装在 AjaxResponse 中。 class AjaxResponse 是泛型类型 class。 Swaggergen 工具无法生成正确的代理 classes,因为包装结果发生在运行时。
因此,Swagger 抓取的 api 的签名是原始结果(未包装)。
所以唯一的解决方案是在解决方案范围内禁用自动包装器。将这两行添加到 Web.Core 项目中的 PreInitialize() 方法。你的问题就迎刃而解了。
Configuration.Modules.AbpAspNetCore().DefaultWrapResultAttribute.WrapOnError = false;
Configuration.Modules.AbpAspNetCore().DefaultWrapResultAttribute.WrapOnSuccess = false;
您还可以将 [DontWrapResult]/[WrapResult] 属性用于各个应用程序方法。
[WrapResult(LogError =false, WrapOnSuccess = true, WrapOnError = true)]
SomeApplicationServiceMethod()
[DontWrapResult(LogError =false, WrapOnError=false ,WrapOnSuccess=false)]
SomeApplicationServiceMethod()
如果您不能这样做,那么您可以在客户端进行相同的更改:
添加下一个class:
public class RequestResultAJAX<T>
{
public bool success { get; set; }
public T result { get; set; }
public string error { get; set; }
public string targetUrl { get; set; }
public string unAuthorizedRequest { get; set; }
public string __abp { get; set; }
}
替换生成的客户端方法中的所有反序列化点:
result_ = Newtonsoft.Json.JsonConvert.DeserializeObject<Dto>(responseData_, _settings.Value);
来自
result_ = Newtonsoft.Json.JsonConvert.DeserializeObject<RequestResultAJAX<Dto>>(responseData_, _settings.Value).result;
并在 return 结果前添加 success/error 个检查。
我通过创建自定义 JsonConverter(并告诉 nswag 在生成我的客户端时使用它)解决了这个问题。
转换器看起来像这样:
public class AjaxWrapperConverter : JsonConverter
{
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
throw new NotImplementedException();
}
public override bool CanWrite => false;
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
// Read about this problem here:
//
var token = JToken.Load(reader);
var tokenResult = token.First.First;
var result = tokenResult.ToObject(objectType);
return result;
}
public override bool CanConvert(Type objectType)
{
return objectType == typeof(TypeIWantToUnwrap) || objectType == typeof(TypeIWantToUnwrap2);
}
}
我尝试为使用 ASP Net Boilerplate 创建的 API 生成 C# 代码,但响应未正确反序列化。
经调查,似乎 json 响应是使用名为 "AjaxResponse" 的 class 包装的;但是,swagger.json 不在方法响应中包含此类型。
有谁知道如何构建一个解释包装结果的 C# Swagger 客户端?
Aspnet Boilerplate 将真实结果包装在 AjaxResponse 中。 class AjaxResponse 是泛型类型 class。 Swaggergen 工具无法生成正确的代理 classes,因为包装结果发生在运行时。 因此,Swagger 抓取的 api 的签名是原始结果(未包装)。
所以唯一的解决方案是在解决方案范围内禁用自动包装器。将这两行添加到 Web.Core 项目中的 PreInitialize() 方法。你的问题就迎刃而解了。
Configuration.Modules.AbpAspNetCore().DefaultWrapResultAttribute.WrapOnError = false;
Configuration.Modules.AbpAspNetCore().DefaultWrapResultAttribute.WrapOnSuccess = false;
您还可以将 [DontWrapResult]/[WrapResult] 属性用于各个应用程序方法。
[WrapResult(LogError =false, WrapOnSuccess = true, WrapOnError = true)]
SomeApplicationServiceMethod()
[DontWrapResult(LogError =false, WrapOnError=false ,WrapOnSuccess=false)]
SomeApplicationServiceMethod()
如果您不能这样做,那么您可以在客户端进行相同的更改:
添加下一个class:
public class RequestResultAJAX<T>
{
public bool success { get; set; }
public T result { get; set; }
public string error { get; set; }
public string targetUrl { get; set; }
public string unAuthorizedRequest { get; set; }
public string __abp { get; set; }
}
替换生成的客户端方法中的所有反序列化点:
result_ = Newtonsoft.Json.JsonConvert.DeserializeObject<Dto>(responseData_, _settings.Value);
来自
result_ = Newtonsoft.Json.JsonConvert.DeserializeObject<RequestResultAJAX<Dto>>(responseData_, _settings.Value).result;
并在 return 结果前添加 success/error 个检查。
我通过创建自定义 JsonConverter(并告诉 nswag 在生成我的客户端时使用它)解决了这个问题。
转换器看起来像这样:
public class AjaxWrapperConverter : JsonConverter
{
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
throw new NotImplementedException();
}
public override bool CanWrite => false;
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
// Read about this problem here:
//
var token = JToken.Load(reader);
var tokenResult = token.First.First;
var result = tokenResult.ToObject(objectType);
return result;
}
public override bool CanConvert(Type objectType)
{
return objectType == typeof(TypeIWantToUnwrap) || objectType == typeof(TypeIWantToUnwrap2);
}
}