【问题标题】:WebApi routing for asp.net WebForms returns 404用于 asp.net WebForms 的 WebApi 路由返回 404
【发布时间】:2014-05-07 22:27:28
【问题描述】:

我在 asp.net WebForms 应用程序中配置 WebApi 路由时遇到了一些问题。

global.asax 文件中,我有这样的内容:

void Application_Start(object sender, EventArgs e)
{
    GlobalConfiguration.Configure(WebApiConfig.Register);
}

我有另一个包含此代码的文件:

using System.Web.Http;

namespace WebConfig
{
    public static class WebApiConfig
    {
        public static void Register(HttpConfiguration config)
        {
            config.MapHttpAttributeRoutes();

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

然后,在根目录中,我有一个名为 api 的文件夹,在该文件夹中我有一个文件,其中包含一个看起来有点像这样的类:

public class MyController : ApiController
{
    [Route("MyController")]
    [HttpPost]
    public HttpResponseMessage Post([FromBody]string value)
    {....}

最后,在我的客户端代码中,我有这个 ajax 调用:

$.ajax({
    url: "/api/MyController",
    contentType: "application/json; charset=utf-8",
    type: "POST",
    dataType: "json",
    cache: "false",
    data: someData});

但是,当我运行此代码时,我得到的只是 404 错误。我需要在路由机制中进行哪些更改才能使其正常工作?

【问题讨论】:

  • 顺便说一句,您所说的用于 asp.net WebForms 的 WebAPI 是什么意思?自 vs2013 以来,我们对所有 Web 应用程序(WebForms、MVC、WebAPI)使用一种类型的项目
  • 我没有使用网络应用程序,只是一个网站。

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


【解决方案1】:

我认为其他人非常接近。试试这个:

[RoutePrefix("api")]  // or maybe "api/", can't recall OTTOMH...
public class MyController : ApiController
{
    [Route("MyController")]
    [HttpPost]
    public HttpResponseMessage Post([FromBody]string value)

然后请求/api/MyController

如果这不起作用,请使用 RouteDebugger 分析您的路线,以及它拒绝匹配的原因。用您在 RouteDebugger 中看到的内容修改您的问题,以便我可以追踪不匹配的内容。

此外,您可能需要在您的 Register 函数中调用 MapHttpAttributeRoutes - 但不确定。


编辑

现在我再次查看它,我想我发现它有更多问题。

首先,让我们从模板开始:

这是你所拥有的(来自你的问题):

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

这里奇怪的是您的模板没有{id} 段,但被定义为可选。听起来模板中缺少它,应该将路由更改为:

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

请注意,您还删除了默认操作 - 我不确定 MVC 是否自动使用约定方法来定位称为 Post 的方法,但我想确实如此。

第二个问题是您的方法签名是(再次来自您的问题):

public HttpResponseMessage Post([FromBody]string value)

它定义了Post,它接受一个名为value的参数,而你的路由定义了一个名为id的参数。因此存在另一个不匹配。您可以重命名变量或装饰(见下文)。此外,{id} 被标记为可选,但我相信(这里我不记得确切的 OTTOMH)对于未提供 {id} 的情况,您需要为 value 赋予默认值,因此将它们组合在一起:

public HttpResponseMessage Post([FromBody(Name="id")]string value = null)

这个应该修复它,虽然可能会有更多问题......但让我们从这些开始。

【讨论】:

  • @frenchie RouteDebugger 呢?你能发布它的输出吗 - 获取更多数据来弄清楚它会非常有用。另外,可以肯定的是,您检查/尝试致电MapHttpAttributeRoutes,对吗?
  • 所有代码贴出;这只是一个语法问题,10秒就解决了。
  • @frenchie 我没有收到你的最后评论。半小时前您说您尝试了一个建议,但仍然无法正常工作。现在你说它在 10 秒内解决。所以您已经有了解决方案(然后您可以将其作为答案发布),还是您仍然遇到问题?如果是后者,那么获得一些调试信息的能力将对您大有帮助。
  • 我的意思是,使用我提供的代码,解决方案是一个简单的修复,如果您知道如何修复它,可能只需要 10 秒即可实现。我仍在尝试打开和关闭;基本上我已经编写了一个使用 asmx Web 服务的应用程序:我有一个 Web 服务,它只有一个我使用 POST 调用的方法,我希望将此 Web 服务转换为使用 WebAPI。
  • @frenchie 请记住,试图在 SO 上帮助您的人是在没有调试器的情况下这样做的(在大多数情况下),并且获取一些调试信息可以帮助解决很多问题。其次,很多问题需要 10 秒才能解决,但需要数小时和数天才能解决问题(尽管首先知道如何解决它,一旦知道它是什么)。
【解决方案2】:

url: "/api/MyController" 更改为url: "/api/My"

【讨论】:

  • 仍然得到 404;如果控制器被称为 MyController 为什么将 ajax 调用更改为 url: "/api/My" 会有所不同?
  • WebAPI 默认只查找Controller后缀之前的部分
【解决方案3】:

您是否考虑过使用 Route 属性?我发现它们比路由配置更容易。

public class MyController : ApiController
{
    [Authorize]
    [Route("MyController")]
    [HttpPost]
    public HttpResponseMessage Post([FromBody]string value)
    {....}
}

也许您还可以尝试在 mvc4 也支持的专用 RouteConfig 类中配置您的路由。我的路由配置设置如下所示:

/// <summary>
/// The route config class
/// </summary>
public class RouteConfig
{
    /// <summary>
    /// Registers the routes.
    /// </summary>
    /// <param name="routes">The routes.</param>
    public static void RegisterRoutes(RouteCollection routes)
    {
        routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

        routes.MapRoute(
            name: "Default",
            url: "{controller}/{action}/{id}",
            defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
        );
    }
}

【讨论】:

  • 我尝试了这种方法,但它不起作用;我一定做错了什么。你能检查一下我发布的修改后的代码吗?
  • 除了我刚刚发布的编辑之外,您可以做的另一件事是转到您的基本 URL,“localhost:{port}/help”,看看是否找到您的帮助页面您有关已配置哪些路线的信息。如果您无法访问帮助页面,您可能还有其他问题。
  • MapRoute 用于 MVC 而不是用于 WebApi
  • 虽然 MapRoute 用于 MVC,但如果您导入 System.Web.Mvc 并在 RouteCollection 对象上使用 MapRoute 方法,WebApi 将识别它。
【解决方案4】:

在你的控制器类上使用 [RoutePrefix]

[RoutePrefix("api/My")]
public class MyController : ApiController
{
    [Route("MyController")]
    [HttpPost]
    public HttpResponseMessage Post([FromBody]string value)
    {....}
}

那么你应该可以导航到 api/My/MyController

【讨论】:

  • 其实我是想导航到api/MyController,而不是api/My/MyController
【解决方案5】:

[Route("MyController")] 更改为[Route("api/MyController")]

然后它将按您的预期工作。

【讨论】:

  • 嗯,这很奇怪,它对我来说工作正常。我有一个示例应用程序,如果您愿意,我可以发送给您;它可能会给你一些关于你的设置有什么问题的想法。我一直在通过 Fiddler 进行测试,尽管这与您的 js 客户端应该没有太大区别。会不会是客户端的问题?
  • 我在网站项目中使用控制器,而不是 Web 应用程序项目。可能这就是为什么没有一个答案能解决它的原因。为努力而投票。
  • 在您的问题中,您说您在 asp.net WebForms 应用程序中配置 WebApi 路由时遇到了一些麻烦。所以,这就是我所做的:我在 VS2013 中创建了一个 Web 表单应用程序并勾选了“Web API”选项。然后我复制并粘贴了您问题中的代码,编译并运行它。我通过传递与您在 ajax 调用中相同的参数使用 Fiddler 对其进行了测试,正如您所说,我得到了 404。但是在我按照回复中的描述更改了路由之后,它就可以正常工作了。请注意,我对这项技术还很陌生,所以我可能会遗漏一些东西。很抱歉我帮不上忙。
  • 它不是一个网络表单应用程序,它是一个网站。在 VS2013 中,转到 File > New WebSite > 并选择 Asp.net Empty Web Site。它不是一个网络应用程序。
【解决方案6】:

您的 RouteAttribute 会覆盖配置设置,因此您有两个选择:

1) 删除 RouteAttribute 并使用 URL:/api/my

2) 保留RouteAttribute 并使用 URL /MyController(在这种情况下忽略配置设置)

从我看到的 cmets,您想要导航到:api/MyController。所以第三个选项没有测试,但我认为它可能有效:

3)[Route("api/MyController")]

【讨论】:

    【解决方案7】:

    好的,经过 2 多周的反复思考为什么看似简单的事情不起作用,我终于弄明白了!!!!!

    问题出在这句话中:

    然后,在根目录中,我有一个名为 api 的文件夹,在该文件夹中我 有一个包含 ... Web API 控制器文件的文件

    解决方案原来是 10 秒修复:

    将 MyWebAPIController.cs 文件放到 App_Code 文件夹中

    按照我的方式,.cs 文件位于名为 /api 的根目录中,因为我错误地认为,如果您想从客户端调用 Web 服务 /api/MyController,您需要创建一个匹配的目录该路径,然后将控制器放在该目录中。相反,您必须将控制器文件放在 App_Code 目录中。

    LB2 的回答确实对我的属性有所帮助,同时使用 [RoutePrefix][Route]

    [RoutePrefix("api")]
    public class MyController : ApiController
    {
        [Route("MyController")]
        public HttpResponseMessage Post([FromBody]string value)
    

    然后你可以这样调用它:

    $.ajax({
        url: "/api/MyController",
        type:POST,
        ...});
    

    感谢大家关注这个问题!!

    【讨论】:

      【解决方案8】:

      我的挑战略有不同。我的设置是 asp.net webforms 项目并使用 VS2013。我想介绍 Web Api。曲线球是我在 VB.net 中实现的 Web 表单。

      我想用 C# 编写我的 API,所以我必须通过 web.config 启用 codeSubDirectories 选项。

      <codeSubDirectories>
          <add directoryName="VBCode"/>
          <add directoryName="CSCode"/>        
      </codeSubDirectories>
      

      我分别在 App_Code 文件夹下创建了两个文件夹(VBCode 和 CSCode)。

      然后我将我所有的 vb.net 类移动到 VBCode 子目录。

      在CSCode下创建UserController.cs,编写常规web api代码。

      using System;
      using System.Collections.Generic;
      using System.Linq;
      using System.Net;
      using System.Net.Http;
      using System.Web.Http;
      
      namespace WebAPIDemo
      {
      
      public class UserController : ApiController
      {
          static IUserRepository _repo = new UserRepository();
          // GET api/<controller>
      
          public IEnumerable<Users> GetAllUsers()
          {
              return _repo.GetAllUsers();            
          }
      
          // GET api/<controller>/5
          public IHttpActionResult GetUserById(int id)
          {
      
              return Json(_repo.GetUserById(id));
          }
      

      修改了global.asax

      <%@ Application Language="VB" %>
      <%@ Import Namespace="System.Web.Routing" %>
      <%@ Import Namespace="System.Web.Http" %>
      
      <script RunAt="server">
      
          Sub Application_Start(ByVal sender As Object, ByVal e As EventArgs)
              ' Code that runs on application startup
              RouteTable.Routes.MapHttpRoute(
                   "defaultApi",
                  "api/{controller}/{action}/{id}",
                  defaults:=New With {.id =     System.Web.Http.RouteParameter.Optional})
      
          End Sub
      

      使用和不使用此装饰器 [RoutePrefix("api")] 的 api 调用都有效。

      我花了几个小时才弄清楚这个实现。

      Call 1:
      http://localhost:60203/api/user/getuserbyid/2
      
      Result:
      {"Id":2,"FirstName":"Alan","LastName":"Wake","Company":"XYZ Corp","Email":"alan@xyz.com","PhoneNo":"64649879"}
      
      Call 2:
      http://localhost:60203/api/user/getallusers
      
      Result:
      <ArrayOfUsers xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.datacontract.org/2004/07/WebAPIDemo">
      <Users>
      <Company>ABC</Company>
      <Email>madhur@abc.com</Email>
      <FirstName>Madhur</FirstName>
      <Id>1</Id>
      <LastName>Kapoor</LastName>
      <PhoneNo>65431546</PhoneNo>
      </Users>
      <Users>
      <Company>XYZ Corp</Company>
      <Email>alan@xyz.com</Email>
      <FirstName>Alan</FirstName>
      <Id>2</Id>
      <LastName>Wake</LastName>
      <PhoneNo>64649879</PhoneNo>
      </Users>
      </ArrayOfUsers>
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2021-02-01
        • 1970-01-01
        • 1970-01-01
        • 2011-01-31
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多