有几种可能的想法你可以尝试解决这个问题,主要原因是 EntityFramework(或你的 ORM)与序列化冲突。
顺便说一句,如果您提供代码,请尝试提供可编译并有意义的代码。由于缺少代码,我无法重现您的问题。如果您可以包含所有代码(甚至是 Visual Studio 项目),我会尝试解决您的问题,而不是基于完全不同的上下文演示解决方案。
在我看来,您不应该从 API 返回 ORM 对象。而是返回 DataTransferObjects。您从序列化对象中删除实体框架,这样错误可能会消失。
使用 RestSharp 进行 REST API 调用
-
您可以做的是使用以下属性标记您的 Product 实体
[DataContract(IsReference=false)]
尝试使用 JSON.NET 吗?
http://json.codeplex.com/ 我会使用 JSON.NET 和 DTO 来实现这一点。
但我不明白的是你想要达到的目标。为什么不简单地对您的 API 进行客户端调用,在这种情况下,我看不到服务器端 API 调用的好处。除非您的 WebApi 托管在不同的环境中,否则从服务器端调用它在任何情况下都没有意义。您的 MVC 项目似乎也引用了您的 ORM 对象层,这又有点奇怪(或者 Product 类不是映射到您的数据库的对象?)
如果它们在同一台服务器上,以这种方式使用 WebApi 没有任何好处,而是创建一个层来提供您需要的信息,并将其包含在您的 Api 和 Controller 中,这样您的控制器就不需要使用API,它可以直接调用其他层。它还删除了服务器端 JSON 反序列化。
我还注意到您的 API 返回“城市”,而您正在将它们转换为产品,这听起来不是很奇怪吗?
编辑:工作示例:
我创建了一个适合我的小型应用程序。示例可在以下网址下载:https://dl.dropboxusercontent.com/u/87239305/WebApi.Example.zip
我使用 restSharp 在 .NET 中为 DTO 和 EF 相关对象创建 Api 调用。
非 DTO 示例:
ApiController 看起来像这样:
public interface IApiExampleController
{
IEnumerable<User> GetAllUsers();
}
public class ApiExampleController : ApiController, IApiExampleController
{
private readonly IEFContext _context;
public ApiExampleController()
{
_context = new EFContext();
}
public IEnumerable<User> GetAllUsers()
{
return _context.Users.ToList();
}
}
调用 API 的 MVC 控制器如下所示:
public ActionResult Index()
{
var users = GetApiUsers();
return View(users);
}
private IList<User> GetApiUsers()
{
const string apiBaseUrl = "http://localhost:52812/Api/";
const string apiSuffix = "ApiExample/GetAllUsers";
var client = new RestClient(apiBaseUrl);
var request = new RestRequest(apiSuffix, Method.GET);
var response = (RestResponse<List<User>>)client.Execute<List<User>>(request);
return response.Data;
}
DTO 示例:
API 控制器:
public interface IApiDTOExampleController
{
IEnumerable<UserDTO> GetAllUsers();
}
public class ApiDTOExampleController : ApiController, IApiDTOExampleController
{
private readonly IEFContext _context;
public ApiDTOExampleController()
{
_context = new EFContext();
}
public IEnumerable<UserDTO> GetAllUsers()
{
return _context.Users.Select(x => new UserDTO { Id = x.Id, Name = x.Name }).ToList();
}
}
调用该API的代码如下:
public ActionResult IndexDTO()
{
var dtoUsers = GetApiDTOUsers();
return View(dtoUsers);
}
private IList<UserDTO> GetApiDTOUsers()
{
const string apiBaseUrl = "http://localhost:52812/Api/";
const string apiSuffix = "ApiDTOExample/GetAllUsers";
var client = new RestClient(apiBaseUrl);
var request = new RestRequest(apiSuffix, Method.GET);
var response = (RestResponse<List<UserDTO>>)client.Execute<List<UserDTO>>(request);
return response.Data;
}
如您所见,DTO 和 EF 实现之间没有太大区别...不过,使用 DTO 可以让您控制调用方需要哪些数据。
两者都可以正常工作(在我的情况下),因此根据您的产品或城市对象,可能不需要实施 DTO 来消除错误(但我建议您这样做)。