I have a react component that when a checkbox is pressed, it calls a rest api, post request with a single parameter.
I put a breakpoint in the webapi and its never hit, still I get a 415 unsopported media type on the component
react js component (see onchange event)
import React, { Component } from 'react';
import { Table, Radio} from 'antd';
import { adalApiFetch } from '../../adalConfig';
import Notification from '../../components/notification';
class ListTenants extends Component {
constructor(props) {
super(props);
this.state = {
data: []
};
}
fetchData = () => {
adalApiFetch(fetch, "/Tenant", {})
.then(response => response.json())
.then(responseJson => {
if (!this.isCancelled) {
const results= responseJson.map(row => ({
key: row.ClientId,
ClientId: row.ClientId,
ClientSecret: row.ClientSecret,
Id: row.Id,
SiteCollectionTestUrl: row.SiteCollectionTestUrl,
TenantDomainUrl: row.TenantDomainUrl
}))
this.setState({ data: results });
}
})
.catch(error => {
console.error(error);
});
};
componentDidMount(){
this.fetchData();
}
render() {
const columns = [
{
title: 'Client Id',
dataIndex: 'ClientId',
key: 'ClientId'
},
{
title: 'Site Collection TestUrl',
dataIndex: 'SiteCollectionTestUrl',
key: 'SiteCollectionTestUrl',
},
{
title: 'Tenant DomainUrl',
dataIndex: 'TenantDomainUrl',
key: 'TenantDomainUrl',
}
];
// rowSelection object indicates the need for row selection
const rowSelection = {
onChange: (selectedRowKeys, selectedRows) => {
if(selectedRows[0].key != undefined){
console.log(selectedRows[0].key);
const options = {
method: 'post',
body: JSON.stringify({ clientid : selectedRows[0].key.toString() }) ,
config: {
headers: {
'Content-Type': 'application/json'
}
}
};
adalApiFetch(fetch, "/Tenant/SetTenantActive", options)
.then(response =>{
if(response.status === 200){
Notification(
'success',
'Tenant set to active',
''
);
}else{
throw "error";
}
})
.catch(error => {
Notification(
'error',
'Tenant not activated',
error
);
console.error(error);
});
}
},
getCheckboxProps: record => ({
type: Radio
}),
};
return (
<Table rowSelection={rowSelection} columns={columns} dataSource={this.state.data} />
);
}
}
export default ListTenants;
and the webapi method
[HttpPost]
[Route("api/Tenant/SetTenantActive")]
public async Task<IHttpActionResult> SetTenantActive([FromBody]string clientid)
{
var tenantStore = CosmosStoreFactory.CreateForEntity<Tenant>();
var allTenants = await tenantStore.Query().Where(x => x.TenantDomainUrl != null).ToListAsync();
foreach(Tenant ten in allTenants)
{
ten.Active = false;
await tenantStore.UpdateAsync(ten);
}
var tenant = await tenantStore.Query().FirstOrDefaultAsync(x => x.clientid == clientid);
if (tenant == null)
{
return NotFound();
}
tenant.Active = true;
var result = await tenantStore.UpdateAsync(tenant);
return Ok(result);
}
Couple of things I noticed.
POST
request with a JSON body. On the client, your request looks fine.As I understand the POST body is
{ clientid: 'some-client-id' }
public async Task<IHttpActionResult> SetTenantActive([FromBody]string clientid)
This is possibly the culprit. Your API is expecting a string as a POST body where it is a json object. Have you tried changing the type to dynamic
or JObject
?
So, essentially,
public async Task<IHttpActionResult> SetTenantActive([FromBody]dynamic clientRequest)
OR
public async Task<IHttpActionResult> SetTenantActive([FromBody]JObject clientRequest)
Alternately,
If you want to continue using your API as is, then you can just change the request you’re making from the client to ’some-client-id’
instead of { clientid: 'some-client-id' }
Change
const options = {
method: 'post',
body: JSON.stringify({ clientid : selectedRows[0].key.toString() }) ,
config: {
headers: {
'Content-Type': 'application/json'
}
}
};
to
const options = {
method: 'post',
body: JSON.stringify({ clientid : selectedRows[0].key.toString() }) ,
headers: {
'Content-Type': 'application/json; charset=utf-8'
}
};
Check your server settings. By default it should support json
but its better to verify it. Also try to clear Accept
header in yor api code and set to *
which means all types.
Moreover check adalApiFetch
method. What headers it send? Is the format of Content-Type
used & set correctly?
For a simple RESTFul call like that you could follow suggestion naming conventions along with HTTP verbs that better clarifies the intention and simplify the call itself. No need to over complicate the API model for such a simple call.
Something like
[HttpPut] // Or HttpPost. PUT is usually used to update the resourcce
[Route("api/Tenant/{clientid}/Active")]
public async Task<IHttpActionResult> SetTenantActive(string clientid) {
var tenantStore = CosmosStoreFactory.CreateForEntity<Tenant>();
var allTenants = await tenantStore.Query().Where(x => x.TenantDomainUrl != null).ToListAsync();
var updates = new List<Task>();
foreach(Tenant ten in allTenants) {
ten.Active = false;
updates.Add(tenantStore.UpdateAsync(ten));
}
await Task.WhenAll(updates);
var tenant = await tenantStore.Query().FirstOrDefaultAsync(x => x.clientid == clientid);
if (tenant == null)
{
return NotFound();
}
tenant.Active = true;
var result = await tenantStore.UpdateAsync(tenant);
return Ok(result);
}
And on the client
const rowSelection = {
onChange: (selectedRowKeys, selectedRows) => {
if(selectedRows[0].key != undefined){
var clientid = selectedRows[0].key;
console.log(clientid);
var url = "/Tenant/" + clientid + "/Active"
const options = {
method: 'put'
};
adalApiFetch(fetch, url, options)
.then(response => {
if(response.status === 200){
Notification(
'success',
'Tenant set to active',
''
);
}else{
throw "error";
}
})
.catch(error => {
Notification(
'error',
'Tenant not activated',
error
);
console.error(error);
});
}
},
getCheckboxProps: record => ({
type: Radio
}),
};
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With