【问题标题】:AngularJS web api call - can't find get method on controllerAngularJS web api调用-在控制器上找不到get方法
【发布时间】:2015-12-02 00:07:51
【问题描述】:

我一生都无法理解为什么这不起作用。

我有一个简单的 ASP.Net MVC Web API 控制器,有 2 个 get 方法。我有一个具有 2 个相应功能的 AngularJS 服务。 GetAllRisks 运行良好。但是,GetRiskByID 会返回一条错误消息,指出“未找到与请求匹配的 HTTP 请求“http://localhost:49376/api/RiskApi/GetRiskByID/6”和“在与请求匹配的 RiskApi 控制器上找不到任何操作。”

URL 被正确传递。我尝试了 API 路由的各种选项,但无处可去。我确定我错过了一些简单但看不到的东西。

如果有任何想法,我将不胜感激。

谢谢,

灰

RiskApiController

public class RiskApiController : ApiController
{
    private readonly IRiskDataService _riskDataService;

    public RiskApiController(IRiskDataService riskDataService)
    {
        _riskDataService = riskDataService;
    }

    // GET api/RiskApi
    [HttpGet]
    public IEnumerable<IRisk> GetAllRisks()
    {
        return _riskDataService.GetAllRisks().Take(20);
    }

    // GET api/RiskApi/5
    [HttpGet]
    public IRisk GetRiskByID(int riskID)
    {
        IRisk risk = _riskDataService.GetRiskByID(riskID);
        if (risk == null)
        {
            throw new HttpResponseException(Request.CreateResponse(HttpStatusCode.NotFound));
        }
        return risk;
    }
}

service.js

app.service('OpenBoxExtraService', function ($http) {

//Get All Risks
this.getAllRisks = function () {
    return $http.get("/api/RiskApi/GetAllRisks");
}

//Get Single Risk by ID
this.getRisk = function (riskID) {
    var url = "/api/RiskApi/GetRiskByID/" + riskID;
    return $http.get(url);
}
});

WebApiConfig

public static class WebApiConfig
{
    public static void Register(HttpConfiguration config)
    {
        config.Routes.MapHttpRoute(
            name: "ActionRoute",
            routeTemplate: "api/{controller}/{action}/{id}",
            defaults: new { id = RouteParameter.Optional }
        );

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

【问题讨论】:

  • [路过...您可能还有另一层问题,但这对我来说很突出] 您不能为 HttpRouteCollection 提供多个具有相同名称的路由。将第二条路线的名称值从“DefaultApi”更改为“Foo”,它可能会起作用。
  • 好吧....您的可选 routeParameters 将发生冲突。如果提供/api/RiskApi/foo,应该选择哪条路线?它将匹配 api/{controller}/{id} 以及 api/{controller}/{action}/{id} 路由,因为您在两者上都有 {id} 可选。路由器将无法判断 foo 是 {id} 还是 {action} 值。它自然无法将“foo”作为 id 的 int 发送,但我不确定路由器是否足够智能以推断基于 {action} 的路由是您想要的路由。我认为它只是无法路由。
  • 我不确定您所说的具有相同名称的路由是什么意思,因为它们具有不同的名称(ActionRoute 和 DeafultApi)。我同意你关于冲突的观点,但认为这可能会表现在可能选择错误的路线上,而不是根本找不到路线。我将研究 RoutingAttributes。谢谢指点。
  • ...哇哦。当我写评论时,我将这两个路由名称都读为“DefaultApi”。
  • ...那么,这是新开发者吗?除非您要维护现有的第一代 Web API 产品,否则在第一代 Web API 和 MVC 4 上构建它并没有什么意义。为什么您决定将您的系统锚定为过时的技术?只是因为你想用VS2010吗?

标签: angularjs asp.net-mvc-4 asp.net-web-api


【解决方案1】:

尝试将您的 WebApiConfig 类更改为:

public static class WebApiConfig
{
    public static void Register(HttpConfiguration config)
    {
        config.Routes.MapHttpRoute(
            name: "DefaultApi",
            routeTemplate: "api/{controller}/{action}/{id}",
            defaults: new { id = RouteParameter.Optional }
        );
    }
}

并更改您的参数:riskID 到 id。

// GET: api/RiskApi/GetRiskByID/5
[HttpGet]
public IRisk GetRiskByID(int id)
{
    IRisk risk = _riskDataService.GetRiskByID(id);
    if (risk == null)
    {
        throw new HttpResponseException(Request.CreateResponse(HttpStatusCode.NotFound));
    }
    return risk;
}

那么,你可以使用:

// GET: api/RiskApi/GetAllRisks
// GET: api/RiskApi/GetRiskByID/5

【讨论】:

  • 这已经是我的第一条路线了。我正在使用您在我的服务中建议的 URL。
  • 是的,但它与您的 WebApiConfig 类有关。
  • 试过了,但它导致了同样的错误(我认为它可能已经是我的第一条路线)。还是谢谢。
  • 嗯,您是否尝试将参数:riskID 更改为 id?
  • @DannyFardyJhonstonBermúdez 哈哈……就是这样。在您的控制器方法中将riskID 切换为id,或在您的路由配置中将id 更改为riskID。
【解决方案2】:

...尝试丢弃您的配置的HttpRoute 映射并使用属性引入路由映射。

由于这是第一代 Web API,您需要引入 AttributeRouting.WebAPI NuGet 包,并且您可能需要参考 here(strathweb) 以获得有关如何操作的直接指导实施。

请注意,在您的{id} 参数的当前实现中存在映射问题:您在路由配置中将其声明为 id,但随后在控制器的方法中将其标识为riskID;这些需要匹配。切换控制器的方法,使其传入的 routeParameter 命名为 id。您可以选择切换配置以在路由中声明 {riskID} 参数,但这会将您的全局配置与特定控制器的语义相结合,并且您可能需要实现更多路由约束以使其他控制器不命名为“风险“ 说得通。

public class RiskApiController : ApiController
{
   private readonly IRiskDataService _riskDataService;

   public RiskApiController(IRiskDataService riskDataService)
   {
       _riskDataService = riskDataService;
   }

   // GET api/RiskApi
   [HttpGet]
   [Route("api/RiskApi")]
   public IEnumerable<IRisk> GetAllRisks()
   {
       return _riskDataService.GetAllRisks().Take(20);
   }

   // GET api/RiskApi/5
   [HttpGet]
   [Route("api/RiskApi/{id}")]
   public IRisk GetRiskByID(int id)
   {
       IRisk risk = _riskDataService.GetRiskByID(id);
       if (risk == null)
       {
           throw new    HttpResponseException(Request.CreateResponse(HttpStatusCode.NotFound));
       }
       return risk;
   }
}

【讨论】:

  • (我想知道为什么您将其完全限定为“ASP.NET MVC Web API”...我没有看到您的标签)默认情况下它适用于 Web API 2。它不会默认情况下它在“pre-2”中工作,但您可以使其与 Nuget 包一起工作。 strathweb.com/2012/05/…
  • @TheDumbRadish 你在什么地方托管? ...IIS? ...控制台?
  • IIS。目前在开发的早期阶段使用我的本地机器。
猜你喜欢
  • 2015-08-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-05-26
  • 2018-02-14
  • 2017-10-21
相关资源
最近更新 更多