RESTful en WCF (couplé avec du LINQ over SQL)

RESTful est une manière de construire une application pour les systèmes distribués. Le terme a été inventé par un des papa (Roy Fielding) de la RFC HTTP... REST n'est pas un protocole ou un format. Il s'agit d'une architecture original du web. Elle se repose sur quelques principes.
  • l'URI est important : connaître l'URI doit suffire pour accéder à la ressource
  • HTTP fournit toutes les opérations nécessaires (GET, POST, PUT et DELETE)
  • chaque opération est auto-suffisante : il n'y a pas d'état
  • Support de la sécurité ASP.NET
La thèse de Roy Fielding précise les avantages de ce style d'architecture // à SOAP etc.
  1. Maintenance plus simple.
  2. Absence d'état => consommation de mémoire inférieure.
  3. Simplicité dans un environnement Webfarm => meilleure tolérance aux pannes.
  4. Intéropérabilité
  5. ...
J'ai tenté d'aborder certaines possibilités sous .NET 3.5 d'utiliser LINQ + WCF en mode RESTful. Afin de réaliser la petite solution de démo, il a fallu procéder en plusieurs étapes.
  1. Créer quelques tables dans SQLServer et générer les classes Linq to SQL via un fichier dbml.
  2. Il faut définir un contrat qui sera celui utilisé par le service WCF. On spécifie également dans l'attribut WebGet ou WebInvoke le type de sérialisation. Par défaut, elle est en XML mais il est possible de l'activer en mode JSON.
  3. [ServiceContract]
    public interface IBugService
    {
        [OperationContract]
        //ResponseFormat = WebMessageFormat.Xml ou WebMessageFormat.Json
        [WebGet(UriTemplate = "/hello")]
        string  Hello();
    
        [OperationContract]
        [WebGet(UriTemplate = "/projects")]
        List GetProjects();
    
        [OperationContract]
        [WebGet(UriTemplate = "/project/{id}")]
        //id doit etre en string (vu restful)
        Project GetProject(string id);
    
        [OperationContract]
        [WebInvoke(Method = "POST", UriTemplate = "/project/createOrUpdate")]
        void SaveOrUpdateProject(Message projectMessage);
    }
    
  4. Il faut implémenter la classe concrète du service WCF
  5. [ServiceBehavior(InstanceContextMode = InstanceContextMode.Single, ConcurrencyMode = ConcurrencyMode.Single)]
    public class BugService : IBugService
    {
        #region IBugService Members
    
        public string Hello()
        {
            return "Hello world !";
        }
    
        public List GetProjects()
        {
            return Business.GetProjects();
        }
    
        public Project GetProject(string id) 
        {
            return Business.GetProject(short.Parse(id));
        }
    
        public void SaveOrUpdateProject(Message projectMessage)
        {
            HttpRequestMessageProperty requestProperties = projectMessage.Properties[HttpRequestMessageProperty.Name] as HttpRequestMessageProperty;
            Project project = projectMessage.GetBody();
    
            Business.SaveOrUpdateProject(project);
            Console.WriteLine("Received " + requestProperties.Method + " for Project.");
    
            //WebOperationContext.Current.OutgoingResponse.StatusCode = System.Net.HttpStatusCode.Created;
        }
    
        #endregion
    }
    
  6. Il faut lancer le service WCF
  7. BugService service = new BugService();
    WebHttpBinding binding = new WebHttpBinding();
    WebHttpBehavior behavior = new WebHttpBehavior();
    
    WebServiceHost host = new WebServiceHost(service, new Uri("http://localhost:8000/bug"));
    host.AddServiceEndpoint(typeof(IBugService), binding, "");
    host.Open();
    
    Console.WriteLine("Bug service is running at http://localhost:8000/bug");
    Console.ReadLine();
    host.Close();
    
  8. Test du service web avant implémentation du client.
  9. Coté client, il faut implémenter un canal pour parser le code XML renvoyé. Il est possible d'utiliser sans problème du code disponible dans les samples de Microsoft (disponible dans l'exemple fourni à la fin de ce post).
  10. HttpClient client = new HttpClient("http://localhost:8000/bug", false);
    Uri requestUri = new Uri("http://localhost:8000/bug/projects");
    Console.WriteLine("GET " + requestUri);
    Message response = client.Get(requestUri);
    Console.WriteLine((int)client.GetStatusCode(response) + " " + client.GetStatusDescription(response));
    List projects = response.GetBody>();
    
    Project newProject = new Project();
    newProject.Name = "Project added by restful webservice";
    newProject.ProjectKey = 3;
    newProject.ProjectID = Guid.NewGuid();
    
    requestUri = new Uri("http://localhost:8000/bug/project/createOrUpdate");
    Console.WriteLine("POST " + requestUri);
    response = client.Post(requestUri, newProject);
    
  11. Solution d'exemple
  12. La solution est disponible ici.

Quelques références:

Ajouter un commentaire

Le code HTML est affiché comme du texte et les adresses web sont automatiquement transformées.

Fil des commentaires de ce billet

Page top