为什么我的Post方法被禁止?

时间:2014-02-04 22:57:37

标签: c# post json.net asp.net-web-api-routing http-status-code-405

我已成功使用此方法来获取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)方法不允许。

为什么不允许?

更新

根据我在此处找到的内容: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
}

......现在它有效。

1 个答案:

答案 0 :(得分: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);

        }
    }
}