MVC est designé pour des applications web standard qui servent des pages HTML.
Web API est designé pour des applications REST qui servent des objets sérialisés (JSON, XML).
Routing
App_Start/WebApiConfig.cs
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
L'extension pour Firefox RESTED permet de tester les requêtes.
Global.asax.cs
protectedvoidApplication_Start()
{
// return json by default (ajouter à la fin de la méthode)
GlobalConfiguration.Configuration.Formatters.Clear();
GlobalConfiguration.Configuration.Formatters.Add(newJsonMediaTypeFormatter());
App_Start/WebApiConfig.cs
// return html by default instead of xml
config.Formatters.JsonFormatter.SupportedMediaTypes.Add(newMediaTypeHeaderValue("text/html"));
Permet de redéfinir la manière dont sera déserialisé l'url.
TestController.cs
// association 1, fonctionne seulement si ComplexType est passé en paramètre// api/test?ct=1,2publicIHttpActionResultGet([ModelBinder(typeof(ComplexTypeModelBinder))] ComplexType ct) { }
// api/test?cts[0]=1,2&cts[1]=3,4publicIHttpActionResultGet([FromUri] IEnumerable<ComplexType> cts) { }
// api/test?ComplexTypes[0]=1,2&ComplexTypes[1]=3,4publicIHttpActionResultGet([FromUri] Containercontainer) { }
// association 2, fonctionne si ComplexType est passé en paramètre mais aussi s'il est un sous-élément du paramètre
[ModelBinder(typeof(ComplexTypeModelBinder))]
publicclassComplexType
{
publicint Prop1 { get; set; }
publicint Prop2 { get; set; }
}
publicclassContainer
{
publicIEnumerable<ComplexType> ComplexTypes { get; set; }
}
WebApiConfig.cs
publicstaticvoidRegister(HttpConfigurationconfig)
{
// association 3, fonctionne seulement si ComplexType est passé en paramètre// la méthode du controller ne doit pas contenir FromUri
config.ParameterBindingRules.Add(
typeof(ComplexType),
descriptor => descriptor.BindWithModelBinding(newComplexTypeModelBinder()));
// association 4, fonctionne si ComplexType est passé en paramètre mais aussi s'il est un sous-élément du paramètre// la méthode du controller doit contenir FromUri
config.Services.Insert(typeof(ModelBinderProvider), 0, newComplexTypeModelBinderProvider());
}
varhttpClient = newHttpClient();
// demande explicitement du xml ("application/xml") ou du json ("application/json")
httpClient.DefaultRequestHeaders.Accept.Add(newMediaTypeWithQualityHeaderValue("application/xml"));
// requête en une ligne utilisant Result, ce qui brise l'asyncstringcontent = httpClient.GetAsync(url).Result.Content.ReadAsStringAsync().Result;
// requête en 2 temsp avec test du status codeHttpResponseMessageresponse = await httpClient.GetAsync(url);
if (response.IsSuccessStatusCode)
{
// XMLvardoc = XDocument.Load(awaitresponse.Content.ReadAsStreamAsync());
varns = (XNamespace)"http://schemas.datacontract.org/2004/07/WebAPITest.Models";
foreach (var name in doc.Descendants(ns + "Name"))
{
Console.WriteLine(name.Value);
}
// récupération du contenu comme un stringstringcontent = await response.Content.ReadAsStringAsync();
// désérialisation du contenu// ReadAsAsync<T> nécessite l'assembly System.Net.Http.Formatting// disponible dans le paquet NuGet Microsoft.AspNet.WebApi.Client// et le using System.Net.Http;JObjectcontent = await response.Content.ReadAsAsync<JObject>();
}
else
{
// retourne un Task<T> avec un contenu nullreturnawait Task.FromResult<JObject>(null);
}
By default, most exceptions are translated into an HTTP response with status code 500, Internal Server Error.
// HttpResponseException permet de spécifier le code d'erreur, ici 404thrownewHttpResponseException(HttpStatusCode.NotFound);
// spécifie en plus le Content et la ReasonPhrasevarresponseMessage = newHttpResponseMessage(HttpStatusCode.NotFound)
{
Content = newStringContent("Error content."),
ReasonPhrase = "Error reason."
}
thrownewHttpResponseException(responseMessage);
Loguer les exceptions non-gérées
Nuget: Microsoft.AspNet.WebApi.Core
App_Start\WebApiConfig.cs
publicstaticclassWebApiConfig
{
publicstaticvoidRegister(HttpConfigurationconfig)
{
/* ... */// plusieurs ExceptionLogger peuvent être ajoutés, permet juste de loguer
config.Services.Add(typeof(IExceptionLogger), newMyExceptionLogger());
// un seul ExceptionHandler, permet de modifier la réponse
config.Services.Replace(typeof(IExceptionHandler), newGlobalExceptionHandler());