Примечание
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
Часть 1. Данные с кодом формы
В этой статье показано, как отправлять данные form-urlencoded в контроллер веб-API.
Примечание
Обзор HTML-форм
Html-формы используют get или POST для отправки данных на сервер. Атрибут method элемента формы предоставляет метод HTTP:
<form action="api/values" method="post">
По умолчанию используется метод GET. Если форма использует GET, данные формы кодируются в URI в виде строки запроса. Если в форме используется POST, данные формы помещаются в текст запроса. Для данных POSTed атрибут enctype задает формат текста запроса:
enctype | Описание |
---|---|
application/x-www-form-urlencoded | Данные формы кодируются в виде пар "имя-значение", аналогично строке запроса URI. Это формат по умолчанию для POST. |
multipart/form-data | Данные формы кодируются как составное сообщение 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>
Обратите внимание, что атрибут действия в форме является универсальным кодом ресурса (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 автоматически преобразует пары "имя-значение" в экземпляр 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 submit заменяет действие формы новой функцией. Это переопределяет поведение по умолчанию кнопки Отправить. Функция serialize сериализует данные формы в пары "имя-значение". Чтобы отправить данные формы на сервер, вызовите .$.post()
По завершении .success()
запроса обработчик или .error()
выводит пользователю соответствующее сообщение.
Отправка простых типов
В предыдущих разделах мы отправили сложный тип, который веб-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
В частности, часть имени пары "имя-значение" должна быть пустой для простого типа. Не все браузеры поддерживают это для 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"] });