【问题标题】:webapi 404 not found when calling from react with post action从响应与发布操作调用时未找到 webapi 404
【发布时间】:2019-01-16 00:55:13
【问题描述】:

我有以下控制器操作

  [HttpPost]
        [Route("api/Tenant/SetTenantActive")]
        public async Task<IHttpActionResult> SetTenantActive(string tenantid)
        {
            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.Id == tenantid);
            if (tenant == null)
            {
                return NotFound();
            }

            tenant.Active = true;
            var result = await tenantStore.UpdateAsync(tenant);

            return Ok(result);
        }

还有我的反应代码:

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: {tenantid:selectedRows[0].key},
                    };

                    adalApiFetch(fetch, "/Tenant/SetTenantActive", options)
                        .then(response =>{
                        if(response.status === 200){
                            Notification(
                                'success',
                                'Tenant created',
                                ''
                                );
                        }else{
                            throw "error";
                        }
                        })
                        .catch(error => {
                        Notification(
                            'error',
                            'Tenant not created',
                            error
                            );
                        console.error(error);
                    });
                }
            },
            getCheckboxProps: record => ({
                type: Radio
            }),
        };

        return (
            <Table rowSelection={rowSelection} columns={columns} dataSource={this.state.data} />
        );
    }
}

export default ListTenants;

只关注 onchange 事件,

还有截图:

看起来请求到达了 webapi(我附加了调试器)

更新:

基本上,如果我不输入 FromBody,我需要通过查询字符串发送参数。 但是,如果我从 Body 中输入并在 body 中发送参数,则它在 webapi 上收到 null

【问题讨论】:

  • 乍一看,您的路线设置对我来说是正确的。我注意到如果 tenantStore.Query().FirstOrDefaultAsync(x =&gt; x.Id == tenantid) 返回 null,您将返回 NotFound。验证此查询是否确实成功。很有可能此查询实际上失败了,因此您返回了 404。
  • 但是当我附加调试器时它甚至没有达到断点
  • 你是否可以直接使用 Postman、Insomnia、curl 或其他一些 REST 测试工具访问 api?试图找出是 API 问题还是您的客户端代码中的问题。
  • 我想通了,基本上我需要创建一个发布请求,但是使用这样的查询字符串参数:/SetTenantActive?tenantid=1。但是,我的问题仍然存在,为什么它不接受正文中的数据?
  • @LuisValencia 尝试在输入参数之前添加[FromBody],如下所示:public async Task&lt;IHttpActionResult&gt; SetTenantActive([FromBody]string tenantid)

标签: asp.net .net reactjs asp.net-web-api asp.net-web-api2


【解决方案1】:

在您的操作方法中的输入参数之前添加 [FromBody],如下所示:

public async Task<IHttpActionResult> SetTenantActive([FromBody] string tenantid) 

然后,将您选择的行键转换为字符串

const options = {
                        method: 'post',
                        body: { tenantid : selectedRows[0].key.toString() }
                    };

【讨论】:

  • 我已经这样做了,但是在 webapi 中,参数被接收为 null
  • 当我调试时我可以看到选项 const 设置正确,将很快上传截图
  • 我是否缺少内容类型 json 或其他内容?
  • 问题是tenantid需要被解释为字符串,这就是为什么我建议添加.tostring()
  • 在开发者工具的网络选项卡中,检查您的 POST api 调用的请求负载
猜你喜欢
  • 2021-02-05
  • 1970-01-01
  • 2015-10-05
  • 2017-12-07
  • 1970-01-01
  • 2019-05-01
  • 2018-03-20
  • 2020-09-14
  • 1970-01-01
相关资源
最近更新 更多