【问题标题】:Web API not workingWeb API 不工作
【发布时间】:2014-05-13 17:09:10
【问题描述】:

我正在尝试使用 Web API 方法,但没有取得多大成功。

在我的控制器中,我有:

public class TestAPIController : ApiController
{
public string Get()
    {
        return "Hello World";
    }

    public Cours Get(int id)
    {
        using (SSDEntities Entity = new SSDEntities())
        return Entity.Courses.SingleOrDefault<Cours>(a => a.ID == id);
    }

在我的 Global.asax 我有:

public static void RegisterGlobalFilters(GlobalFilterCollection filters)
    {
        filters.Add(new HandleErrorAttribute());
    }

    public static void RegisterRoutes(RouteCollection routes)
    {
        routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

        routes.MapHttpRoute(
    name: "DefaultApi",
    routeTemplate: "api/{controller}/{id}",
    defaults: new { id = RouteParameter.Optional }
    );
        routes.MapHttpRoute(
            name: "ApiWithAction",
            routeTemplate: "api/{controller}/{action}/{id}",
            defaults: new { id = RouteParameter.Optional }
        );

        routes.MapRoute(
            "Default", // Route name
            "{controller}/{action}", // URL with parameters
            new { controller = "Home", action = "Index" } // Parameter defaults
        );

    }

    protected void Application_Start()
    {
        AreaRegistration.RegisterAllAreas();

        RegisterGlobalFilters(GlobalFilters.Filters);
        RegisterRoutes(RouteTable.Routes);

    }

问题是,如果我输入 /api/TestAPI 我成功看到“Hello World”,但是 /api/TestAPI/7 给出以下异常消息:“ObjectContent`1”类型无法序列化响应正文内容类型'应用程序/xml; charset=utf-8'。

我有 1 个来自数据库的结果与 id “7”匹配,它应该返回。我不确定我做错了什么。有人可以帮忙吗?

【问题讨论】:

  • 你的问题是你正在返回一个 EF 对象......不要那样做......创建一个模型并映射它。

标签: c# asp.net-web-api


【解决方案1】:

映射到模型。您真的不应该尝试序列化活动的 EF 对象。它失败的原因有很多。正如所指出的,这可能是因为它具有惰性属性,但您也可能在对象中有循环。只需将您需要的内容映射到模型即可。

public CoursModel Get(int id)
{
    using (SSDEntities Entity = new SSDEntities())
    return Entity.Courses.SingleOrDefault<Cours>(a => a.ID == id)
    .Select(x=> new CoursModel()
         { MAP STUFF HERE });
}

【讨论】:

  • 您的回答对我来说并不完全有效,但稍作修改就奏效了:)谢谢。以下代码对我有用,如果您可以更新您的答案以包含它,那就太好了: using (SSDEntities Entity = new SSDEntities()) return new APIModel() { MAP STUFF HERE}
【解决方案2】:

您正在返回一个由实体框架控制的对象...这里至少有两个问题:

  1. 如果实体类有任何 IQueryable&lt;T&gt; / IEnumerable&lt;T&gt; / ICollection&lt;T&gt; 属性是来自 EF 的延迟加载投影,则会导致确切的错误 The 'ObjectContent1' type failed to serialize...。序列化程序无法处理这些。
  2. 如果您越过了这一点,您还将释放数据上下文,因此如果序列化程序尝试解析任何其他延迟加载的属性,它将失败。

在使用 WebAPI 将对象发送出去之前,您希望将其剥离为仅包含您知道需要的属性的最简单的对象。您可以使用 Web 项目中的一组模型类来执行此操作,这些模型类来回映射到您的 EF 类 (see @CrazyDart's answer);或像这样项目匿名对象:

return new 
{
    WantedProperty = entity.SomeProperty
};

(请注意,您需要将 WebAPI 返回类型更改为 object 才能正常工作。)

在最近的项目中,我看到开发人员采用返回匿名对象的方法和接受参数的方法,使用 dynamic 参数并在控制器中处理 JSON 分解。对于中小型项目,这似乎非常有效。对于更正式/更大的项目,围绕它的适当框架和映射可能更有意义。

【讨论】:

  • 匿名对象是一个不错的方法...但是您需要更改方法的返回类型。优点是需要维护的代码更少,您可以从同一方法返回不同的匿名对象……缺点是您将无法生成文档。
  • @CrazyDart 是的...我会补充的。
猜你喜欢
  • 2013-03-01
  • 2018-03-21
  • 2013-04-12
  • 2014-09-17
  • 2017-12-11
  • 2020-10-15
  • 1970-01-01
  • 1970-01-01
  • 2018-01-15
相关资源
最近更新 更多