Asp net send html

Отправка данных html-формы в веб-API ASP.NET: данные с кодом формы

В этой статье показано, как отправлять данные form-urlencoded в контроллер веб-API.

Обзор HTML-форм

Html-формы используют get или POST для отправки данных на сервер. Атрибут method элемента формы предоставляет метод HTTP:

По умолчанию используется метод 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 Dictionaryupdates = new Dictionary(); [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 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", >)); 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///. Клиент будет отправлять данные в «/api/updates/complex».

Читайте также:  Promo html and css

Теперь давайте напишем HTML-форму, чтобы пользователи отправили обновление состояния.

Complex Type

Обратите внимание, что атрибут действия в форме является универсальным кодом ресурса (URI) действия контроллера. Ниже приведена форма с некоторыми значениями, введенными в:

Снимок экрана: форма сложного типа H T M L с полем

Когда пользователь нажимает кнопку Отправить, браузер отправляет 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.

  

Функция jQuery submit заменяет действие формы новой функцией. Это переопределяет поведение по умолчанию кнопки Отправить. Функция serialize сериализует данные формы в пары «имя-значение». Чтобы отправить данные формы на сервер, вызовите . $.post()

По завершении .success() запроса обработчик или .error() выводит пользователю соответствующее сообщение.

Снимок экрана: форма сложного типа H T M L с ошибкой локального узла, отображаемой для пользователя полужирным шрифтом.

Отправка простых типов

В предыдущих разделах мы отправили сложный тип, который веб-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 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", >)); return response; > else

По умолчанию веб-API пытается получить простые типы из URI запроса. Атрибут FromBody сообщает веб-API, что нужно считывать значение из текста запроса.

Веб-API считывает текст ответа не более одного раза, поэтому только один параметр действия может поступать из текста запроса. Если необходимо получить несколько значений из текста запроса, определите сложный тип.

Во-вторых, клиенту необходимо отправить значение в следующем формате:

В частности, часть имени пары «имя-значение» должна быть пустой для простого типа. Не все браузеры поддерживают это для HTML-форм, но этот формат создается в скрипте следующим образом:

Ниже приведен пример формы:

Ниже приведен скрипт для отправки значения формы. Единственное отличие от предыдущего сценария заключается в том, что аргумент передается в функцию post .

$('#form2').submit(function () < var jqxhr = $.post('api/updates/simple', < "": $('#status1').val() >) .success(function () < var loc = jqxhr.getResponseHeader('Location'); var a = $('', < href: loc, text: loc >); $('#message').html(a); >) .error(function () < $('#message').html("Error posting the update."); >); return false; >); 

Для отправки массива простых типов можно использовать тот же подход:

Источник

Sending HTML Form Data in ASP.NET Web API: File Upload and Multipart MIME

This tutorial shows how to upload files to a web API. It also describes how to process multipart MIME data.

Here is an example of an HTML form for uploading a file:

 

Screenshot of an HTML form showing a Image Caption field with the text Summer Vacation and an Image File file picker.

This form contains a text input control and a file input control. When a form contains a file input control, the enctype attribute should always be «multipart/form-data», which specifies that the form will be sent as a multipart MIME message.

The format of a multipart MIME message is easiest to understand by looking at an example request:

POST http://localhost:50460/api/values/1 HTTP/1.1 User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:12.0) Gecko/20100101 Firefox/12.0 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 Accept-Language: en-us,en;q=0.5 Accept-Encoding: gzip, deflate Content-Type: multipart/form-data; boundary=---------------------------41184676334 Content-Length: 29278 -----------------------------41184676334 Content-Disposition: form-data; name="caption" Summer vacation -----------------------------41184676334 Content-Disposition: form-data; name="image1"; filename="GrandCanyon.jpg" Content-Type: image/jpeg (Binary data not shown) -----------------------------41184676334-- 

This message is divided into two parts, one for each form control. Part boundaries are indicated by the lines that start with dashes.

The part boundary includes a random component («41184676334») to ensure that the boundary string does not accidentally appear inside a message part.

Each message part contains one or more headers, followed by the part contents.

  • The Content-Disposition header includes the name of the control. For files, it also contains the file name.
  • The Content-Type header describes the data in the part. If this header is omitted, the default is text/plain.

In the previous example, the user uploaded a file named GrandCanyon.jpg, with content type image/jpeg; and the value of the text input was «Summer Vacation».

File Upload

Now let’s look at a Web API controller that reads files from a multipart MIME message. The controller will read the files asynchronously. Web API supports asynchronous actions using the task-based programming model. First, here is the code if you are targeting .NET Framework 4.5, which supports the async and await keywords.

using System.Diagnostics; using System.Net; using System.Net.Http; using System.Threading.Tasks; using System.Web; using System.Web.Http; public class UploadController : ApiController < public async TaskPostFormData() < // Check if the request contains multipart/form-data. if (!Request.Content.IsMimeMultipartContent()) < throw new HttpResponseException(HttpStatusCode.UnsupportedMediaType); >string root = HttpContext.Current.Server.MapPath("~/App_Data"); var provider = new MultipartFormDataStreamProvider(root); try < // Read the form data. await Request.Content.ReadAsMultipartAsync(provider); // This illustrates how to get the file names. foreach (MultipartFileData file in provider.FileData) < Trace.WriteLine(file.Headers.ContentDisposition.FileName); Trace.WriteLine("Server file path: " + file.LocalFileName); >return Request.CreateResponse(HttpStatusCode.OK); > catch (System.Exception e) < return Request.CreateErrorResponse(HttpStatusCode.InternalServerError, e); >> > 

Notice that the controller action does not take any parameters. That’s because we process the request body inside the action, without invoking a media-type formatter.

The IsMultipartContent method checks whether the request contains a multipart MIME message. If not, the controller returns HTTP status code 415 (Unsupported Media Type).

The MultipartFormDataStreamProvider class is a helper object that allocates file streams for uploaded files. To read the multipart MIME message, call the ReadAsMultipartAsync method. This method extracts all of the message parts and writes them into the streams provided by the MultipartFormDataStreamProvider.

When the method completes, you can get information about the files from the FileData property, which is a collection of MultipartFileData objects.

  • MultipartFileData.FileName is the local file name on the server, where the file was saved.
  • MultipartFileData.Headers contains the part header (not the request header). You can use this to access the Content_Disposition and Content-Type headers.

As the name suggests, ReadAsMultipartAsync is an asynchronous method. To perform work after the method completes, use a continuation task (.NET 4.0) or the await keyword (.NET 4.5).

Here is the .NET Framework 4.0 version of the previous code:

public Task PostFormData() < // Check if the request contains multipart/form-data. if (!Request.Content.IsMimeMultipartContent()) < throw new HttpResponseException(HttpStatusCode.UnsupportedMediaType); >string root = HttpContext.Current.Server.MapPath("~/App_Data"); var provider = new MultipartFormDataStreamProvider(root); // Read the form data and return an async task. var task = Request.Content.ReadAsMultipartAsync(provider). ContinueWith(t => < if (t.IsFaulted || t.IsCanceled) < Request.CreateErrorResponse(HttpStatusCode.InternalServerError, t.Exception); >// This illustrates how to get the file names. foreach (MultipartFileData file in provider.FileData) < Trace.WriteLine(file.Headers.ContentDisposition.FileName); Trace.WriteLine("Server file path: " + file.LocalFileName); >return Request.CreateResponse(HttpStatusCode.OK); >); return task; > 

Reading Form Control Data

The HTML form that I showed earlier had a text input control.

You can get the value of the control from the FormData property of the MultipartFormDataStreamProvider.

public async Task PostFormData() < if (!Request.Content.IsMimeMultipartContent()) < throw new HttpResponseException(HttpStatusCode.UnsupportedMediaType); >string root = HttpContext.Current.Server.MapPath("~/App_Data"); var provider = new MultipartFormDataStreamProvider(root); try < await Request.Content.ReadAsMultipartAsync(provider); // Show all the key-value pairs. foreach (var key in provider.FormData.AllKeys) < foreach (var val in provider.FormData.GetValues(key)) < Trace.WriteLine(string.Format(": ", key, val)); > > return Request.CreateResponse(HttpStatusCode.OK); > catch (System.Exception e) < return Request.CreateErrorResponse(HttpStatusCode.InternalServerError, e); >> 

FormData is a NameValueCollection that contains name/value pairs for the form controls. The collection can contain duplicate keys. Consider this form:

 
Round-Trip
One-Way
Only show non-stop flights
Compare nearby airports
My travel dates are flexible

Screenshot of the HTML form with the Round-Trip circle filled in and the Only show non-stop flights and My travel dates are flexible boxes checked.

The request body might look like this:

-----------------------------7dc1d13623304d6 Content-Disposition: form-data; name="trip" round-trip -----------------------------7dc1d13623304d6 Content-Disposition: form-data; name="options" nonstop -----------------------------7dc1d13623304d6 Content-Disposition: form-data; name="options" dates -----------------------------7dc1d13623304d6 Content-Disposition: form-data; name="seat" window -----------------------------7dc1d13623304d6-- 

In that case, the FormData collection would contain the following key/value pairs:

Источник

Оцените статью