Примечание.
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
Часть 1. Данные form-urlencoded
В этой статье показано, как отправлять данные в формате form-urlencoded в контроллер веб-API.
Замечание
Обзор HTML-форм
ФОРМЫ HTML используют GET или POST для отправки данных на сервер. Атрибут метода элемента формы предоставляет метод HTTP:
<form action="api/values" method="post">
По умолчанию используется метод GET. Если форма использует GET, данные формы кодируются в URI в виде строки запроса. Если форма использует POST, данные формы помещаются в текст запроса. Для данных, отправленных методом POST, атрибут enctype указывает формат тела запроса.
| энктип | Описание |
|---|---|
| application/x-www-form-urlencoded | Данные формы кодируются как пары "имя-значение", аналогичные строке запроса URI. Это формат по умолчанию для POST. |
| многочастная/формат данных | Данные формы кодируются в виде многопартийного сообщения MIME. Используйте этот формат, если вы отправляете файл на сервер. |
Часть 1 этой статьи посвящена формату x-www-form-urlencoded. Часть 2 описывает многопартийный MIME.
Отправка сложных типов
Как правило, вы отправляете сложный тип, состоящий из значений, взятых из нескольких элементов управления формами. Рассмотрим следующую модель, представляющую обновление состояния:
namespace FormEncode.Models
{
using System;
using System.ComponentModel.DataAnnotations;
public class Update
{
[Required]
[MaxLength(140)]
public string Status { get; set; }
public DateTime Date { get; set; }
}
}
Ниже приведен контроллер веб-API, который принимает Update объект через POST.
namespace FormEncode.Controllers
{
using FormEncode.Models;
using System;
using System.Collections.Generic;
using System.Net;
using System.Net.Http;
using System.Web;
using System.Web.Http;
public class UpdatesController : ApiController
{
static readonly Dictionary<Guid, Update> updates = new Dictionary<Guid, Update>();
[HttpPost]
[ActionName("Complex")]
public HttpResponseMessage PostComplex(Update update)
{
if (ModelState.IsValid && update != null)
{
// Convert any HTML markup in the status text.
update.Status = HttpUtility.HtmlEncode(update.Status);
// Assign a new ID.
var id = Guid.NewGuid();
updates[id] = update;
// Create a 201 response.
var response = new HttpResponseMessage(HttpStatusCode.Created)
{
Content = new StringContent(update.Status)
};
response.Headers.Location =
new Uri(Url.Link("DefaultApi", new { action = "status", id = id }));
return response;
}
else
{
return Request.CreateResponse(HttpStatusCode.BadRequest);
}
}
[HttpGet]
public Update Status(Guid id)
{
Update update;
if (updates.TryGetValue(id, out update))
{
return update;
}
else
{
throw new HttpResponseException(HttpStatusCode.NotFound);
}
}
}
}
Замечание
Этот контроллер использует маршрутизацию на основе действий, поэтому шаблон маршрута — api/{controller}/{action}/{id}". Клиент будет публиковать данные в "/api/updates/complex".
Теперь давайте создадим HTML-форму для пользователей, чтобы отправить обновление состояния.
<h1>Complex Type</h1>
<form id="form1" method="post" action="api/updates/complex"
enctype="application/x-www-form-urlencoded">
<div>
<label for="status">Status</label>
</div>
<div>
<input name="status" type="text" />
</div>
<div>
<label for="date">Date</label>
</div>
<div>
<input name="date" type="text" />
</div>
<div>
<input type="submit" value="Submit" />
</div>
</form>
Обратите внимание, что атрибут action в форме — это URI действия контроллера. Вот форма с некоторыми введенными значениями:
Когда пользователь нажимает кнопку "Отправить", браузер отправляет HTTP-запрос, аналогичный следующему:
POST http://localhost:38899/api/updates/complex HTTP/1.1
Accept: text/html, application/xhtml+xml, */*
User-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0)
Content-Type: application/x-www-form-urlencoded
Content-Length: 47
status=Shopping+at+the+mall.&date=6%2F15%2F2012
Обратите внимание, что текст запроса содержит данные формы, отформатированные в виде пар "имя-значение". Веб-API автоматически преобразует пары name/value в экземпляр Update класса.
Отправка данных формы с помощью AJAX
Когда пользователь отправляет форму, браузер переходит с текущей страницы и отображает содержимое ответного сообщения. Это нормально, когда ответ является HTML-страницей. Однако при использовании веб-API текст ответа обычно пуст или содержит структурированные данные, например JSON. В этом случае более целесообразно отправлять данные формы с помощью запроса AJAX, чтобы страница может обрабатывать ответ.
В следующем коде показано, как публиковать данные формы с помощью jQuery.
<script type="text/javascript">
$("#form1").submit(function () {
var jqxhr = $.post('api/updates/complex', $('#form1').serialize())
.success(function () {
var loc = jqxhr.getResponseHeader('Location');
var a = $('<a/>', { href: loc, text: loc });
$('#message').html(a);
})
.error(function () {
$('#message').html("Error posting the update.");
});
return false;
});
</script>
Функция отправки jQuery заменяет действие формы новой функцией. Это переопределяет поведение кнопки "Отправить" по умолчанию. Функция сериализации сериализует данные формы в пары "имя-значение". Чтобы отправить данные формы на сервер, вызовите $.post().
Когда запрос завершится, .success().error() обработчик отображает соответствующее сообщение пользователю.
Отправка простых типов
В предыдущих разделах мы отправили сложный тип, который Web API десериализовал в экземпляр класса модели. Вы также можете отправлять простые типы, например строку.
Замечание
Прежде чем отправлять простой тип, рассмотрите возможность упаковки значения в сложный тип. Это дает преимущества проверки модели на стороне сервера и упрощает расширение модели при необходимости.
Основные шаги для отправки простого типа одинаковы, но есть два тонких различия. Во-первых, в контроллере необходимо декорировать имя параметра атрибутом FromBody.
[HttpPost]
[ActionName("Simple")]
public HttpResponseMessage PostSimple([FromBody] string value)
{
if (value != null)
{
Update update = new Update()
{
Status = HttpUtility.HtmlEncode(value),
Date = DateTime.UtcNow
};
var id = Guid.NewGuid();
updates[id] = update;
var response = new HttpResponseMessage(HttpStatusCode.Created)
{
Content = new StringContent(update.Status)
};
response.Headers.Location =
new Uri(Url.Link("DefaultApi", new { action = "status", id = id }));
return response;
}
else
{
return Request.CreateResponse(HttpStatusCode.BadRequest);
}
По умолчанию веб-API пытается получить простые типы из URI запроса. Атрибут FromBody сообщает веб-API считывать значение из текста запроса.
Замечание
Веб-API считывает текст ответа по крайней мере один раз, поэтому из текста запроса может поступать только один параметр действия. Если необходимо получить несколько значений из текста запроса, определите сложный тип.
Во-вторых, клиенту необходимо отправить значение со следующим форматом:
=value
В частности, часть имени пары name/value должна быть пуста для простого типа. Не все браузеры поддерживают это для форм HTML, но вы создаете этот формат в скрипте следующим образом:
$.post('api/updates/simple', { "": $('#status1').val() });
Ниже приведен пример формы:
<h1>Simple Type</h1>
<form id="form2">
<div>
<label for="status">Status</label>
</div>
<div>
<input id="status1" type="text" />
</div>
<div>
<input type="submit" value="Submit" />
</div>
</form>
Ниже приведен скрипт для отправки значения формы. Единственное отличие от предыдущего скрипта — это аргумент, переданный в функцию post .
$('#form2').submit(function () {
var jqxhr = $.post('api/updates/simple', { "": $('#status1').val() })
.success(function () {
var loc = jqxhr.getResponseHeader('Location');
var a = $('<a/>', { href: loc, text: loc });
$('#message').html(a);
})
.error(function () {
$('#message').html("Error posting the update.");
});
return false;
});
Вы можете использовать тот же подход для отправки массива простых типов:
$.post('api/updates/postlist', { "": ["update one", "update two", "update three"] });