ASP.net Core RC2 Web API POST - Когда использовать Create, CreatedAtAction, vs. CreatedAtRoute?

Каковы основные отличия этих функций? Все, что я знаю, это все три результата в 201, что подходит для успешного запроса POST.

Я только следую примерам, которые я вижу в Интернете, но они действительно не объясняют, почему они делают то, что делают.

Мы должны предоставить имя для нашего GET (1 запись по id):

[HttpGet("{id}", Name="MyStuff")]
public async Task<IActionResult> GetAsync(int id)
{
     return new ObjectResult(new MyStuff(id));
}

Какова цель именования этой функции get, кроме того, что она "вероятно" требуется для функции POST ниже:

[HttpPost]
public async Task<IActionResult> PostAsync([FromBody]MyStuff myStuff)
{
     // actual insertion code left out

     return CreatedAtRoute("MyStuff", new { id = myStuff.Id }, myStuff);
}

Я заметил, что CreatedAtRoute также имеет перегрузку, которая не принимает имя маршрута.

Существует также CreatedAtAction, который принимает аналогичные параметры. Почему этот вариант существует?

Существует также Created, который ожидает URL и объект, который мы хотим вернуть. Могу ли я использовать этот вариант и предоставить фиктивный URL-адрес и вернуть объект, который я хочу, и выполнить его с помощью?

Я не уверен, почему существует так много вариантов, чтобы иметь возможность вернуть 201 клиенту. В большинстве случаев все, что я хочу сделать, - это вернуть уникальный идентификатор приложения (скорее всего из базы данных) или версию моего объекта, имеющего минимальную информацию.

Я думаю, что в итоге ответ 201 должен "создать" заголовок местоположения, у которого есть URL-адрес вновь созданного ресурса, который, я считаю, все 3 и их перегрузки заканчиваются. Почему я должен всегда возвращать заголовок местоположения? Мои клиенты JavaScript, родные мобильные и настольные приложения никогда не используют его. Если я, например, выдаю HTTP POST, чтобы создавать платежные заявления и отправлять их пользователям, каков был бы такой URL-адрес местоположения? (Приношу свои извинения за то, что вы не углубляетесь в историю Интернета, чтобы найти ответ для этого.)

Зачем создавать имена для действий и маршрутов? Какая разница между именами действий и именами маршрутов?

Я запутался в этом, поэтому я прибегал к возврату Ok(), который возвращает 200, что неприемлемо для POST.

Ответы

Ответ 1

Здесь есть несколько разных вопросов, которые, вероятно, должны быть разделены, но я думаю, что это покрывает основную часть ваших проблем.

Зачем создавать имена для действий и маршрутов? Какая разница между именами действий и именами маршрутов?

Прежде всего, действия и маршруты очень разные.

Действие работает на контроллере. Маршрут определяет полную конечную точку, состоящую из контроллера и действия и потенциально дополнительных параметров маршрута.

Вы можете указать имя маршрута, что позволяет вам ссылаться на него в приложении. например

routes.MapRoute(
  name: "MyRouteName",
  url: "SomePrefix/{action}/{id}",
  defaults: new { controller = "Section", action = "Index" }
);

Причины имен действий рассматриваются в этом вопросе: Цель ActionName

Это позволяет вам начинать действие с номера или включать любой символ, который .net не разрешает в идентификаторе. - Наиболее распространенная причина заключается в том, что он позволяет иметь две действия с одной и той же сигнатурой (см. Действия GET/POST Delete любого контроллера леса)

Каковы основные отличия этих функций?

Эти 3 функции выполняют по существу одну и ту же функцию - возвращают ответ 201 Created с заголовком Location, указывающим на url для вновь созданного ответа, и сам объект в теле. URL-адрес должен быть URL-адресом, по которому запрос GET возвращает URL-адрес объекта. Это будет считаться "правильным" поведением в системе RESTful.

Для примера Почтового кода в вашем вопросе вы действительно хотели бы использовать CreatedAtAction.

[HttpPost]
public async Task<IActionResult> PostAsync([FromBody]MyStuff myStuff)
{  
   // actual insertion code left out

   return CreatedAtAction("MyStuff", new { id = myStuff.Id }, myStuff);
}

Предполагая, что вы настроили маршрут по умолчанию, это добавит заголовок Location, указывающий на действие MyStuff на том же контроллере.

Если вы хотите, чтобы URL-адрес местоположения указывал на определенный маршрут (как мы определили ранее, вы можете использовать, например,

[HttpPost]
public async Task<IActionResult> PostAsync([FromBody]MyStuff myStuff)
{  
   // actual insertion code left out

   return CreatedAtRoute("MyRouteName", new { id = myStuff.Id }, myStuff);
}

Могу ли я использовать этот вариант и предоставить фиктивный URL-адрес и вернуть объект, который я хочу, и выполнить его с помощью?

Если вы действительно не хотите использовать CreatedResult, вы можете использовать простой StatusCodeResult, который вернет 201, без заголовка Location.

[HttpPost]
public async Task<IActionResult> PostAsync([FromBody]MyStuff myStuff)
{  
  // actual insertion code left out

  return StatusCode(201);
}