自定义 Web api 上的 POST 405(不允许的方法)
Posted
技术标签:
【中文标题】自定义 Web api 上的 POST 405(不允许的方法)【英文标题】:POST 405 (Method Not Allowed) on custom web api 【发布时间】:2019-07-04 02:39:21 【问题描述】:我有以下反应代码来调用 post 端点,webapi 确实有一个帖子,但我仍然不知道为什么会出现此错误
import React, Component from 'react';
import Row, Col, Tabs, Menu, Dropdown, Button, Icon, message, Input from 'antd';
import Form from '../../components/uielements/form';
import PageHeader from '../../components/utility/pageHeader';
import Box from '../../components/utility/box';
import LayoutWrapper from '../../components/utility/layoutWrapper';
import ContentHolder from '../../components/utility/contentHolder';
import basicStyle from '../../settings/basicStyle';
import IntlMessages from '../../components/utility/intlMessages';
import Cascader from 'antd';
import adalApiFetch from '../../adalConfig';
import Notification from '../../components/notification';
const FormItem = Form.Item;
class ExtractPageTemplate extends Component
constructor(props)
super(props);
this.state = options:[], loading:false, selectedOptions:[], description:'';
this.loadData = this.loadData.bind(this);
this.enterLoading = this.enterLoading.bind(this);
this.onChange = this.onChange.bind(this);
this.handleChangeDescription= this.handleChangeDescription.bind(this);
handleChangeDescription(event)
this.setState(description : event.target.value);
enterLoading ()
this.setState( loading: true );
const options =
method: 'post',
body: JSON.stringify(
"SiteCollectionUrl": this.state.selectedOptions[0].value,
"PageName": this.state.selectedOptions[1].label,
"Description": this.state.Description
),
headers:
'Content-Type': 'application/json; charset=utf-8'
;
adalApiFetch(fetch, "/Page/CreatePageTemplate", options)
.then(response =>
if(response.status === 204)
Notification(
'success',
'Page tempate created',
''
);
else
throw "error";
)
.catch(error =>
Notification(
'error',
'Page template not created',
error
);
console.error(error);
);
componentDidMount()
adalApiFetch(fetch, "/SiteCollection", )
.then(response => response.json())
.then(json =>
console.log(json);
const firstLevelOptions = json.map(post => (
value: post.Url,
label: post.Title,
isLeaf: false
));
this.setState(
options: firstLevelOptions
);
);
onChange(value, selectedOptions)
console.log("value:", value, "selectedOptions", selectedOptions);
this.setState(
selectedOptions: selectedOptions
);
loadData(selectedOptions)
console.log("loaddata", selectedOptions);
const targetOption = selectedOptions[selectedOptions.length - 1];
targetOption.loading = true;
const options =
method: 'get',
headers:
'Content-Type': 'application/json; charset=utf-8'
;
adalApiFetch(fetch, "/Page/"+encodeURIComponent(targetOption.value.replace("https://","")), options)
.then(response => response.json())
.then(json =>
targetOption.loading = false;
console.log(json);
const secondLevelOptions = json.map(page => (
value: page.Id,
label: page.Name,
isLeaf: true
));
targetOption.children = secondLevelOptions;
this.setState(
options: [...this.state.options],
);
);
render()
console.log("uepa" , this.props);
const rowStyle, colStyle, gutter = basicStyle;
const TabPane = Tabs.TabPane;
const getFieldDecorator = this.props.form;
const formItemLayout =
labelCol:
xs: span: 24 ,
sm: span: 6 ,
,
wrapperCol:
xs: span: 24 ,
sm: span: 14 ,
,
;
const tailFormItemLayout =
wrapperCol:
xs:
span: 24,
offset: 0,
,
sm:
span: 14,
offset: 6,
,
,
;
return (
<div>
<LayoutWrapper>
<PageHeader><IntlMessages id="pageTitles.PageAdministration" /></PageHeader>
<Row style=rowStyle gutter=gutter justify="start">
<Col md=12 sm=12 xs=24 style=colStyle>
<Box
title=<IntlMessages id="pageTitles.siteCollectionsTitle" />
subtitle=<IntlMessages id="pageTitles.siteCollectionsTitle" />
>
<ContentHolder>
<Cascader
options=this.state.options
loadData=this.loadData
onChange=this.onChange
changeOnSelect
/>
<FormItem ...formItemLayout label="Description " hasFeedback>
getFieldDecorator('Description',
rules: [
required: true,
message: 'Please input the page template description',
]
)(<Input name="Description" id="Description" onChange=this.handleChangeDescription />)
</FormItem>
<Button type="primary" loading=this.state.loading onClick=this.enterLoading>
Click me!
</Button>
</ContentHolder>
</Box>
</Col>
</Row>
</LayoutWrapper>
</div>
);
const WrappedExtractPageTemplate = Form.create()(ExtractPageTemplate );
export default WrappedExtractPageTemplate;
还有我的 webapi 代码
namespace TenantManagementWebApi.Controllers
[Authorize]
[RoutePrefix("api/Page")]
public class PageController : ApiController
[HttpGet]
[Route("*sitecollectionUrl")]
public async Task<List<TenantManagementWebApi.Entities.Page>> Get(string sitecollectionUrl)
var tenant = await TenantHelper.GetActiveTenant();
var siteCollectionStore = CosmosStoreFactory.CreateForEntity<TenantManagementWebApi.Entities.SiteCollection>();
await siteCollectionStore.RemoveAsync(x => x.Title != string.Empty); // Removes all the entities that match the criteria
string domainUrl = tenant.TestSiteCollectionUrl;
string tenantName = domainUrl.Split('.')[0];
string tenantAdminUrl = tenantName + "-admin.sharepoint.com";
KeyVaultHelper keyVaultHelper = new KeyVaultHelper();
await keyVaultHelper.OnGetAsync(tenant.SecretIdentifier);
using (var context = new OfficeDe***P.Core.AuthenticationManager().GetSharePointOnlineAuthenticatedContextTenant("https://"+sitecollectionUrl, tenant.Email, keyVaultHelper.SecretValue))
var pagesLibrary = context.Web.GetListByUrl("SitePages") ?? context.Web.GetListByTitle("SitePages");
CamlQuery query = CamlQuery.CreateAllItemsQuery(100);
var pages = pagesLibrary.GetItems(query);
context.Load(pages);
context.ExecuteQuery();
List<TenantManagementWebApi.Entities.Page> listOfPages = new List<TenantManagementWebApi.Entities.Page>();
foreach(ListItem item in pages)
listOfPages.Add(new TenantManagementWebApi.Entities.Page() Id = item.Id, Name = item.FieldValues["Title"]+".aspx" );
return listOfPages;
;
[HttpPost]
[Route("api/Page/CreatePageTemplate")]
public async Task<IHttpActionResult> CreatePageTemplate([FromBody]PageTemplateCreationModel model)
if (ModelState.IsValid)
var tenant = await TenantHelper.GetActiveTenant();
var siteCollectionStore = CosmosStoreFactory.CreateForEntity<TenantManagementWebApi.Entities.SiteCollection>();
await siteCollectionStore.RemoveAsync(x => x.Title != string.Empty); // Removes all the entities that match the criteria
string domainUrl = tenant.TestSiteCollectionUrl;
string tenantName = domainUrl.Split('.')[0];
string tenantAdminUrl = tenantName + "-admin.sharepoint.com";
KeyVaultHelper keyVaultHelper = new KeyVaultHelper();
await keyVaultHelper.OnGetAsync(tenant.SecretIdentifier);
using (var context = new OfficeDe***P.Core.AuthenticationManager().GetSharePointOnlineAuthenticatedContextTenant(model.SiteCollectionUrl, tenant.Email, keyVaultHelper.SecretValue))
try
var clientsidepageTemplateStore = CosmosStoreFactory.CreateForEntity<OfficeDe***P.Core.Pages.ClientSidePage>();
var page = OfficeDe***P.Core.Pages.ClientSidePage.Load(context, model.PageName);
if (!ModelState.IsValid)
return BadRequest(ModelState);
var added = await clientsidepageTemplateStore.AddAsync(page);
return StatusCode(HttpStatusCode.NoContent);
//PageTemplate pageTemplate = new PageTemplate();
//pageTemplate.Name = model.Name;
// var page = OfficeDe***P.Core.Pages.ClientSidePage.Load(context, "Home.aspx");
//int sectionOrder = 0;
//foreach (var section in page.Sections)
//
// pageTemplate.Sections.Add(section);
// foreach (var column in section.Columns)
//
// foreach(var webpart in column.Controls)
//
//
//
// sectionOrder++;
//
catch (System.Exception ex)
throw ex;
return BadRequest(ModelState);
get 端点完美运行
【问题讨论】:
'返回状态码(HttpStatusCode.NoContent);'可以写成'return NoContent();'。您是否尝试过使用 postman 之类的东西来访问 webapi?可能会告诉您这是 API 问题还是前端问题 每当你看到你的Route
属性复制RoutePrefix
属性(在api/Page
中),你必须知道你做错了。跨度>
我不懂卡米洛?
【参考方案1】:
如果您想访问CreatePageTemplate
操作,您必须请求以下格式的网址:RoutePrefix
+ Route
。在您的情况下,结果 url 应该是 api/Page
+ api/Page/CreatePageTemplate
= api/Page/api/Page/CreatePageTemplate
。但显然这段代码
adalApiFetch(fetch, "/Page/CreatePageTemplate", options)
请求api/Page/CreatePageTemplate
。所以只需将其更新为以下内容
adalApiFetch(fetch, "/Page/api/Page/CreatePageTemplate", options)
但如果您打算使用原始网址,您应该只更新您的操作
[HttpPost]
[Route("CreatePageTemplate")] //remove api/Page as it is already in RoutePrefix
public async Task<IHttpActionResult> CreatePageTemplate([FromBody]PageTemplateCreationModel model)
【讨论】:
以上是关于自定义 Web api 上的 POST 405(不允许的方法)的主要内容,如果未能解决你的问题,请参考以下文章
从 POSTMAN 到我的 java api 的 POST 上的 405 响应代码