使用AJAX传递多个参数到WebApi

5

AJAX请求:

$.ajax({
            url: url,
            dataType: 'json',
            type: 'Post',
            data: {token:"4", feed:{"id":0,"message":"Hello World","userId":4} }
        });

服务器端 Web API:

 [HttpPost]
 public HttpResponseMessage Post(string token, Feed feed)
 {
    /* Some code */

    return new HttpResponseMessage(HttpStatusCode.Created);
 }

错误代码404: {"message":"找不到匹配请求URI“localhost:8080/api/feed”的HTTP资源。","messageDetail":"在控制器'Feed'上没有找到与请求相匹配的操作。"}

我为什么会遇到这个错误,为什么我不能将多个参数POST到我的API?


这是正确的代码吗?它说你正在调用 feed,但方法名是 post - Christian Phillips
@christiandev:feed是控制器的名称,不是类似WEBAPI调用中的方法名。 - iCollect.it Ltd
@TrueBlueAussie,我不确定控制器是什么 - 但是,要调用控制器,需要在feed/前加上斜线吗? - Christian Phillips
@christiandev:不需要斜杠。如果缺少方法和ID部分,它将调用默认定义的方法。 - iCollect.it Ltd
@TrueBlueAussie 这跟我的情况不一样。 我确实更改了我的路由规则 routeTemplate: "api/{controller}/{action}"。 - Mohsin JK
显示剩余3条评论
5个回答

13

首先编写一个视图模型:

public class MyViewModel
{
    public string Token { get; set; }
    public Feed Feed { get; set; }
}

你的控制器操作将作为参数使用:

[HttpPost]
public HttpResponseMessage Post(MyViewModel model)
{
    /* Some code */

    return new HttpResponseMessage(HttpStatusCode.Created);
}

最后,将您的jQuery调用适应为将其发送为JSON:

$.ajax({
    url: url,
    type: 'POST',
    contentType: 'application/json',
    data: JSON.stringify({
        token: '4',
        feed: {
            id: 0,
            message: 'Hello World',
            userId: 4
        } 
    })
});

注意AJAX调用的重要事项:

  • 将请求的contentType设置为application/json
  • 使用JSON.stringify函数将数据包装起来,以有效地将javascript对象转换为JSON字符串
  • 删除无用的dataType: 'json'参数。jQuery将自动使用服务器发送的Content-Type响应头来推断如何解析传递给success回调函数的结果。

不,那绝对是不正确的。Web API 使用的 Newtonsoft JSON 序列化器将完美地处理这种情况。这允许根据语言编写语义上正确的变量名称:在 JS 中,变量名称以小写字母开头,在 C# 中,属性名称以大写字母开头。 - Darin Dimitrov
1
@DarinDimitrov 您的意思是我不能在POST API中使用多个参数吗? - Mohsin JK
你可以这样做,但是模型绑定器会让你的生活变得更加困难。这是一团糟。在这里阅读:http://blogs.msdn.com/b/jmstall/archive/2012/04/16/how-webapi-does-parameter-binding.aspx 一旦你阅读了这篇文章,你就会完全忘记传递多个参数,并像我的答案所示一样正确地使用视图模型。这样,你就不必担心哪个参数来自哪个主体或头部或其他什么地方。你只有一个参数,即你的视图模型,客户端直接将其作为JSON字符串发送到请求有效负载中。 - Darin Dimitrov
我同意@DarinDimitrov的观点(很难不同意一个拥有464k积分的人 :) )使用viewmodel的方法,这绝对可以使事情变得更加清晰。 - Christian Phillips

2
我最近遇到了类似的问题,以下是我解决它的一些信息。我认为这个问题与WebApi如何处理参数有关。你可以在这里这里阅读更多相关信息。但本质上有两种方式来POST参数,即在body或uri中。Body只能包含一个参数,但它可以是一个复杂的参数,而URI可以包含任意数量的参数(达到URI字符限制),但它们必须是简单的。当jQuery执行POST ajax调用时,它试图将所有数据参数传递给body,在你的情况下,由于body只能具有一个参数,这种做法行不通。
从代码角度来看,我认为你需要像这样的东西:
var token = "4";
var feed = {Id:0, Message:"Hello World", UserId:4};

$.ajax({
    url: "/api/Feed/?token=" + token,
    dataType: 'json',
    type: 'Post',
    data: JSON.stringify(feed)
});

希望这能帮到你。

2

尝试使用服务器端(从记忆中,您只能拥有一个FromBody参数,因此它需要包含所有传入的属性):

public class TokenAndFeed
{
    public String token {get; set;}
    public Feed feed {get; set;}
}

 public HttpResponseMessage Post([FromBody]TokenAndFeed tokenAndFeed)
 {
    /* Some code */

    return new HttpResponseMessage(HttpStatusCode.Created);
 }

@Mohsin JK:我的错...我认为你只能有一个[FromBody]参数,所以它必须包含你的两个对象。 - iCollect.it Ltd

1

你能发一下你的Feed类,以确保属性匹配吗?

var data = {
     token: "4",
     feed: {Id:0,Message:"Hello World",UserId:4}
}

$.ajax({
            url: "/api/Feed/",
            dataType: 'json',
            type: 'Post',
            data: JSON.stringify(data)
        });

@TrueBlueAussie,更新 - 我以为是因为缺少“/”,所以才出现了这个问题。 - Christian Phillips
这是我的Feed类, public class Feed { public int Id { get; set; } public string Message { get; set; } public int UserId { get; set; } } - Mohsin JK
属性不匹配,它们是大小写敏感的。我会更新。 - Christian Phillips

0
试一下这个。你需要从请求体中获取JSON对象数据,读取请求的输入流并将其映射到你的数据模型中。
public class TokenAndFeed
{
public string Token { get; set; }
public Feed Feed { get; set; }
}      

[HttpPost]
public HttpResponseMessage Post()
{
    System.IO.Stream str;
    String jsonContents;
    Int32 strLen, strRead;
    str = HttpContext.Current.Request.InputStream;
    strLen = Convert.ToInt32(str.Length);
    byte[] byteArray = new byte[strLen];
    strRead = str.Read(byteArray, 0, strLen);
    jsonContents = Encoding.UTF8.GetString(byteArray);

    TokenAndFeed tAndf = JsonConvert.DeserializeObject<TokenAndFeed>(jsonContents);

    // some code here  
    return new HttpResponseMessage(HttpStatusCode.Created);
    }

希望这能有所帮助。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接