IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

C# Discussion :

BestPractice solution client lourd / RESTful API Service


Sujet :

C#

  1. #1
    Nouveau membre du Club
    Femme Profil pro
    Développeur .NET
    Inscrit en
    Janvier 2007
    Messages
    58
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Janvier 2007
    Messages : 58
    Points : 34
    Points
    34
    Par défaut BestPractice solution client lourd / RESTful API Service
    Bonjour à tous,

    Voilà, avec mes collègues nous sommes dans une impasse.

    Notre projet consiste à réaliser un client lourd, une interface Web et un service pour que tout le monde communique.

    Après avoir fait des recherches en tout sens, nous avons sélectionnés l'architecture suivante :
    Le client lourd en WPF (.Net 3.5 car des utilisateurs sous Vista).
    Un service Web de type RESTFull API service contenant la couche Data (entity Framework sur une base SQL Serveur) (.Net 4)
    Un projet Model contenant les interfaces de nos classes (.Net 4). Ce projet est accessible dans le client et le service.

    Cela nous permet d'avoir les mêmes objets dans le client et le service. Le service sérialisant ses données en Json, nous pensions que la récupération des données dans le client se ferait intuitivement.

    Oui mais voila, ce n'est pas le cas, comme vous devez vous en douter.

    Voila ce que nous avons dans notre projet Models :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
        public interface ISheet
        {
            int ID { get; set; }
            string Name { get; set; }
     
            Collection<ICategory> Category { get; set; }
        }
        public interface ICategory
        {
            int ID { get; set; }
            string Name { get; set; }
        }
    projet WebAPIService :
    - Le model :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
     
        [DataContract(IsReference = true)]
        [KnownType(typeof(Category))]
        public partial class Sheet : ISheet
        {
            #region Primitive Properties
        	[DataMember]
            public int ID
            {
                get;
                set;
            }
     
        	[DataMember]
            public string Name
            {
                get;
                set;
            }
            #endregion
            #region Navigation Properties
        	[DataMember]
            public Collection<ICategory> Category
            {
                get
                {
                    if (_category == null)
                    {
                        var newCollection = new FixupCollection<ICategory>();
                        newCollection.CollectionChanged += FixupCategory;
                        _category = newCollection;
                    }
                    return _category;
                }
                set
                {
                    if (!ReferenceEquals(_category, value))
                    {
                        var previousValue = _category as FixupCollection<ICategory>;
                        if (previousValue != null)
                        {
                            previousValue.CollectionChanged -= FixupCategory;
                        }
                        _category = value;
                        var newValue = value as FixupCollection<ICategory>;
                        if (newValue != null)
                        {
                            newValue.CollectionChanged += FixupCategory;
                        }
                    }
                }
            }
            private Collection<ICategory> _category;
     
            #endregion
            #region Association Fixup
            private void FixupCategory(object sender, NotifyCollectionChangedEventArgs e)
            {
                if (e.NewItems != null)
                {
                    foreach (ICategory item in e.NewItems)
                    {
                        if (!item.Sheet.Contains(this))
                        {
                            item.Sheet.Add(this);
                        }
                    }
                }
     
                if (e.OldItems != null)
                {
                    foreach (ICategory item in e.OldItems)
                    {
                        if (item.Sheet.Contains(this))
                        {
                            item.Sheet.Remove(this);
                        }
                    }
                }
            }
            #endregion
        }
     
        [DataContract(IsReference = true)]
        public partial class Category : ICategory
        {
            #region Primitive Properties
        	[DataMember]
            public int ID
            {
                get;
                set;
            }
        	[DataMember]
            public string Name
            {
                get;
                set;
            }
            #endregion
        }
    - Le service :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
     
        public class SheetController : ApiController
        {
            private TORDBEntities db = new TORDBEntities();
     
            /// <summary>
            /// GET api/Sheet/5
            /// </summary>
            /// <param name="id">int</param>
            /// <returns>Sheet</returns>
            public Sheet GetSheet(int id)
            {
                Sheet sheet = db.Sheet.Include("Category").Single(s => s.ID == id);
                if (sheet == null)
                {
                    throw new HttpResponseException(Request.CreateResponse(HttpStatusCode.NotFound));
                }
     
                return sheet;
            }
        }
    Côté client :
    - Le model :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
     
        public class Sheet : ISheet
        {
            public int ID { get; set; }
            public string Name { get; set; }
     
            public ICollection<ICategory> Category { get; set; }
        }
     
        public class Category : ICategory
        {
            public int ID { get; set; }
            public string Name { get; set; }
        }
    - La récupération des données :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
     
        class ServiceSheet
        {
            public Sheet sheet = new Sheet();
     
            public Sheet GetSheet(int id)
            {
                string url = ConfigurationManager.AppSettings["UrlWebService"];
                url += @"api/sheet/" + id;
                HttpWebRequest requete = WebRequest.Create(url) as HttpWebRequest;
                requete.Method = WebRequestMethods.Http.Get;
     
                requete.BeginGetResponse(new AsyncCallback(this.GetSheetResponseCallback), requete);
     
                return sheet;
            }
     
            private void GetSheetResponseCallback(IAsyncResult ar)
            {
                //Récupération de l'objet HttpWebRequest 
                HttpWebRequest requete = (HttpWebRequest)ar.AsyncState;
     
                try
                {
                    using (HttpWebResponse reponse = requete.EndGetResponse(ar) as HttpWebResponse)
                    {
                        using (StreamReader streamReader = new StreamReader(reponse.GetResponseStream()))
                        {
                            string Text = streamReader.ReadToEnd();
                            sheet = JsonConvert.DeserializeObject<Sheet>(Text);
                        } 
                    }
                }
                catch (WebException we)
                {
                    if (we.Status == WebExceptionStatus.ProtocolError)
                    {
                        HttpWebResponse r = (HttpWebResponse)we.Response;
                        if (r.StatusCode == HttpStatusCode.NotFound)
     
                            MessageBox.Show("Code d'erreur: " + r.StatusCode.ToString());
                        r.Close();
                    }
                    else
                        MessageBox.Show(we.Message + " " + we.Status.ToString());
                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.Message, "Erreur");
                }
            }
        }
    Le problème que nous avons ici, se trouve dans l'objet Sheet : ICollection<ICategory>.
    Json n'arrive pas à instancier ICollection<ICategory> avec se qu'il récupère.

    Après avoir regardé un peu partout sur le net, je n'arrive pas à trouver un exemple qui corresponde à notre problème. J'ai bien trouvé des exemples avec des interfaces, mais il n'y avait jamais de ICollection.
    Voici quelques sites que j'ai visité, sans trouver de réponse :
    http://bojordan.com/?p=1301
    http://james.newtonking.com/json/help/index.html
    http://blog.greatrexpectations.com/2...sing-json-net/

    Le dernier m'a bien fait avancer :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
     
        public class Sheet : ISheet
        {
            public int ID { get; set; }
            public string Name { get; set; }
     
            [JsonConverter(typeof(ConcreteTypeConverter<Category>))]
            public ICollection<ICategory> Category { get; set; }
        }
     
        public class ConcreteTypeConverter<TConcrete> : JsonConverter
        {
            public override bool CanConvert(Type objectType)
            {
                //assume we can convert to anything for now
                return true;
            }
     
            public override object ReadJson(JsonReader reader, Type objectType, 
                object existingValue, JsonSerializer serializer)
            {
                //explicitly specify the concrete type we want to create
                return serializer.Deserialize<TConcrete>(reader);
            }
     
            public override void WriteJson(JsonWriter writer, object value, 
                JsonSerializer serializer)
            {
                //use the default serialization - it works fine
                serializer.Serialize(writer, value);
            }
        }
    Mais j'ai l'erreur suivante :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    Unable to cast object of type 'System.Collections.Generic.List1[App.Client.Models.Category]' to
      type 'System.Collections.Generic.ICollection1[App.Models.ICategory]'.
    Du coup, on se demande si on n'est pas partie dans la mauvaise direction. Voici quelques questions que nous nous posons :
    Est-ce une bonne idée de créer une interface qui est utilisée dans les 2 projets ?
    Le problème ne viendrait-il pas de ICollection, mais dans ce cas, par quoi faudrait-il le remplacer ?
    Existe-t-il une meilleur façon de faire ? Une qui fonctionne quoi !


    Merci de m'avoir lue jusqu'au bout, j'attends vos réponses !

  2. #2
    Nouveau membre du Club
    Femme Profil pro
    Développeur .NET
    Inscrit en
    Janvier 2007
    Messages
    58
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Janvier 2007
    Messages : 58
    Points : 34
    Points
    34
    Par défaut
    C'est bon j'ai trouvé !

    J'ai juste 'oublié' de mettre une partie du code :
    Voila ce qu'on doit trouver côté client :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
     
        public class Sheet : ISheet
        {
            public int ID { get; set; }
            public string Name { get; set; }
            public ICollection<ICategory> Category
            {
                get
                {
                    if (_category == null)
                    {
                        var newCollection = new FixupCollection<ICategory>();
                        newCollection.CollectionChanged += FixupCategory;
                        _category = newCollection;
                    }
                    return _category;
                }
                set
                {
                    if (!ReferenceEquals(_category, value))
                    {
                        var previousValue = _category as FixupCollection<ICategory>;
                        if (previousValue != null)
                        {
                            previousValue.CollectionChanged -= FixupCategory;
                        }
                        _category = value;
                        var newValue = value as FixupCollection<ICategory>;
                        if (newValue != null)
                        {
                            newValue.CollectionChanged += FixupCategory;
                        }
                    }
                }
            }
            private ICollection<ICategory> _category;
     
     
            private void FixupCategory(object sender, NotifyCollectionChangedEventArgs e)
            {
                if (e.NewItems != null)
                {
                    foreach (ICategory item in e.NewItems)
                    {
                        if (!item.Sheet.Contains(this))
                        {
                            item.Sheet.Add(this);
                        }
                    }
                }
     
                if (e.OldItems != null)
                {
                    foreach (ICategory item in e.OldItems)
                    {
                        if (item.Sheet.Contains(this))
                        {
                            item.Sheet.Remove(this);
                        }
                    }
                }
            }
        }
     
        public class FixupCollection<T> : ObservableCollection<T>
        {
            protected override void ClearItems()
            {
                new List<T>(this).ForEach(t => Remove(t));
            }
     
            protected override void InsertItem(int index, T item)
            {
                if (!this.Contains(item))
                {
                    base.InsertItem(index, item);
                }
            }
        }
    Voilà, si ça peut aider certain.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. objets/règles métier lors de l'adaptation d'un client lourd au style Rest/web
    Par chrisdot dans le forum Général Conception Web
    Réponses: 0
    Dernier message: 25/01/2013, 12h09
  2. [RIA Services] Client Lourd et SilverLight
    Par BVK dans le forum Silverlight
    Réponses: 2
    Dernier message: 25/02/2010, 09h32
  3. Architecture Client lourd + RestFul
    Par e_gugus dans le forum Java EE
    Réponses: 3
    Dernier message: 19/05/2008, 00h00
  4. client lourd en web service
    Par amelA dans le forum Services Web
    Réponses: 4
    Dernier message: 04/04/2007, 21h57
  5. Client lourd java et web service
    Par gs@ab dans le forum Services Web
    Réponses: 6
    Dernier message: 22/11/2006, 18h15

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo