Pass complex parameter to web API service via javascript

I am making an ASP.NET Web API web service and an HTML / javascript page to validate it. The problem I am facing is passing a complex data parameter and using it correctly in the web API controller.

I know there are many similar questions and I have read them, tried the solutions and didn’t solve them. I have also read the JQuery documentation.

Here's my controller:

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
}

      

Displaying the route in WebApiConfig.cs:

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

      

And the 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);
          });

      

I am currently getting 404. I tried $.getJSON(uri + '/' + query)

but that didn't work either. Before I passed this object, I called it successfully, so I believe that routing in general is fine. I tried a type converter but it didn't help but still 404. Does anyone see what I am missing / doing wrong?

+3


source to share


3 answers


Answer

You are using the wrong one uri

. You need api/titleEstimate/getTitleEstimate

. This will explain and resolve your 404s.

The answer to the next question

Everything you do almost works. After you resolve 404, you find that you are not getting the value FromUri

and you have your next question. So, you need to change your route config to this:

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

      

Then, you will not only allow 404, but also get the value FromUri

that you send as query string parameters.

Demo

Here is a fiddle for proof that calls this controller where LIVE is hosted here . The only thing I changed in production is uri

for 404 resolution and route config to make sure you get the value FromUri

. It's all.

Html

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

      



JavaScript

It will be successful.

Note, we only need this domain

because we are doing cross-site scripting here for demo purpose.

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);
    });
});

      

It will be 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);
    });
});

      

controller

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!");
        }
    }        
}

      

You can read more about WebApi routing here . From reading it, you can probably find an alternative solution in your route config. This blog also has many awesome examples .

+6


source


For complex objects, I usually send them in the body of the message, not the URL.

Do you have any objections to an approach like the answer to this question? How to pass json POST data to Web API method as object

Seems like a simpler / natural approach.



Something like (untested, but should be close):

[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);
      });
});

      

0


source


First, I would try to use the web.api attribute routing feature like this:

[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
    }
}

      

It would also be helpful to see the request in your dev tools. I disagree with Colin that you should do this POST because HTTP POST is supposed to be used to create new items. You are trying to get information, so HTTP GET makes sense.

I think Web.Api assumes GET methods are the default, but declaring it an HttpGet attribute will surely take care of that.

0


source







All Articles