Я попытался изменить один из моих контроллеров api, чтобы разрешить создание нескольких резервирований, разрешив передавать один из параметров в виде строки с ограничением на канал. Метод и класс можно увидеть здесь:
public class ReservationsController : ApiController
{
public HttpResponseMessage PostReservation(string eRaiderUserName, string SpaceNumbers)
{
char[] delimiter = { '|' };
string[] spaces = SpaceNumbers.Split(delimiter);
bool saved = true;
foreach(string space in spaces)
{
var reservation = new Reservation { eRaiderUserName=eRaiderUserName, SpaceNumber=Convert.ToInt32(space) };
if (true)
{
reservation.Game = db.Games.FirstOrDefault(g => g.ID == AppSettings.CurrentGameID);
db.Reservations.Add(reservation);
db.SaveChanges();
//HttpResponseMessage response = Request.CreateResponse(HttpStatusCode.Created, reservation);
//response.Headers.Location = new Uri(Url.Link("DefaultApi", new { id = reservation.ID }));
//return response;
}
else
{
saved = false;
//return Request.CreateErrorResponse(HttpStatusCode.BadRequest, ModelState);
}
}
db.SaveChanges();
if (saved)
{
HttpResponseMessage response = Request.CreateResponse(HttpStatusCode.Created);
response.Headers.Location = new Uri(Url.Link("DefaultApi", new { id = 1 }));
return response;
} else
{
return Request.CreateErrorResponse(HttpStatusCode.BadRequest, ModelState);
}
}
}
У меня есть форма, в которой указано, что я думаю, должна быть правильная информация, но я продолжаю получать эту ошибку:
{"$id":"1","Message":"No HTTP resource was found that matches the request URI 'http://localhost:58463/api/Reservations'.","MessageDetail":"No action was found on the controller 'Reservations' that matches the request."}
Метод (измененный) сохранения в api все еще определенно работает. Но что удерживает это от поиска контроллера веб-api? Вот вывод Firebug:
Как отмечалось, проблема заключается в том, что действие POST может передавать только данные, отправленные в теле одному объекту (по техническим причинам).
Это означает, что вы можете получать данные из данных маршрута, из строки запроса и из тела, со следующими ограничениями:
Таким образом, наиболее общий способ решения вашей проблемы (т.е. Который может быть легко применен к другим классам, где вам необходимо передать сложные данные, даже более сложные, чем этот случай):
Сначала создайте класс, который обладает свойствами для всех необходимых данных, в вашем случае:
public class ReservationData
{
public string eRaiderUserName { get; set; }
public string SpaceNumbers { get; set; }
}
Во-вторых, используйте этот класс как тип полученного параметра в вашем действии:
public HttpResponseMessage PostReservation(ReservationData reservationData)
С помощью этого кода форматер может сопоставить все данные в теле запроса с одним параметром в действии. Вы можете использовать форматы JSON или formdata, например, сгенерированные jQuery.
ПРИМЕЧАНИЕ. Имена свойств должны иметь случайное соответствие имени опубликованных параметров.
Веб-API имеет ограниченную поддержку для сопоставления переменных формы POST с простыми параметрами метода Web API. Веб-API не имеет дело с несколькими значениями размещенного контента, вы можете отправлять только одно значение содержимого методу действия веб-API.
public HttpResponseMessage PostReservation(string eRaiderUserName, string SpaceNumbers)
{//...}
и вы пытаетесь вызвать с помощью jQuery:
$.ajax({ url: 'api/reservations', type: 'POST', data: { ... }, dataType: 'json', success: function (data) {alert(data);} });
К сожалению, веб-API не справляется с этим запросом, и вы получите ошибку. Но если вы передаете параметры с помощью строки запроса, Itll работает:
$.ajax({url: 'api/reservations? eRaiderUserName = 2012 & SpaceNumbers = test', type: 'POST', dataType: 'json', success: function (data) {alert (data);}});
Но это нехорошее решение и неприменимо для сложных объектов. Итак, вот несколько способов сделать это.
Это связано с тем, что вы отправляете x-www-form-urlencoded данные в контроллер, для обработки этих данных вы должны использовать [FromBody] перед параметром, например
public HttpResponseMessage Post([FromBody] string name) { ... }
но этот подход имеет большое ограничение: 1) Может быть только один параметр, помеченный атрибутом [FromBody] (он может быть сложным типом) 2) Данные должны быть закодированы как = значение не как key = value. Вы можете прочитать его здесь описание и как заставить его работать здесь пример. Если это возможно, я рекомендую вам отправлять данные Json на контроллер без этих ограничений.
Post
?