【问题标题】:Asp Web Api async action - 404 errorAsp Web Api 异步操作 - 404 错误
【发布时间】:2013-04-30 17:35:10
【问题描述】:

我有一些用于此操作的 api 控制器:

public class ProxyController : ApiController {
    public async Task<HttpResponseMessage> PostActionAsync(string confirmKey)
    {
         return await Task<HttpResponseMessage>.Factory.StartNew( () =>
               {
                  var result = GetSomeResult(confirmKey);
                  return Request.CreateResponse(HttpStatusCode.Created, result);
               });
    }
}

这是我的 api 路由配置:

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

当我尝试对此操作发出任何发布/获取请求时,它会返回“404”错误。我该如何解决?此控制器中的所有其他非异步操作都可以正常工作。

UPD。 JS查询:

$.ajax({
        url: Url + '/api/Proxy/PostActionAsync',
        type: 'POST',
        data: { confirmKey: that.confirmKey },                  
        dataType: 'json',                   
        xhrFields: {  withCredentials: true  },
        success: function (data) {
            ............
        },
        error: function (jqXHR, textStatus, errorThrown) {
             ............
        }                        
});

UPD。通过将[FromBody] 添加到我的操作方法中的参数来解决,就像在 J. Steen 的回答中一样,现在看起来像

public class ProxyController : ApiController {
       public async Task<HttpResponseMessage> PostActionAsync([FromBody]string confirmKey)
        {
            var someModel = new SomeResultModel(User.Identity.Name);
            await Task.Factory.StartNew(() => someModel.PrepareModel(confirmKey));

            return Request.CreateResponse(HttpStatusCode.OK, someModel);
        }
    }

而且它有效!

【问题讨论】:

  • 也发布您的ActionResult 方法和控制器名称。如果可能的话,你的异步调用 Jquery 也是。:)
  • @IgorKonopko:尝试用[HttpPost]标记动作
  • 应该是action-based路由,这样就好了

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


【解决方案1】:

Web API 的路由配置与 MVC 的工作方式略有不同。

试试

routes.MapHttpRoute("DefaultApi", "api/{controller}/{id}", new { id = RouteParameter.Optional });

请注意缺少的{action},因为它会在调用时由 Web API 自动解决,具体取决于您用于请求的 HTTP 动词。

考虑this article on Web API routing 列出(例如):

HTTP Method  URI Path            Action           Parameter
GET          api/products        GetAllProducts   (none)
GET          api/products/4      GetProductById   4
DELETE       api/products/4      DeleteProduct    4

在您的情况下,操作的异步版本也会自动解析。

POST         api/products        PostActionAsync  (Post data)

由于我们现在知道控制器名称,请求将如下所示:

GET api/proxy
GET api/proxy/4
POST api/proxy (with post data)

编辑

经过进一步的研究(我承认简短),我发现了问题。

您需要在您的参数前添加[FromBody]

public async Task<HttpResponseMessage> PostActionAsync([FromBody] string confirmKey)

这与发送 just 值(无包装 json)相结合可以创造奇迹。将内容类型设置为“application/x-www-form-urlencoded”而不是json,并将您的参数发送为"=" + that.confirmKey

替代方案

如果您不想摆弄内容类型和前缀 =-符号,只需将其作为查询字符串的一部分发送即可。忘记[FromBody] 和其他。打电话

/api/Proxy/PostActionAsync?confirmKey=' + that.confirmKey

Additional, exhaustive information in this blog.

【讨论】:

  • 我已经按照你的例子更改了路由,我的客户端 ajax url 也更改为 ServerUrl+ '/api/Proxy?action=PostActionAsync',现在它返回 500(内部服务器错误)。我是否应该在一个 api 控制器中只使用一个 get/post/put 操作?
  • 惯例是每个控制器只使用一个 POST。此外, ?action=PostActionAsync 可能也无法正常工作,我很抱歉。 =/
  • 我很困惑。如果您想要基于操作的路由,我的回答是错误的。您的 route-config 需要与您最初声明的一样。
  • 你的意思是顶帖?
  • 我一直在尝试您的代码,创建一个带有后异步操作的控制器以及您的原始路由配置。对我来说,它按预期工作。您确定您在api/Proxy/PostActionAsync 前面粘贴的Url 参数值正确吗?
【解决方案2】:

这种改变可能吗?

public async Task<HttpResponseMessage> PostActionAsync()
{
    var result = await GetSomeResult();
    return Request.CreateResponse(HttpStatusCode.Created, result);
}

【讨论】:

  • 'CreateResponse()' 返回'HttpResponseMessage',无法转换为'Task'
  • async Task&lt;string&gt; WaitAsynchronouslyAsync() { await Task.Delay(10000); return "Finished"; } 这是来自MSDN 的示例。
  • 如果您的PrepareModel 方法返回布尔值,您可以更改:var eventModel = new EventResultModel(...); var result = await eventModel.PrepareModel(confirmKey)); if (result) { return Request.CreateResponse(HttpStatusCode.OK, eventModel); } else { ...error response... }
  • 但是当我尝试对此操作发出 Get 请求时,它说该操作只允许 Post 请求
猜你喜欢
  • 2011-12-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-04-22
  • 1970-01-01
  • 2016-02-02
  • 1970-01-01
相关资源
最近更新 更多