通过javascript将复杂参数传递给Web API服务

时间:2015-04-30 20:59:31

标签: javascript c# jquery asp.net asp.net-web-api

我正在制作一个ASP.NET Web API Web服务,以及一个HTML / javascript页面来测试它。我遇到的问题是传递一个复杂的数据参数,并在Web API控制器中正确地通过它。

我知道有很多类似的问题,我已经阅读过它们并尝试了解决方案并且没有解决它。我还阅读了一些JQuery文档。

这是我的控制器:

public class TitleEstimateController : ApiController
{
    public IHttpActionResult GetTitleEstimate([FromUri] EstimateQuery query)
    {
            // All the values in "query" are null or zero
            // Do some stuff with query if there were anything to do
    }
}

public class EstimateQuery
{
    // Various fields
}

WebApiConfig.cs中的路由映射:

config.Routes.MapHttpRoute(
                name: "DefaultApi",
                routeTemplate: "api/{controller}/{query}"
            );

和javascript:

var uri = 'api/titleEstimate/';
var query = {
            "username": $("#user").val(),
            // other fields
        };

      $.getJSON(uri,query)
          .done(function (data) {
              $('#product').text("OK");
          })
          .fail(function (jqXHR, textStatus, err) {
            $('#product').text('Error: ' + err);
          });

目前我正在收到404.我尝试了$.getJSON(uri + '/' + query),但这也没有用。在我传递这个对象之前,我正在成功调用它,所以我认为路由通常是正常的。我试过一个类型转换器,但这没有帮助,仍然是404.有人看到我错过了什么/做错了吗?

3 个答案:

答案 0 :(得分:6)

答案

您使用的是错误的uri。您需要api/titleEstimate/getTitleEstimate。这解释并将解决您的404。

回答问题

你所做的其他事情几乎都有效。解决404后,您会发现自己没有收到FromUri的值,并且您会有一个跟进问题。因此,您需要将路径配置更改为:

config.Routes.MapHttpRoute(
    name: "Default",
    routeTemplate: "api/{controller}/{action}"
);

然后,您不仅要解析404,还要接收您作为查询字符串参数发送的FromUri值。

演示

以下是a fiddle for evidence,正在调用this controlleris hosted LIVE here。我在工作版中唯一更改的是uri来解析404和路由配置,以确保您收到FromUri值。这就是全部。

HTML

<label>Username:
    <input id="user" />
</label>
<button id="submit">Submit</button>
<button id="submit-fail">Submit Fail</button>
<div id="product"></div>

的JavaScript

这将成功。

请注意,我们只需要domain,因为我们在此处进行跨站点脚本以用于演示目的。

var domain = "https://cors-webapi.azurewebsites.net";

$("#submit").click(function () {

    var uri = domain + '/api/titleEstimate/getTitleEstimate';

    var query = {
        "username": $("#user").val(),
        // other fields
    };

    $.getJSON(uri, query)
        .done(function (data) {
        $('#product').text(data);
    })
        .fail(function (jqXHR, textStatus, err) {
        $('#product').text('Error: ' + err);
    });
});

这将是404。

$("#submit-fail").click(function () {

    var uri = domain + '/api/titleEstimate';

    var query = {
        "username": $("#user").val(),
        // other fields
    };

    $.getJSON(uri, query)
        .done(function (data) {
        $('#product').text(data);
    })
        .fail(function (jqXHR, textStatus, err) {
        $('#product').text('Error: ' + err);
    });
});

控制器

public class TitleEstimateController : ApiController
{
    public class EstimateQuery
    {
        public string username { get; set; }
    }

    public IHttpActionResult GetTitleEstimate([FromUri] EstimateQuery query)
    {
        // All the values in "query" are null or zero
        // Do some stuff with query if there were anything to do
        if(query != null && query.username != null)
        {
            return Ok(query.username);
        }
        else
        {
            return Ok("Add a username!");
        }
    }        
}

您可以阅读更多详情about WebApi routing here。通过阅读,您可以在路线配置中找到替代解决方案。还有很多terrific examples in this blog post

答案 1 :(得分:0)

对于复杂对象,我通常将它们发送到邮件正文而不是URL。

您是否有任何反对类似于此问题答案的方法? How to pass json POST data to Web API method as object

这似乎是更简单/自然的方法。

类似(未经测试,但应该关闭):

[RoutePrefix("api/titleestimate")]
public class TitleEstimateController : ApiController
{
   [HttpGet]
    public IHttpActionResult GetTitleEstimate([FromBody] EstimateQuery query)
    {
        // All the values in "query" are null or zero
        // Do some stuff with query if there were anything to do
     }
}

public class EstimateQuery
{
    public string QueryName{ get; set; }
    public string Whatever{ get; set; }
}

$(function () {
   var query = {QueryName:"My Query",Whatever:"Blah"};
   $.ajax({
       type: "GET",
       data :JSON.stringify(query),
       url: "api/titleEstimate",
       contentType: "application/json"
   })
      .done(function (data) {
          $('#product').text("OK");
      })
      .fail(function (jqXHR, textStatus, err) {
        $('#product').text('Error: ' + err);
      });
});

答案 2 :(得分:0)

首先,我会尝试使用web.api的属性路由功能,如下所示:

[RoutePrefix("api/titleestimate")]
public class TitleEstimateController : ApiController
{
    [HttpGet]
    public IHttpActionResult GetTitleEstimate([FromUri] EstimateQuery query)
    {
            // All the values in "query" are null or zero
            // Do some stuff with query if there were anything to do
    }
}

在您的开发工具中查看请求也会很有帮助。我不同意Colin你应该把它作为POST,因为HTTP POST应该用于创建新项目。您正在尝试获取信息,因此HTTP GET是有意义的。

我认为Web.Api默认情况下假设方法是GET,但使用HttpGet属性声明它肯定会处理它。