Autocomplete “REST-style” în ASP.NET WebAPI

Să zicem că primim următorul task: să se creeze un HTTP service, care să poata fi apelat de un client oarecare pentru a implementa o funcționalitate gen auto-complete.
Poate că vrem ca acel service sa fie cât de cat “REST”-style: un request (GET) de genul
/…/resursa/name
ar trebui să returneze fie o singura resursă (in cazul in care e un singur match), fie lista resurselor al caror nume începe cu ‘name’ (și, normal 404 not found dacă nu se găsește nimic). Aparent, nimic complicat.
Totuși, dacă vrem ca al nostru serviciu sa fie “REST”-style, care ar trebui să fie status code-ul în cazul în care nu avem un match exact?
O variantă ar fi să returnăm un status code 300: ‘multiple choices’E potrivit acest status? S-ar putea – RFC-ul (http://tools.ietf.org/html/rfc2616#section-10) ne zice cam așa:

The requested resource corresponds to any one of a set of
representations, each with its own specific location, and agent-
driven negotiation information (section 12) is being provided so that
the user (or user agent) can select a preferred representation and
redirect its request to that location.
Unless it was a HEAD request, the response SHOULD include an entity
containing a list of resource characteristics and location(s) from
which the user or user agent can choose the one most appropriate. The
entity format is specified by the media type given in the Content-
Type header field. Depending upon the format and the capabilities of
the user agent, selection of the most appropriate choice MAY be
performed automatically. However, this specification does not define
any standard for such automatic selection.
If the server has a preferred choice of representation, it SHOULD
include the specific URI for that representation in the Location
field; user agents MAY use the Location field value for automatic
redirection. This response is cacheable unless indicated otherwise.
La prima vedere, nu e chiar cel mai potrivit răspuns – totuși – dacă citim un pic despre “agent-driven negotiation”, printre variante există și: “manually by the user selecting from a generated (possibly hypertext) menu” ceea ce ne apropie de un auto-complete menu.

Cum implementăm asta folosind ASP.NET WebAPI? Destul de simplu:

public class CitiesController : ApiController
 {
 private readonly string[] _cities = { "Cluj", "Bucuresti", "Iasi", "Constanta", "Călarasi", "Câmpeni", "Câmpia Turzii", "Câmpina", "Câmpulung", "Călan", "Călimanesti" };

// GET /api/cities/name
 public HttpResponseMessage<IEnumerable<string>> Get(string cityName)
 {
 var matches = (from c in _cities
                where c.StartsWith(cityName, StringComparison.CurrentCultureIgnoreCase)
                select c).ToArray();

HttpStatusCode status = HttpStatusCode.OK;

if (matches.Length == 0)
 {
   throw new HttpResponseException(HttpStatusCode.NotFound);
 }
   else if (matches.Length == 1)
 {
   status = HttpStatusCode.OK;
 }
 else if (matches.Length > 1)
 {
   status = HttpStatusCode.MultipleChoices;
 }

 return new HttpResponseMessage<IEnumerable<string>>(matches, status);
 }
 }

Clar, e doar un exemplu simplificat, într-o aplicație reala probabil ar mai fi și alți parametrii, validări, rezultatele ar fi extrase dintr-o baza de date etc..

Cum arată un astfel de response văzut cu Fiddler?

Fiddler capture - HTTP 300 status

Este aceasta cea mai bună abordare? Încă nu sunt sigur – e clar că depinde și de clientul ce va consuma acest serviciu (ex.: JQuery), dacă știe să interpreteze respectivul status code.

Privit din perspectiva “REST” justificarea ar fi: un GET pentru /api/cities/Că
dacă nu gaseste o singură resursă, ar trebui să returneze 404 not found.
300 ‘multiple choices’ ne permite să spunem clientului ceva de genul: “nu am găsit orașul respectiv, dar iată o listă de posibilități din care poti alege”.
E un “redirect” pentru că îl trimitem pe client să caute altundeva.
(totuși, nu e vorba de 301, 302 sau 307 care sunt folosite de obicei pentru redirectari permanente sau temporare)

Mai sus, am pus “REST” in ghilimele, pentru că se prea poate ca serviciul meu să nu fie cu adevărat REST, in sensul în care e definit în dizertatia lui Roy Fielding. De ex., lista cu opțiunile posibile, nu include și locația fiecăreia, deci clientul trebuie să știe cum să obțină un city ulterior.

Advertisements
This entry was posted in .NET, Web and tagged , , , . Bookmark the permalink.

3 Responses to Autocomplete “REST-style” în ASP.NET WebAPI

  1. Andrei Ignat says:

    Sa inteleg ca iti place WebAPI?

    • Tudor Turcu says:

      Nu e rau ca idee, mai ales dupa atata SOAP 🙂 – clar, nu poate inlocui WCF-ul in multe cazuri, da’ pentru ceva gen web applications ce folosesc la greu AJAX, sau pentru API-uri publicate pe web, e foarte ok.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s