在使用MVC托管时,无法通过AJAX调用WebAPI Controller

时间:2015-09-10 21:53:03

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

我有一个MVC应用程序,其中包含几个简单的页面,这些页面主要在Web API调用上运行。为简单起见,我想将它们包含在同一个项目中。我可以启动并导航到我的页面,但是当我尝试通过Ajax调用我的API时,我一直收到404错误 - 它无法找到API函数。

这是我的javascript文件:

$(document).ready(function () {
    //set the login button to call our test API function
    document.getElementById("login_submit").addEventListener("click", GetUser);

});

function GetUser() {
    var response = $.ajax({        
        url: '/api/User',
        method: 'GET',
        contentType: 'application/json; charset=utf-8',
        success: function (data) {
            alert("Success!");
        },
        error: function (request, status, error) {
            alert(error);
        }
    });
}

这是我的控制器:

namespace MyProject.Controllers.API
{
    public class UserController : ApiController
    {
        // GET api/<controller>
        [HttpGet]        
        public IEnumerable<string> Get()
        {
            return new string[] { "value1", "value2" };
        }

        // GET api/<controller>/5
        [HttpGet]        
        public string Get(int id)
        {
            return "value";
        }
    }
}

API控制器位于我项目中Controllers文件夹中的自己的文件夹(称为“API”)中 - 这就是命名空间在此示例控制器中包含“API”的原因。

当我在浏览器上使用F12捕获发送的请求时,我可以看到我的呼叫具有以下信息:

Request URL: http://localhost:50035/api/User
Request Method: GET
Status Code: 404 / Not Found

现在我的理解是,这应该找到名为UserController的API并找到没有参数的[HttpGet]标签的函数,然后返回字符串数组(“value1”,“value2”)。相反,它没有找到任何东西。

作为最后一点,这是我的路由配置(是的,它正在Global.asax上初始化):

public static class WebApiConfig
    {
        public static void Register(HttpConfiguration config)
        {
            // Web API configuration and services

            // Web API routes
            config.MapHttpAttributeRoutes();

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

更新

根据我到目前为止收到的反馈,我移动了我的Global.asax配置。 现在看起来像这样:

 protected void Application_Start()
    {
        AreaRegistration.RegisterAllAreas();
        FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
        GlobalConfiguration.Configure(WebApiConfig.Register);
        RouteConfig.RegisterRoutes(RouteTable.Routes);
        BundleConfig.RegisterBundles(BundleTable.Bundles);

    }

现在当我调用我的API函数时,我得到......待定。它不会返回成功消息。它只是挂起。我没有得到“成功!”警报。

2 个答案:

答案 0 :(得分:2)

虽然我不确定这与我在评论中猜到的问题相同,但这是一个可能的原因。所以任何面临类似问题的人都会遇到这个问题。

MVC路由引擎尝试将传入请求与路由按照注册顺序进行匹配。

  1. 因此,如果您首先注册MVC路由 - {controller} / {action} / {id} id:optional
  2. 然后注册WebAPI路由 - api / {controller} / {id} ID:可选的
  3.   

    然后传入的请求将与MVC路由匹配,如果它不匹配路由PATTERN,那么它只会与WebAPI路由匹配。

    现在,如果您有api/User之类的请求,它将与MVC路由模式匹配,并且不会与WebAPI路由匹配。因此,MvcHandler将尝试创建一个ApiController MVC控制器类并在其上调用User()方法。因此,客户端将获得404 - 资源未找到!

    此外,如果您没有使用属性路由,则可能需要删除/注释此行

    //config.MapHttpAttributeRoutes();
    

    对于更安全的http-verb-to-api-method路由,您可以在api配置中添加以下内容。

    routes.MapHttpRoute("RestApiRoute", "Api/{controller}/{id}", new { id = RouteParameter.Optional }, new { id = @"\d+" }); //this replaces your current api route
    routes.MapHttpRoute("ApiWithActionRoute", "Api/{controller}/{action}/{id}", new { id = RouteParameter.Optional });
    routes.MapHttpRoute("DefaultApiGetRoute", "Api/{controller}", new { action = "Get" }, new { httpMethod = new HttpMethodConstraint(new string[] { "GET" }) });
    routes.MapHttpRoute("DefaultApiPostRoute", "Api/{controller}", new { action = "Post" }, new { httpMethod = new HttpMethodConstraint(new string[] { "POST" }) });
    routes.MapHttpRoute("DefaultApiPutRoute", "Api/{controller}", new { action = "Put" }, new { httpMethod = new HttpMethodConstraint(new string[] { "PUT" }) });
    routes.MapHttpRoute("DefaultApiDeleteRoute", "Api/{controller}", new { action = "Delete" }, new { httpMethod = new HttpMethodConstraint(new string[] { "DELETE" }) });
    

    前两条路线可以以[1]纯REST方式调用端点。 [2]用方法名称调用它们(虽然不符合REST标准!)

答案 1 :(得分:1)

尝试

/api/User/Get 

而不仅仅是/ api / user。如果您想了解它,请查看[RoutePrefix] and [Route],以便您可以手动管理这些内容。