方法不允许 405 POST ASP.NET CORE 5.0 WEB API

问题描述

我正在同时运行两个项目,在我的 mvc 项目上,当我调用 PaymentServiceAsync() 方法时,当它到达 response.EnsureSuccessstatusCode() 行时,变量 response 表示 方法不允许 (405) 如果我正确设置了它,我似乎无法弄清楚为什么会这样做。

这是我的 PaymentServiceAsync() 方法

        public async Task<string> PaymentServiceAsync()
        {
            var response = await _httpClient.GetAsync("api/paymentservices/payment");

            response.EnsureSuccessstatusCode();

            var result = await response.Content.ReadAsstringAsync();

            return result;
        }

现在在我的 asp.net core web api 项目中,这是我调用的控制器:

using Microsoft.AspNetCore.Mvc;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using nest;
using Microsoft.Extensions.Configuration;
using System.Data.sqlClient;
using PaymentService.API.Models;
using Microsoft.Extensions.Logging;

namespace PaymentService.API.Controllers
{
    [Route("api/[controller]")]
    [ApiController]
    public class PaymentServicesController : ControllerBase
    {
        private String _connectionString;
        private IElasticclient _elasticclient = new Elasticclient();
        private readonly ILogger<PaymentServicesController> _logger;

        public PaymentServicesController(IConfiguration configuration,ILogger<PaymentServicesController> logger)
        {
            _connectionString = configuration.GetConnectionString("Default");
            _logger = logger;
        }


        // POST api/<PaymentServices>
        [HttpPost]
        [Route("payment")]
        public async Task<int> Post([FromBody] string value)
        {
            _logger.Loginformation("Payment method involked!");
            using (sqlConnection connection = new sqlConnection(_connectionString))
            {
                Console.WriteLine("\nopening connection...");

                sqlCommand command = new sqlCommand("insert into applog(ElkLog_id,CorrelationId,DateCreated,MessageTemplate,Message) values(@elk_id,@cid,@dt,@mt,@m)",connection);

                string indexName = "customer-simulation-es-app-logs*";
                var connectionSettings = new ConnectionSettings(new Uri("http://localhost:9200"));
                connectionSettings.DefaultIndex(indexName);
                connectionSettings.EnableDebugMode();
                _elasticclient = new Elasticclient(connectionSettings);


                // this will tell us how much hits/results there is based on the following criteria 
                var countResponse = _elasticclient.Count<EsSource>(c => c
                     .Query(q => q
                         .Bool(b => b
                             .Should(
                                   m => m
                                   .Match(ma => ma
                                       .Field(fa => fa.level)
                                       .Query("Error")),m => m
                                   .Match(ma => ma
                                       .Field(fa => fa.level)
                                       .Query("information")))
                             .Filter(f => f.Daterange(dr => dr
                             .Field("@timestamp")
                                 .GreaterThanorEquals("2021-06-18T16:34:45.701-05:00")
                                 .LessthanorEquals("2021-07-18T16:34:45.701-05:00")))
                             .MinimumShouldMatch(1)))).Count;


                Console.WriteLine($"\nDocuments in index: {countResponse}");

                Console.WriteLine($"Open new pit");
                var openPit = await _elasticclient.OpenPointInTimeAsync(indexName,d => d.KeepAlive("1m"));
                var pit = openPit.Id;

                Console.WriteLine($"Read all docs from index ..");
                // we will start reading docs from the beginning
                var searchAfter = DateTimeOffset.MinValue;


                var elkLogId = "";
                var correlationId = "";
                var dateCreated = default(DateTimeOffset);
                var messageTemplate = "";
                var message = "";
                int numrows = 0;

                try
                {
                    connection.open();

                    Console.WriteLine("\nConnection successful!");

                    while (true)
                    {
                        ........

                       

                        numrows = await command.ExecuteNonQueryAsync();

                        

                        command.Parameters.Clear();

                        

                    }

                    Console.WriteLine("\nAll logs have been recorded to the database successfully!");

                    connection.Close();
                    Console.WriteLine("\nConnection closed....");
                }
                catch (Exception ex)
                {
                    Console.WriteLine(ex.Message);
                }
                finally
                {
                    Console.WriteLine($"Close pit");
                    var closePit = await _elasticclient.ClosePointInTimeAsync(d => d.Id(pit));
                }

                return numrows;
            }
        }

       
    }
}

appsettings.json

{
  "ConnectionStrings": {
    "Default": "Data Source=.\\sqlExpress;Database=ElasticSearchService;Trusted_Connection=True;"
  },"Logging": {
    "LogLevel": {
      "Default": "information","Microsoft": "Warning","Microsoft.Hosting.Lifetime": "information"
    }
  },"AllowedHosts": "*"
}

解决方法

您尝试在代码中尝试“获取”动词操作,而不是“发布”方法。

var 响应 = 等待 _httpClient.GetAsync("api/paymentservices/payment");

根据您的要求,这些是与付款相关的代码,如果您真的考虑安全性,请使用 POST 方法而不是 GET。

这里我们通过构造函数依赖注入创建了"IServiceProvider"(ASP.NET Core 提供了一个内置的服务容器,IServiceProvider。)实例"_serviceProvider"。这是如何在 ASP.NET Core 应用程序中调用 POST 方法的示例之一。

在 ASP.Net Core 应用程序中使用 IHttpClientFactory 而不是 HttpClient,在启用 DI 的应用程序中使用 IHttpClientFactory 避免:

  • 通过池化 HttpMessageHandler 实例解决资源耗尽问题。
  • 定期循环 HttpMessageHandler 实例导致过时的 DNS 问题 间隔。

试试这个:

using (var scope = _serviceProvider.CreateScope())
        {
            var clientFactory = (IHttpClientFactory)scope.ServiceProvider
             .GetService(typeof(IHttpClientFactory));
            var client = clientFactory.CreateClient();
            //PaymentObject
            string jsonData = JsonConvert.SerializeObject(paymentObject);
            var httpContent = new StringContent(jsonData,Encoding.UTF8,"application/json");
            client.BaseAddress = new Uri("http://localhost:3978/");
            var response = await client.PostAsync("api/paymentservices/payment",httpContent);
       }

参考:

  1. IHttpClientFactory Docs
,

由于您使用的是 get 请求,因此请从 api 中删除 [post]

[Route("~api/paymentservices/payment/{value}")]
 public async Task<int> Post(string value)

并修复请求

//--init http client with base url

var baseUri= @"http:...";
    
    using HttpClient client = new HttpClient { BaseAddress = new Uri(baseUri) };
client.DefaultRequestHeaders.Accept.Clear();
    client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
.....
string value="test"; //replace with your value

var response = await client.GetAsync("api/paymentservices/payment/"+value);

if (response.IsSuccessStatusCode)
{
.....
}

或者你也可以尝试 post 方法,在这种情况下尝试使用 action

[Route("~api/paymentservices/payment")]
 public async Task<int> Post(string value)

和代码

var baseUri= @"http:....";
    
    using HttpClient client = new HttpClient { BaseAddress = new Uri(baseUri) };
    client.DefaultRequestHeaders.Accept.Clear();
    client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));

    string value="test"; //replace with your value

    Dictionary<string,string> packet = new Dictionary<string,string>();
    packet.Add("value",value);
    

    var content = new StringContent(JsonConvert.SerializeObject(packet),UTF8Encoding.UTF8,"application/json");

    
    var response = await client.PostAsync("api/paymentservices/payment",content);
    
    if (response.IsSuccessStatusCode)
    {
        var stringData = await response.Content.ReadAsStringAsync();
        .....
    }