Метод не разрешен при вызове метода DELETE; возможная проблема с маршрутизацией

У меня есть приложение AngularJS, которое взаимодействует с веб-API. Я реализовал методы GET (один и многие), DELETE, POST и PUT. В моем контроллере я указал два маршрута атрибутов для каждого метода, и с тех пор у меня возникли трудности с работой некоторых методов. А именно, в моем методе DELETE я всегда получаю 405 — метод не разрешен. Я почти уверен, что это как-то связано с маршрутизацией, которую я выбрал. Я могу получить ожидаемые результаты, используя оба маршрута для обоих моих методов GET, поэтому, по крайней мере, я знаю h

Мой метод API выглядит так:

[HttpDelete]
[ResponseType(typeof(CustomerFee))]
[Route("~/api/CustomerFees/{id:int}")]
[Route("~/api/Customers/{customerID:int?}/Fees/{id:int}")]
public async Task<IHttpActionResult> DeleteCustomerFee(int id, int? feeID = null)
{
   ...
}

В моем приложении Angular я создал ресурс, который выглядит так:

$resource('http://localhost:62415/api/Customers/:customerID/Fees/:feeID',
{
    customerID: '@customerID',
    feeID: '@feeID'
},
{
    create: { method: 'POST' },
    get: { method: 'GET' },
    query: { method: 'GET', isArray: true },
    remove: { method: 'DELETE' },
    update: { method: 'PUT' }
});

Я подозреваю, что это может иметь какое-то отношение к тому, как я указал аргументы в своем определении ресурса. Мой метод API имеет два аргумента: «id» (feeID) и «customerID». Однако в URL моего ресурса есть :customerID и :feeID. Мой вопрос заключается в том, должны ли эти аргументы совпадать по имени (в данном случае аргумент «feeID» в ресурсе не совпадает с аргументом «id» в API), или они строго обрабатываются по положению, в котором они появиться в URL? Я думаю, что, поскольку метод API имеет аргумент с именем «id» вместо «feeID», строка ниже неверна.

{ customerID: '@customerID', feeID: '@feeID' }

Вместо этого, будет ли любой из них лучше?

{ customerID: '@customerID', feeID: '@id' }

or

{ customerID: '@customerID', id: '@feeID' }

Это может быть неверно предполагать, но использование символа «@», похоже, указывает на то, что это заполнитель, такой как параметры, отправленные в хранимую процедуру, поэтому я думаю, что здесь в основном то же самое, но я могу ошибаться. Документация AngularJS не объясняет этого; их примеры всегда используют одно и то же имя и не упоминают аргументы в методе API, который будет вызывать ресурс.

У меня есть несколько других контроллеров, которые предоставляют такие маршруты, и, возможно, потребуется изменить их, если я делаю это неправильно, потому что я в основном следовал одному и тому же шаблону для каждого. Когда я запускаю свой запрос DELETE, Fiddler говорит в заголовках ответа, что разрешены только операции GET, поэтому явно что-то не так со спецификациями маршрута в API.

Вот мои другие операции:

[HttpGet]
[ResponseType(typeof(CustomerFee))]
[Route("~/api/CustomerFees/{id:int}")]
[Route("~/api/Customers/{customerID:int?}/Fees/{id:int}")]
public async Task<IHttpActionResult> GetCustomerFee(int id, int? customerID = null)
{
    ...
}

[HttpGet]
[Route("~/api/CustomerFees")]
[Route("~/api/Customers/{customerID:int?}/Fees")]
public IQueryable<CustomerFee> GetCustomerFees(int? customerID = null)
{
    ...
}

[HttpPost]
[ResponseType(typeof(CustomerFee))]
[Route("~/api/CustomerFees")]
[Route("~/api/Customers/{customerID:int?}/Fees")]
public async Task<IHttpActionResult> PostCustomerFee(CustomerFee customerFee, int? customerID = null)
{
    ...
}

[HttpPut]
[ResponseType(typeof(void))]
[Route("~/api/CustomerFees/{id:int}")]
[Route("~/api/Customers/{customerID:int?}/Fees/{id:int}")]
public async Task<IHttpActionResult> PutCustomerFee(int id, CustomerFee customerFee, int? customerID = null)
{
    ...
}

Еще один вопрос, который у меня есть, заключается в том, что в моем методе API аргумент «customerID» является необязательным, должен ли второй маршрут включать «{customerID:int?}» или «{customerID:int}»? По сути, если я попытаюсь использовать второй маршрут, но не укажу значение customerID, оно будет иметь значение null, поэтому мне интересно, какая запись верна. Я обеспокоен тем, что он может попытаться использовать маршрут «/api/Customers/Fes/5», когда аргумент «customerID» является необязательным и передается значение null. Этот конкретный маршрут должен быть недействительным.


person DesertFoxAZ    schedule 15.02.2018    source источник


Ответы (2)


Вы пропустили 's' $resource('http://localhost:62415/api/Customer/:customerID/Fees/:feeID'

Я предполагаю, что это должен быть '$resource('http://localhost:62415/api/Customers/:customerID/Fees/:feeID''

person theAnubhav    schedule 15.02.2018
comment
спасибо, @theAnubhav, я неправильно набрал это в своем посте, но в моем коде это правильно. Это не причина проблемы, с которой я сталкиваюсь. Я исправлю эту опечатку в своем посте. - person DesertFoxAZ; 15.02.2018

Теперь я понял, в чем проблема, хотя это не будет ясно в моем описании проблемы, потому что я не упомянул об этом...

Поскольку $resource требует, чтобы «customerID» указывался для каждого запроса (поскольку я использую маршрут, который его ожидает), я получал 405 — метод не разрешен, поскольку был предоставлен только «feeID». Это привело к тому, что запрос перешел к «api/Customers/Fee/6», что является недопустимым маршрутом. Это происходило для всех запросов DELETE, POST и PUT.

person DesertFoxAZ    schedule 15.02.2018
comment
Это идеальный RCA. - person theAnubhav; 16.02.2018