为啥不允许我的 Post 方法?

Posted

技术标签:

【中文标题】为啥不允许我的 Post 方法?【英文标题】:Why is my Post method disallowed?为什么不允许我的 Post 方法? 【发布时间】:2014-03-01 04:19:46 【问题描述】:

我已经成功使用这个方法来获取 REST 数据了:

private JArray GetRESTData(string uri)

    try
    
        var webRequest = (HttpWebRequest)WebRequest.Create(uri);
        var webResponse = (HttpWebResponse)webRequest.GetResponse();
        var reader = new StreamReader(webResponse.GetResponseStream());
        string s = reader.ReadToEnd();
        return JsonConvert.DeserializeObject<JArray>(s);
    
    catch // This method crashes if only one json "record" is found - try this:
    
        try
        
            MessageBox.Show(GetScalarVal(uri));
        
        catch (Exception ex)
        
            MessageBox.Show(ex.Message);
        
    
    return null;

在 webRequest 和 webResponse 分配之间,我添加了这个:

if (uri.Contains("Post"))

    webRequest.Method = "POST";

...并用这个 URI 调用它:

http://localhost:28642/api/Departments/PostDepartment/42/76TrombonesLedTheZeppelin

虽然我有一个与之对应的 Post 方法:

控制器

[Route("api/Departments/PostDepartment/accountid/name/dbContext=03")]
public void PostDepartment(string accountid, string name, string dbContext)

    _deptsRepository.PostDepartment(accountid, name, dbContext);

存储库

public Department PostDepartment(string accountid, string name, string dbContext)

    int maxId = departments.Max(d => d.Id);
    // Add to the in-memory generic list:
    var dept = new Department Id = maxId + 1, AccountId = accountid, Name = name;
    departments.Add(dept);
    // Add to the "database":
    AddRecordToMSAccess(dept.AccountId, dept.Name, dbContext);
    return dept;

...失败,“远程服务器返回错误:(405) Method Not Allowed.

为什么不允许?

更新

根据我在此处找到的内容:http://blog.codelab.co.nz/2013/04/29/405-method-not-allowed-using-asp-net-web-api/,我将其添加到 Web.Config:

  <validation validateIntegratedModeConfiguration="false" />
    <modules runAllManagedModulesForAllRequests="true">
      <remove name="WebDAVModule" />
    </modules>
    <handlers>
      <remove name="WebDAV" />
      <remove name="ExtensionlessUrlHandler-Integrated-4.0" />
      <add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="GET,HEAD,POST,DEBUG,PUT" 
type="System.Web.Handlers.TransferRequestHandler" resourceType="Unspecified" requireAccess="Script" 
preCondition="integratedMode,runtimeVersionv4.0" />
    </handlers>

...所以它是从这个开始的:

<system.webServer>
    <handlers>
      <remove name="ExtensionlessUrlHandler-Integrated-4.0" />
      <remove name="OPTIONSVerbHandler" />
      <remove name="TRACEVerbHandler" />
      <add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="*" 
type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />
    </handlers>
  </system.webServer></configuration>

...到这个:

<system.webServer>
    <validation validateIntegratedModeConfiguration="false" />
    <modules runAllManagedModulesForAllRequests="true">
      <remove name="WebDAVModule" />
    </modules>
    <handlers>
      <remove name="WebDAV" />
      <remove name="ExtensionlessUrlHandler-Integrated-4.0" />
      <remove name="OPTIONSVerbHandler" />
      <remove name="TRACEVerbHandler" />
      <add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="GET,HEAD,POST,DEBUG,PUT" 
type="System.Web.Handlers.TransferRequestHandler" resourceType="Unspecified" requireAccess="Script" 
preCondition="integratedMode,runtimeVersionv4.0" />
    </handlers>
</system.webServer></configuration>

....但没有区别。

更新 2

它甚至无法在 Controller 中调用:

        [HttpPost]
[System.Web.Http.Route("api/Departments/PostDepartment/accountid/name/dbContext=03")]
        public void PostDepartment(string accountid, string name, string dbContext)
        
            _deptsRepository.PostDepartment(accountid, name, dbContext);
        

我有一个没有到达的断点...???

更新 3

VirtualBlackFox 的最后一条评论成功了。我只是改变了我的“这是一个帖子吗?”在我的客户端代码中如下:

if (uri.Contains("Post"))

    webRequest.Method = "POST";
    webRequest.ContentLength = 0; // <-- This line is all I added

...现在它可以工作了。

【问题讨论】:

您可能需要在您的web.config 中允许它,或者在api 方法允许POST 中添加一个属性。不过我只使用过 WCF,所以不能肯定。 @CodeCaster:这就是为什么我添加了查找“Post”的逻辑——因为我想使用这种新型方法(到目前为止,它们都是“GET”。跨度> 其他 POST 方法是否有效,或者在其他请求时是否有效,例如通过 jQuery?您是否尝试过“web api 405”的众多结果? @CodeCaster:由于 CORS 问题,我的 jQuery 测试还没有开始工作 (***.com/questions/21561121/…) 【参考方案1】:

我不使用 Asp.Net,但我猜您需要指定 HttpPost 属性,如 Attribute Routing / HTTP Methods 文档中所示:

[HttpPost]
[Route("api/Departments/PostDepartment/accountid/name/dbContext=03")]
public void PostDepartment(string accountid, string name, string dbContext)

    _deptsRepository.PostDepartment(accountid, name, dbContext);


在我的电脑上工作的小样本:

TestController.cs:

using System.Web.Http;

namespace WebApplication2.Controllers

    public class TestController : ApiController
    
        [HttpPost]
        [Route("api/Departments/PostDepartment/accountid/name/dbContext=03")]
        public string PostDepartment(string accountid, string name, string dbContext)
        
            return accountid + name + dbContext;
        
    

Test.html

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <script src="http://ajax.aspnetcdn.com/ajax/jQuery/jquery-2.0.3.min.js"></script>
    <script>
        $(function () 
            $.ajax("api/Departments/PostDepartment/accountid/name/dbContext", 
                type: 'POST', success: function (data) 
                    $('#dest').text(data);
                
            );
        );
    </script>
</head>
<body>
    <div id="dest"></div>
</body>
</html>

用 C# 调用服务的示例程序:

namespace ConsoleApplication1

    using System;
    using System.IO;
    using System.Net;
    using Newtonsoft.Json;

    class Program
    
        static void Main()
        
            Console.WriteLine(GetRestData(@"http://localhost:52833//api/Departments/PostDepartment/42/76TrombonesLedTheZeppelin"));
            Console.ReadLine();
        

        private static dynamic GetRestData(string uri)
        

            var webRequest = (HttpWebRequest)WebRequest.Create(uri);
            webRequest.Method = "POST";
            webRequest.ContentLength = 0;
            var webResponse = (HttpWebResponse)webRequest.GetResponse();
            var reader = new StreamReader(webResponse.GetResponseStream());
            string s = reader.ReadToEnd();
            return JsonConvert.DeserializeObject<dynamic>(s);

        
    

【讨论】:

我刚试过;但是,当添加它时,它会迫使您在两种不同风格的 HttpPost 之间进行选择。第一个没有任何区别,第二个不会编译。有一个“通用”选项,然后还有一个 System.Web.MVC 选项。现在它不会让我使用任何一个(System.Web.Http 是另一个)。 后来:删除“system.web.mvc”使用允许我使用第一个(System.Web.Http)。尽管如此,它仍然没有区别(它应该在 Controller 中装饰方法,对吧?)。 是的,它在控制器上运行。我创建了一个小的最小示例,创建了一个新的 Asp.Net 项目,只检查了 WebApi 并添加了一个控制器和一个小 html 文件(参见答案中的代码)。它可以正常工作并按预期显示“accountidnamedbContext” 有趣;不过,目前走 jQuery 路线对我不起作用,因为我有未解决的 CORS 问题 (***.com/questions/21561121/…) 我添加了一个适合我的小示例程序(与您问题中的相同,只是我添加了webRequest.ContentLength = 0 以避免***.com/questions/5915131/…

以上是关于为啥不允许我的 Post 方法?的主要内容,如果未能解决你的问题,请参考以下文章

不带 URL 参数的 POST:405(不允许方法)

为啥在 Laravel 中保存数据时出现方法不允许错误?

为啥不允许方法?

错误 405:不允许的方法

不允许的方法(POST):/

Zend_Http_Client - 为啥我的 POST 请求发送错误的内容类型标头?