Exposer un flux RSS/Atom avec Web API 2/2
Mon précédent article sur la Web API et les flux RSS/Atom abordait uniquement les aspects sympathiques de cette solution. Attaquons-nous maintenant au côté obscur du problème.
Un flux RSS/Atom a besoin d’être partagé. En général, on partage celui-ci par un lien sur ses pages, et dans ses entêtes HTML.
Mais que ce passet-il quand un utilisateur click sur le lien affiché sur vos pages ?
Son navigateur va produire un Get… oui, mais pas que : il va aussi demander qu’on lui retourne un contenu de type text/html. Ce type n’étant pas géré par notreFormatter
, la Web API va produire un résultat dans son format à défaut. L’utilisateur va donc obtenir du JSON. Le navigateur demandant du HTML et recevant du JSON, il va certainement proposer à votre utilisateur de télécharger un fichier JSON.Pour résoudre le problème, il suffit donc d’indiquer à notre Formatter
de supporter les messages de type text/html
.
En soit, rien de compliqué :
private const string atom = "application/atom+xml";
private const string rss = "application/rss+xml";
private const string html = "text/html";
public SyndicationFeedFormatter()
{
SupportedMediaTypes.Add(new MediaTypeHeaderValue(atom));
SupportedMediaTypes.Add(new MediaTypeHeaderValue(rss));
SupportedMediaTypes.Add(new MediaTypeHeaderValue(html));
}
Maintenant que vous avez un flux RSS et Atom solide, vous avez peut-être envie de l’utiliser avec des outils tiers. Pour un lecteur de flux, un navigateur, une application mobile, pas de problèmes. Mais pour un service web tiers comme dlvr.it, les choses se gâtent.
Vous pourriez avoir un énigmatique message disant que le premier caractère de votre flux doit être un « < ». Les flux RSS et Atom reposant sur du XML, on est en droit de ce demandé pourquoi le service ne voit pas bien le premier caractère de nos flux.
La réponse est malheureusement toute simple : le client de notre service demande du JSON.
On est donc parti pour ajouter le support de application/json
à notre Formatter
:
private const string atom = "application/atom+xml";
private const string rss = "application/rss+xml";
private const string html = "text/html";
private const string json = "application/json";
public SyndicationFeedFormatter()
{
SupportedMediaTypes.Add(new MediaTypeHeaderValue(atom));
SupportedMediaTypes.Add(new MediaTypeHeaderValue(rss));
SupportedMediaTypes.Add(new MediaTypeHeaderValue(html));
SupportedMediaTypes.Add(new MediaTypeHeaderValue(json));
}
En a-t-on pour autant fini ?
Oui, mais peut-être que non. On peut donc être tenté d’ajouter le fameux content type */*
à notre Formatter
pour répondre une fois pour toutes les problèmes de négociation de type. Heureusement, Web API ne le permet pas (oui heureusement, car ça c’est le job de MVC et WebForm). Il est bien évidemment possible de faire en sorte que notre Formatter
soit le Formatteur utilisé à défaut. Mais est -bien ce que l’on souhaite ?
On commence à se substituer au bon vieux handler ASHX ou à un Controller MVC. La Web API n’est donc peut-être pas la solution à employer pour fournir un flux RSS et/ou Atom.
Et côté performance. Est-ce bien judicieux d’enregistrer un Formatter
qui sera interrogé pour toutes les requêtes alors qu’il ne sert qu’à un endroit ? Bien évidemment non.
Pour résoudre le problème de performances et toujours retourner nos messages aux bons formats, il ne reste donc qu’une solution : forcer la création des messages de réponse via notre Controller Web API.
public class FeedController : ApiController
{
public HttpResponseMessage Get()
{
return Request.CreateResponse(
HttpStatusCode.OK,
FeedService.Get(),
new SyndicationFeedFormatter());
}
}
On se rapproche beaucoup plus d’un Controller MVC. La Web API vient de perdre toute sa saveur et son intérêt :(
Celons-moi même si la solution est complète, et fonctionnelle, on utilise la Web API à contresens. Un Controller MVC serait bien plus indiqué pour un tel usage (bien évidemment, un article est prévu pour couvrir ce sujet).