Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/csharp-4.0/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 将Web API调用的结果存储到泛型类型类中_C#_C# 4.0_Asp.net Web Api - Fatal编程技术网

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”类型声明负载,你会在其中存储任何东西。但是,您将很难将其拆开以便以后使用。如果我是你,我会将有效负载设置为列表。然后,我将使服务始终返回一个列表对象,即使只填充了一个索引。