C# 将Web API调用的结果存储到泛型类型类中
我有一个简单的模型类,定义如下:C# 将Web API调用的结果存储到泛型类型类中,c#,c#-4.0,asp.net-web-api,C#,C# 4.0,Asp.net Web Api,我有一个简单的模型类,定义如下: public class CountryLanguage { public string Name { get; set; } public string ShortName { get; set; } public string Description { get; set; } } 我有一个Web API,它返回CountryLanguage的IEnumerable: [HttpGet] public IEnumerable<
public class CountryLanguage
{
public string Name { get; set; }
public string ShortName { get; set; }
public string Description { get; set; }
}
我有一个Web API,它返回CountryLanguage的IEnumerable:
[HttpGet]
public IEnumerable<CountryLanguage> Get()
{
List<CountryLanguage> list = new List<CountryLanguage>();
list.Add(new CountryLanguage());
list.Add(new CountryLanguage());
return list;
}
[HttpGet]
公共IEnumerable Get()
{
列表=新列表();
添加(新的CountryLanguage());
添加(新的CountryLanguage());
退货清单;
}
我想在这个类中存储Web API调用的结果:
public class ResponseResult<T>
{
public HttpStatusCode StatusCode { get; set; }
public string Message { get; set; }
public T Payload { get; set; }
}
公共类响应结果
{
公共HttpStatusCode状态码{get;set;}
公共字符串消息{get;set;}
公共T有效载荷{get;set;}
}
最后,下面是调用Web API的代码:
HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, actionToCallWithParameters);
var response = httpClient.SendAsync(request).Result;
ResponseResult<T> responseResult = new ResponseResult<T>();
responseResult.StatusCode = response.StatusCode;
responseResult.Message = response.Content.ReadAsStringAsync().Result;
responseResult.Payload = response.Content.ReadAsAsync<T>().Result;
return responseResult;
HttpRequestMessage请求=新的HttpRequestMessage(HttpMethod.Get,actionToCallWithParameters);
var response=httpClient.SendAsync(请求).Result;
ResponseResult ResponseResult=新ResponseResult();
responseResult.StatusCode=response.StatusCode;
responseResult.Message=response.Content.ReadAsStringAsync().Result;
responseResult.Payload=response.Content.ReadAsAsync().Result;
返回响应结果;
如果web API返回CountryLanguage对象,那么将该对象存储到泛型类型属性有效负载中就没有问题
但如果Web API返回IEnumerable,则会出现以下错误:
无法将当前JSON数组(例如[1,2,3])反序列化为类型“CountryLanguage”,因为该类型需要JSON对象(例如{“name\”:“value\”})才能正确反序列化。若要修复此错误,请将JSON更改为JSON对象(例如{“name\”:“value\”}),或将反序列化类型更改为数组或实现可从JSON数组反序列化的类似集合接口(例如ICollection、IList)的列表的类型。还可以将JsonArrayAttribute添加到类型中,以强制它从JSON数组反序列化
我的问题是:是否可以“规范化”此代码,以便将对象或IEnumerable存储到我的T类型有效负载属性中?实际上,您的逻辑不正确。如果在运行时您的T类型充当“CountryLanguage”类型,则您的有效负载属性充当CountryLanguage属性。这就是为什么当您尝试将IEnumerable值分配给属性时会抛出错误,因为您将IEnumerable对象分配给不可枚举的属性
基本上,在运行时,系统会执行以下操作:
CountryLanguage Payload = IEnumerable<CountryLanguage>(variable);
CountryLanguage有效负载=IEnumerable(变量);
它显然会抛出错误。好的,可以将IEnumerable存储到泛型类型T的变量中 如果我希望返回的数据是一个对象,那么我需要进行的调用是:
ResponseResult<CountryLanguage> response = serviceConnector.GetData <CountryLanguage>(actionToCall);
ResponseResult response=serviceConnector.GetData(actionToCall);
如果我希望从调用中获得IEnumerable:
ResponseResult<IEnumerable<CountryLanguage>> response =
serviceConnector.GetData<IEnumerable<CountryLanguage>>(actionToCall);
ResponseResult响应=
serviceConnector.GetData(actionToCall);
因此,我的错误是调用代码时没有指定IEnumerable类型。通过这一更改,我能够解决问题,但我认为这并不能完全回答您的问题。下面我将为您的答案提供一个解决方案,但这里是我添加的用于修复运行时问题的内容,它将返回您的列表
var responseResult = new ResponseResult<IEnumerable<CountryLanguage>>
{
StatusCode = response.StatusCode,
Message = response.Content.ReadAsStringAsync().Result,
Payload = response.Content.ReadAsAsync<IEnumerable<CountryLanguage>>().Result
};
var responseResult=新responseResult
{
StatusCode=response.StatusCode,
Message=response.Content.ReadAsStringAsync().Result,
有效负载=response.Content.ReadAsAsync().Result
};
基本上只需将T转换为IEnumerable,如果T在类或方法中定义为CountryLanguage,则可以将其设置为IEnumerable,但代码不会显示完整的类或方法
现在转到另一个问题,从一个泛型方法返回对象或对象列表。第一个响应是正确的,您只需要返回object和box/unbox,并使用反射和其他非常不愉快的代码,这些代码可以被封装,但仍然有点恶心。因此,如果您的目标是将返回的有效负载用于除CountryLanguage之外的其他用途,您可以尝试以下方法。创建一个名为PayloadWrapper的新类,该类包含以下两个属性:
public class PayloadWrapper<T>
{
public T Item { get; set; }
public IEnumerable<T> Items { get; set; }
}
公共类PayloadWrapper
{
公共T项{get;set;}
公共IEnumerable项{get;set;}
}
然后,您可以在webapi中设置on或其他选项,并在客户端检查已设置的选项
public PayloadWrapper<CountryLanguage> Get()
{
var languages = new List<CountryLanguage> {new CountryLanguage(), new CountryLanguage()};
var payload = new PayloadWrapper<CountryLanguage>();
payload.Items = languages;
payload.Item = null;
return payload;
}
public PayloadWrapper Get()
{
var languages=新列表{new CountryLanguage(),new CountryLanguage()};
var payload=新的PayloadWrapper();
有效载荷.项目=语言;
有效载荷.Item=null;
返回有效载荷;
}
关于客户:
var request = new HttpRequestMessage(HttpMethod.Get, "http://localhost:34213/api/values/");
var httpClient = new HttpClient();
var response = httpClient.SendAsync(request).Result;
var responseResult = new ResponseResult<PayloadWrapper<CountryLanguage>>
{
StatusCode = response.StatusCode,
Message = response.Content.ReadAsStringAsync().Result,
Payload = response.Content.ReadAsAsync<PayloadWrapper<CountryLanguage>>().Result
};
var request=newhttprequestmessage(HttpMethod.Get)http://localhost:34213/api/values/");
var httpClient=新的httpClient();
var response=httpClient.SendAsync(请求).Result;
var responseResult=新responseResult
{
StatusCode=response.StatusCode,
Message=response.Content.ReadAsStringAsync().Result,
有效负载=response.Content.ReadAsAsync().Result
};
您的负载现在是一个包含一个项目或同一项目列表的单个对象。可以用于发回符合此模式的任何内容。是的,您是对的。但是你能想出什么方法把一个对象或IEnumerable的结果存储到一个泛型类型类变量中吗?是的,如果你用“object”类型声明负载,你会在其中存储任何东西。但是,您将很难将其拆开以便以后使用。如果我是你,我会将有效负载设置为列表。然后,我将使服务始终返回一个列表对象,即使只填充了一个索引。