I have what should be a VERY basic scenario ... one which I feel I have done 100 time before but for some reason it has decided to NOT work and waste my time on something trivial ...
I am using WebAPI with Attribute routes (love them).
I am trying to pass in two parameters, one from the Body and one from the Uri. They are both basic types ... one a Boolean and the other a Long sponsorID.
Pretty simple service signature ...
[HttpPut]
[Route("adminAPI/sponsors/{sponsorID:long}/Enable")]
public HttpResponseMessage EnableSponsor([FromBody]Boolean enabled, [FromUri] Int64 sponsorID)
{
HttpResponseMessage ret = null;
// does stuff and populates the response
return ret;
}
Using Postman and Advanced REST Client and JQuery/Chrome I have been getting "Bad Request" errors ...
var request = function () {
$.ajax({
type: 'PUT',
url: 'http://localhost:50865/adminAPI/Sponsor/23/Enable',
data: { "enabled": true },
contentType: "application/json"
})
.done(function (data, textStatus, jqXHR) {
if ([200, 204, 304].indexOf(data.StatusCode) === -1) {
} else {
}
})
.fail(function (jqXHR, textStatus, errorThrown) {
});
};
I am getting the following error ...
The parameters dictionary contains a null entry for parameter 'enabled' of non-nullable type 'System.Boolean' for method 'System.Net.Http.HttpResponseMessage EnableSponsorBanner(Boolean, Int64)' in 'WEB.Admin.api.SponsorAPIController'. An optional parameter must be a reference type, a nullable type, or be declared as an optional parameter."
For some reason the [FromBody] parameter is not being passed along with the request, resulting in the error. When I make the parameter nullable the request goes through but, as expected the enabled argument is NULL?
I am beating my head against the wall ... any ideas?
SOLUTION
I tried simply removing the key from the Web Service call and had no success. Instead I created a Data Transfer Object (DTO) with the basic datatypes that I might send to a service individually. I can use this to pass this model to pass simple value references for this and any other requests made in the future.
//
// The Data Transfer Object
public class APIValueTypes
{
public Boolean booleanValue { get; set; }
public Int64 longValue { get; set; }
public String stringValue { get; set; }
public DateTime dateValue { get; set; }
}
Since the Service knows what value it's looking for it can grab whatever value it requires.
[HttpPut]
[Route("adminAPI/sponsors/{sponsorID:long}/Enable")]
public HttpResponseMessage EnableSponsor([FromBody]APIValueTypes enabled, [FromUri] Int64 sponsorID)
{
HttpResponseMessage ret = null;
Boolean isEnabled = enabled.booleanValue;
// does stuff and populates the response
return ret;
}
CAVEAT
I have to confess at this time however that while I have it working in my REST tools, I have been unable to get it to work in my JQuery implementation. So while my post has been answered I am having another issue with JQuery ajax$ ... Even though I am sending in the DTO object the service method still receives a null instead of the object ... (another post I suspect ... - sigh)
var request = function () {
$.ajax({
type: 'PUT',
url: 'http://localhost/adminAPI/Sponsor/23/Enable',
data: { "booleanValue": false },
contentType: "application/json",
})
.done(function (data, textStatus, jqXHR) {
console.log(data);
if ([200, 204, 304].indexOf(data.StatusCode) === -1) {
} else {
}
})
.fail(function (jqXHR, textStatus, errorThrown) {
});
};
CAVEAT SOLUTION
I discovered that simply sending the JSON object as the data payload was not working. I had to "stringify" the data in order to get it to be serialized back to the APIValueTypes parameter datatype. So the call to the service from JQuery now looks like ... pay attention to the data assignment ...
var request = function () {
$.ajax({
type: 'PUT',
url: 'http://localhost/adminAPI/Sponsor/23/Enable',
data: JSON.stringify({ "booleanValue": false }),
contentType: "application/json",
})
.done(function (data, textStatus, jqXHR) {
console.log(data);
if ([200, 204, 304].indexOf(data.StatusCode) === -1) {
} else {
}
})
.fail(function (jqXHR, textStatus, errorThrown) {
});
};
I hope that someone can find this little journey useful and that when I forget it in 6 months this post will still be here to remind me as well!! Thanks again!