5

在 Web API 方面,我有一个这样的客户类

public class CustomerAPI
{  
    public string CustomerName { get; set; }
    public string CustomerCity { get; set; }
}

在 MVC 方面,我有一个这样的客户类

public class CustomerMVC
{
    public string CustomerName { get; set; }
    public string CustomerCity{ get; set; }
}

我在 ASP.Net MVC4 中使用 Web API 服务,如下所示:

 var task = client.GetAsync("api/values")
                  .ContinueWith((taskwithresponse) =>
                    {
                        var response = taskwithresponse.Result;
                        var readtask = response.Content.ReadAsAsync<IEnumerable<CustomerMVC>>();

                        readtask.Wait();
                        serviceList = readtask.Result.ToList();
                    });
 task.Wait();  

我在执行此操作时遇到了聚合异常,如何转换CustomerWebAPICustomerMVC.

4

2 回答 2

5

将代码拆分一下可能会有所帮助。我还建议使用Newtonsoft.Json nuget 包进行序列化。

var task = client.GetAsync("api/values").Result;
//get results as a string
var result = task.Content.ReadAsStringAsync().Result;
//serialize to an object using Newtonsoft.Json nuget package
var customer = JsonConvert.DeserializeObject<CustomerMVC>(result);

如果你想让它异步,你可以在 C#5 中使用async 和 await关键字:

public async Task<CustomerMVC> GetCustomer()
{
    //return control to caller until GetAsync has completed
    var task = await client.GetAsync("api/values");
    //return control to caller until ReadAsStringAsync has completed
    var result = await task.Content.ReadAsStringAsync()
    return JsonConvert.DeserializeObject<CustomerMVC>(result);
}
于 2013-11-06T16:49:16.143 回答
1

反序列化解决方案在这里感觉有点像 hack。除非您遗漏了某些内容,否则您可能会遇到UnsupportedMediaTypeException显示为 an 的情况,AggregateException因为这就是未捕获Task的异常如何抬起丑陋的头脑。

反序列化可能是一项昂贵的操作,使用此解决方案,您最终将在每次反序列化对象时完全命中。由于最近对扩展的性能改进,使用response.Content.ReadAsAsync<IEnumerable<CustomerWebAPI>>()效率会更高:http: //blogs.msdn.com/b/webdev/archive/2015/02/09/asp-net-mvc-5-2-3- web-pages-3-2-3-and-web-api-5-2-3-release.aspxReadAsAsync

至于从 CustomerWebAPI 到 CustomerMVC 的转换,您可以轻松添加一个静态便捷方法,如下所示:

public static CustomerMVC FromCustomerWebAPI(CustomerWebAPI customer){
    return new CustomerMVC(){
        CustomerName = customer.CustomerName,
        CustomerCity = customer.CustomerCity
    }
}

这是额外的代码,但最终应该会更有效率。如果客户对象是一个相当大的对象,您始终可以使用 AutoMapper 或 ValueInjecter 之类的工具,或者您可以通过缓存 get(您要映射的类型)和 set 访问器(您要映射到的类型)来推出自己的解决方案) 所以你只需要产生一次反射的成本——你可以通过编译一个表达式来做到这一点——这是一个关于如何为Set访问器做到这一点的例子:

public static Action<object, object> BuildSetAccessor( MethodInfo method )
{
    var obj = Expression.Parameter(typeof(object), "o");
    var value = Expression.Parameter(typeof(object));

    Expression<Action<object, object>> expr =
        Expression.Lambda<Action<object, object>>(
               Expression.Call(
                      Expression.Convert( obj, method.DeclaringType )
                    , method
                    , Expression.Convert( value, method.GetParameters()[0].ParameterType )
            ), obj
              , value );

    return expr.Compile();
}
于 2015-02-10T19:34:23.610 回答