Использование ASP.NET Web API в приложении Web Forms

Одно из самых востребованных улучшений для приложений ASP.NET Web Forms, это возможность использования Web API. То, чего так не хватало в предыдущих версиях платформы. Приходилось реализовывать подобное самому с использованием обработчиков HTTP-данных и веб-служб. Не то чтобы это сложно, но надо было писать рутинный код самому. А сейчас это стало намного проще и удобнее. Всё это уже есть, нужно только использовать. Попробую продемонстрировать на простейшем примере, как всё просто. Нужно только это знать, ведь есть разработчики которые даже не знают об этом. Данная возможность доступна также и в Visual Studio 2010 SP1, так как сама библиотека доступна через NuGet. Просто придётся прописывать и подключать некоторые вещи вручную. И так создадим пустое приложение ASP.NET Web Forms для наглядности.
 


Добавим глобальный класс приложения.
 


Библиотеку jQuery через NuGet, так как именно она будет вызывать методы контроллера с помощью AJAX.
 


И пустую веб-форму.

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="WebForm.aspx.cs"
  Inherits="TestWebApi.WebForm" %>

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head id="Head1" runat="server">
  <title></title>
  <script src="<%=Page.ResolveUrl("~/Scripts/jquery-1.8.3.js")%>" 
    type="text/javascript"></script>
</head>
<body>
  <form id="form1" runat="server">
    <div>
   
    </div>
  </form>
</body>
</html>

Для подключения маршрутизации нужно просто добавить ссылку на сборку System.Web.Routing в проект, чтобы  иметь возможность регистрировать маршруты. Модуль маршрутизации по умолчантю уже включён в конвейер, поэтому отдельно прописывать его в web.config не нужно.
 


Определим дефолтовый маршрут, например так:

namespace TestWebApi
{
  public class Global : System.Web.HttpApplication
  {
    protected void Application_Start(object sender, EventArgs e)
    {
      RegisterRoutes(RouteTable.Routes);
    }
    public static void RegisterRoutes(RouteCollection routes)
    {
      routes.MapPageRoute("Default", "WebForm/{id}", "~/WebForm.aspx");
    }
  }
}

Теперь нужно подключить сборки Web API к своему проекту. Для этого нужно их установить через NuGet.
 


После установки всех пакетов, при установке одного на самом деле установится несколько, будем иметь следующее.
 


Нужно прописать маршрут, который будет отвечать вызовам Web API. Пропишем его:

using System;
using System.Web.Http;
using System.Web.Routing;

namespace TestWebApi
{
  public class Global : System.Web.HttpApplication
  {
    protected void Application_Start(object sender, EventArgs e)
    {
      RegisterRoutes(RouteTable.Routes);
    }
    public static void RegisterRoutes(RouteCollection routes)
    {
      routes.MapHttpRoute(name: "DefaultApi", routeTemplate: "api/{controller}/{id}",
        defaults: new { id = System.Web.Http.RouteParameter.Optional });
      routes.MapPageRoute("Default", "WebForm/{id}", "~/WebForm.aspx");
    }
  }
}

Как и в случае с приложением ASP.NET MVC за регистрацию маршрута отвечает метод расширения, только немножко другой. Метод MapHttpRout, который находится в сборке System.Web.Http.WebHost.dll, регистрирует маршрут с обработчиком HttpMessageHandler. Далее добавим контроллер.
 


Немножко дополним код созданный по умолчанию, изменив метод Get( ).

using System.Web.Http;
using System.Collections.Generic;

namespace TestWebApi
{
  public class ValuesController : ApiController
  {
    // GET api/<controller>    
    public IEnumerable<MyClass> Get()
    {
      MyClass[] resultData = new MyClass[]         
      {
        new MyClass { Id = 1, Name = "Text 1" }, 
        new MyClass { Id = 2, Name = "Text 2" }, 
        new MyClass { Id = 3, Name = "Text 3" },
        new MyClass { Id = 4, Name = "Text 4" },
        new MyClass { Id = 5, Name = "Text 5" }         
      };
      return resultData;
    }
    // GET api/<controller>/5
    public string Get(int id)
    {
      return "value";
    }
    // POST api/<controller>   
    public void Post([FromBody]string value)
    {
    }
    // PUT api/<controller>/5
    public void Put(int id, [FromBody]string value)
    {
    }
    // DELETE api/<controller>/5    
    public void Delete(int id)
    {
    }
  }
}

Сам класс MyClass очень простой, как можно догадаться.

namespace TestWebApi
{
  public class MyClass
  {
    public int Id { get; set; }
    public string Name { get; set; }
  }
}

 Добавим код в нашу веб-форму.

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="WebForm.aspx.cs"
  Inherits="TestWebApi.WebForm" %>

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head id="Head1" runat="server">
  <title></title>
  <script src="<%=Page.ResolveUrl("~/Scripts/jquery-1.8.3.js")%>" 
    type="text/javascript"></script>
</head>
<body>
  <form id="form1" runat="server">
    <div>
      <span>Список полученных данных</span>
      <ul id="TestList"></ul>
      <input type="button" id="LoadData" value="Загрузить данные" />
    </div>
  </form>
  <script type="text/javascript">
    $(document).ready(function () {
      $("#LoadData").click(function () {
        $.getJSON("<%=Page.ResolveUrl("~/api/Values")%>",
          function (data) {
            var html = "";
            $.each(data, function (key, value) {
              var html = html + "<li>" + value.Name + "</li>";
              $(html).appendTo("#TestList");
            });
          });
      });
    });
  </script>
</body>
</html>

Запускаем приложение
 


и видим, что всё работает. А вот и сам готовый проект.
Станислав
25.01.2013 10:50
Код читать невозможно....
25.01.2013 11:25
Спасибо, исправил.
26.01.2013 13:59
Выложил код проекта, по просьбе некоторых пользователей. Хотя воспроизвести высшеперечислен­ное очень легко.
Андрей
18.02.2013 19:02
То, что Вы написали, ничего не понятно. Вы видимо программист профи?
18.02.2013 20:14
Думаю, проще уже некуда...Если, что-то непонятно, то можете спросить на форумах MSDN.
Andrey
11.03.2013 10:51
Сколько я смотрю на этот WebAPI, тем больше не могу понять - в чем его отличие от обычного базового контроллера, особенно в описанном вами примере? Я понимаю, что здесь рассказ про Web Forms, но что мешает нам возвращать JSON в ASP.NET MVC из простого контроллера?
11.03.2013 11:23
Говоря простым языком, это урезанная и выделенная версия обычного контроллера, предназначенная для работы с простыми данными типа строк и JSON. Чтобы его можно было использовать вне MVC, где не очень то и нужно визуализировать представления и прочее. Например в том же проекте Web Forms или обычном консольном приложении. Если вы работаете с MVC и нет задач связанных с разделением бизнес-логики в отдельную службу, с которой может работать не только ваше веб-приложение, то делайте так как и раньше.
Alexander
23.03.2013 11:32
Картинки можно было не урезать так сильно :)
Юрий
09.09.2013 13:37
Спасибо
очень понятно все описано