Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • World
  • Users
  • Groups
Skins
  • Light
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Code Project
  1. Home
  2. General Programming
  3. WCF and WF
  4. WCF: Return type should implement abstract method.

WCF: Return type should implement abstract method.

Scheduled Pinned Locked Moved WCF and WF
helpcsharpwcf
17 Posts 2 Posters 0 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • P Offline
    P Offline
    Phillip Donegan
    wrote on last edited by
    #1

    Hi All, I think I'm just being stupid and I need to add an attribute to a method but despite endless googling I can still not find the answer so I thought I'd try my luck here. I have a abstract class called Discount, Discount has an abstract method called Calculate: [DataContract] [KnownType(typeof(Percentage))] public abstract class Discount : IDiscount { //Some data members here public abstract void Calculate(); } Here is the concrete implementation: [DataContract] internal class Percentage:Discount { internal Percentage() { } public override void Calculate() { //Logic here } } Now in the interface for the WCF project a generic type of Discount is returned (so I can return different implementations of discount), and this knows that it should implement a method called Calculate(). However because WCF is opt in with reagrds to data it doesn't yet know about the Calculate implementation. So I get this error: Error 1 'ECommerce_TestSuite.ECommerce_API.Percentage' does not implement inherited abstract member 'ECommerce_Module.BusinessObject.Discount.Discount.Calculate(ECommerce_Module.VirtualObject.IBasket)' So I think I just need to add an attribute to either the implementation of the Calculate method or to the abstract method declarations so that the WCF project knows that it does have an implemented method. However I do not know what attribute this is! Any help would be really appreciated. Phil

    I 1 Reply Last reply
    0
    • P Phillip Donegan

      Hi All, I think I'm just being stupid and I need to add an attribute to a method but despite endless googling I can still not find the answer so I thought I'd try my luck here. I have a abstract class called Discount, Discount has an abstract method called Calculate: [DataContract] [KnownType(typeof(Percentage))] public abstract class Discount : IDiscount { //Some data members here public abstract void Calculate(); } Here is the concrete implementation: [DataContract] internal class Percentage:Discount { internal Percentage() { } public override void Calculate() { //Logic here } } Now in the interface for the WCF project a generic type of Discount is returned (so I can return different implementations of discount), and this knows that it should implement a method called Calculate(). However because WCF is opt in with reagrds to data it doesn't yet know about the Calculate implementation. So I get this error: Error 1 'ECommerce_TestSuite.ECommerce_API.Percentage' does not implement inherited abstract member 'ECommerce_Module.BusinessObject.Discount.Discount.Calculate(ECommerce_Module.VirtualObject.IBasket)' So I think I just need to add an attribute to either the implementation of the Calculate method or to the abstract method declarations so that the WCF project knows that it does have an implemented method. However I do not know what attribute this is! Any help would be really appreciated. Phil

      I Offline
      I Offline
      Ian Shlasko
      wrote on last edited by
      #2

      I think you just need to put the [DataMember] attribute on any property/method that WCF should recognize. This is in addition to the [DataContract] attribute you already have on the class.

      Proud to have finally moved to the A-Ark. Which one are you in?
      Author of the Guardians Saga (Sci-Fi/Fantasy novels)

      P 1 Reply Last reply
      0
      • I Ian Shlasko

        I think you just need to put the [DataMember] attribute on any property/method that WCF should recognize. This is in addition to the [DataContract] attribute you already have on the class.

        Proud to have finally moved to the A-Ark. Which one are you in?
        Author of the Guardians Saga (Sci-Fi/Fantasy novels)

        P Offline
        P Offline
        Phillip Donegan
        wrote on last edited by
        #3

        Nope, Error 1 Attribute 'DataMember' is not valid on this declaration type. It is only valid on 'property, indexer, field' declarations.

        I 1 Reply Last reply
        0
        • P Phillip Donegan

          Nope, Error 1 Attribute 'DataMember' is not valid on this declaration type. It is only valid on 'property, indexer, field' declarations.

          I Offline
          I Offline
          Ian Shlasko
          wrote on last edited by
          #4

          To clarify... Are you getting this error at runtime or compile time? EDIT: I'm guessing you trimmed down the code to post, as I notice your error message shows Calculate() having an argument. If this is a compile-time error, then it has nothing to do with WCF, and probably indicates that you just need to double-check the arguments in the abstract and override versions of Calculate to be sure that they match.

          Proud to have finally moved to the A-Ark. Which one are you in?
          Author of the Guardians Saga (Sci-Fi/Fantasy novels)

          P 1 Reply Last reply
          0
          • I Ian Shlasko

            To clarify... Are you getting this error at runtime or compile time? EDIT: I'm guessing you trimmed down the code to post, as I notice your error message shows Calculate() having an argument. If this is a compile-time error, then it has nothing to do with WCF, and probably indicates that you just need to double-check the arguments in the abstract and override versions of Calculate to be sure that they match.

            Proud to have finally moved to the A-Ark. Which one are you in?
            Author of the Guardians Saga (Sci-Fi/Fantasy novels)

            P Offline
            P Offline
            Phillip Donegan
            wrote on last edited by
            #5

            Sorry forgot to say, its a compile time error.

            I 1 Reply Last reply
            0
            • P Phillip Donegan

              Sorry forgot to say, its a compile time error.

              I Offline
              I Offline
              Ian Shlasko
              wrote on last edited by
              #6

              Ah, then like I said, this actually isn't related to WCF at all. Could you post the actual function definition for Calculate in both the abstract class and the subclass?

              Proud to have finally moved to the A-Ark. Which one are you in?
              Author of the Guardians Saga (Sci-Fi/Fantasy novels)

              P 1 Reply Last reply
              0
              • I Ian Shlasko

                Ah, then like I said, this actually isn't related to WCF at all. Could you post the actual function definition for Calculate in both the abstract class and the subclass?

                Proud to have finally moved to the A-Ark. Which one are you in?
                Author of the Guardians Saga (Sci-Fi/Fantasy novels)

                P Offline
                P Offline
                Phillip Donegan
                wrote on last edited by
                #7

                It must be related to WCF as this error occurs in the test project were the service reference is. In the implementation the project compiles fine. The workaround I have at the moment is to make the Calculate method in the abstract class virtual. Then because it knows a type Discount is returned it will compile and all is well. However this should be an abstract method really I just need to tell the WCF project that this method is implemented in the concrete class Percentage somehow?

                I 1 Reply Last reply
                0
                • P Phillip Donegan

                  It must be related to WCF as this error occurs in the test project were the service reference is. In the implementation the project compiles fine. The workaround I have at the moment is to make the Calculate method in the abstract class virtual. Then because it knows a type Discount is returned it will compile and all is well. However this should be an abstract method really I just need to tell the WCF project that this method is implemented in the concrete class Percentage somehow?

                  I Offline
                  I Offline
                  Ian Shlasko
                  wrote on last edited by
                  #8

                  Do me a favor and post the method signatures for both versions of Calculate() in both projects... Let's make sure it all matches up.

                  Proud to have finally moved to the A-Ark. Which one are you in?
                  Author of the Guardians Saga (Sci-Fi/Fantasy novels)

                  P 1 Reply Last reply
                  0
                  • I Ian Shlasko

                    Do me a favor and post the method signatures for both versions of Calculate() in both projects... Let's make sure it all matches up.

                    Proud to have finally moved to the A-Ark. Which one are you in?
                    Author of the Guardians Saga (Sci-Fi/Fantasy novels)

                    P Offline
                    P Offline
                    Phillip Donegan
                    wrote on last edited by
                    #9

                    Ok: How I've got it now: [DataContract] [Serializable] public abstract class Discount : IDiscount { #region Constructors internal Discount() { } #endregion //Should be abstract but then WCF engine will not compile public virtual void Calculate(VirtualObject.IBasket basket) { throw new NotImplementedException(); } #region Helper Methods protected decimal RoundToTwoDecimalPlaces(decimal amount) { return (Math.Ceiling(amount * 100) / 100); } #endregion } This compiles and works but really it should be abstract. So how it should be: [DataContract] [Serializable] public abstract class Discount : IDiscount { #region Constructors internal Discount() { } #endregion public abstract void Calculate(VirtualObject.IBasket basket); } And this is how its implemented in the concrete class Percentage: [DataContract] [Serializable] internal class Percentage:Discount { internal Percentage() { } public override void Calculate(VirtualObject.IBasket basket) { foreach (ECommerce_Module.VirtualObject.IBasketItem item in basket.Items) { decimal productPrice = item.ItemPricePreDiscount.Value; item.ItemPricePostDiscount = (item.ItemPricePreDiscount - RoundToTwoDecimalPlaces(productPrice * (DiscountValue.Value / 100)) * item.Quantity); } } } But this the returns the error: Error 2 'ECommerce_TestSuite.ECommerce_API.Percentage' does not implement inherited abstract member 'ECommerce_Module.BusinessObject.Discount.Discount.Calculate(ECommerce_Module.VirtualObject.IBasket)' ..\ECommerce_Module\v1\DotNet\ECommerce_TestSuite\Service References\ECommerce_API\Reference.cs 51 26 ECommerce_TestSuite This error is in the test suite, where ECommerce_API is the service reference to the WCF project. So that tells me that the WCF project doesn't know that the method Calculate is implemented in the concrete class because I haven't "opted" to expose the method, but how I do this I have no idea! Thanks for the help so far though

                    I 1 Reply Last reply
                    0
                    • P Phillip Donegan

                      Ok: How I've got it now: [DataContract] [Serializable] public abstract class Discount : IDiscount { #region Constructors internal Discount() { } #endregion //Should be abstract but then WCF engine will not compile public virtual void Calculate(VirtualObject.IBasket basket) { throw new NotImplementedException(); } #region Helper Methods protected decimal RoundToTwoDecimalPlaces(decimal amount) { return (Math.Ceiling(amount * 100) / 100); } #endregion } This compiles and works but really it should be abstract. So how it should be: [DataContract] [Serializable] public abstract class Discount : IDiscount { #region Constructors internal Discount() { } #endregion public abstract void Calculate(VirtualObject.IBasket basket); } And this is how its implemented in the concrete class Percentage: [DataContract] [Serializable] internal class Percentage:Discount { internal Percentage() { } public override void Calculate(VirtualObject.IBasket basket) { foreach (ECommerce_Module.VirtualObject.IBasketItem item in basket.Items) { decimal productPrice = item.ItemPricePreDiscount.Value; item.ItemPricePostDiscount = (item.ItemPricePreDiscount - RoundToTwoDecimalPlaces(productPrice * (DiscountValue.Value / 100)) * item.Quantity); } } } But this the returns the error: Error 2 'ECommerce_TestSuite.ECommerce_API.Percentage' does not implement inherited abstract member 'ECommerce_Module.BusinessObject.Discount.Discount.Calculate(ECommerce_Module.VirtualObject.IBasket)' ..\ECommerce_Module\v1\DotNet\ECommerce_TestSuite\Service References\ECommerce_API\Reference.cs 51 26 ECommerce_TestSuite This error is in the test suite, where ECommerce_API is the service reference to the WCF project. So that tells me that the WCF project doesn't know that the method Calculate is implemented in the concrete class because I haven't "opted" to expose the method, but how I do this I have no idea! Thanks for the help so far though

                      I Offline
                      I Offline
                      Ian Shlasko
                      wrote on last edited by
                      #10

                      Ok, this might be a silly question, but let's just rule out anything you might have missed (Sometimes we get too close to the problem and start missing things that are "too obvious")... Does the test suite, where the compile-time error is occurring, reference these classes from the same library, or is it using a copy? If it's a copy, check the implementation of 'Percentage' in the test suite to make sure Calcluate() is implemented. Remember that while ServiceContract classes only have to be implemented on the server side, with an interface given to the client, DataContract classes are just passed as-is (The attributes only specify which fields/properties are serialized). Any code in a DataContract class has to be available to the client.

                      Proud to have finally moved to the A-Ark. Which one are you in?
                      Author of the Guardians Saga (Sci-Fi/Fantasy novels)

                      P 1 Reply Last reply
                      0
                      • I Ian Shlasko

                        Ok, this might be a silly question, but let's just rule out anything you might have missed (Sometimes we get too close to the problem and start missing things that are "too obvious")... Does the test suite, where the compile-time error is occurring, reference these classes from the same library, or is it using a copy? If it's a copy, check the implementation of 'Percentage' in the test suite to make sure Calcluate() is implemented. Remember that while ServiceContract classes only have to be implemented on the server side, with an interface given to the client, DataContract classes are just passed as-is (The attributes only specify which fields/properties are serialized). Any code in a DataContract class has to be available to the client.

                        Proud to have finally moved to the A-Ark. Which one are you in?
                        Author of the Guardians Saga (Sci-Fi/Fantasy novels)

                        P Offline
                        P Offline
                        Phillip Donegan
                        wrote on last edited by
                        #11

                        Ian Shlasko wrote:

                        Does the test suite, where the compile-time error is occurring, reference these classes from the same library, or is it using a copy? If it's a copy, check the implementation of 'Percentage' in the test suite to make sure Calcluate() is implemented.

                        Hmm, I've just done this in the test suite: ECommerce_API.Percentage percentage = new ECommerce_API.Percentage(); So that's me calling the Percentage class from the Service Reference (called ECommerece_API). This class has a method called Calculate which I can call so the IDE knows that its implemented. Its just the reference.cs file that's having trouble??

                        I 1 Reply Last reply
                        0
                        • P Phillip Donegan

                          Ian Shlasko wrote:

                          Does the test suite, where the compile-time error is occurring, reference these classes from the same library, or is it using a copy? If it's a copy, check the implementation of 'Percentage' in the test suite to make sure Calcluate() is implemented.

                          Hmm, I've just done this in the test suite: ECommerce_API.Percentage percentage = new ECommerce_API.Percentage(); So that's me calling the Percentage class from the Service Reference (called ECommerece_API). This class has a method called Calculate which I can call so the IDE knows that its implemented. Its just the reference.cs file that's having trouble??

                          I Offline
                          I Offline
                          Ian Shlasko
                          wrote on last edited by
                          #12

                          The IDE knows that it's a subclass of Discount, so it could be showing you the Calculate() from the parent class. It doesn't necessarily know whether Percentage has it implemented. I'm trying to eliminate the possibility that you're calling the wrong "Percentage" class, or the wrong version of it. So do you have one common implementation of Percentage that both the server and client reference (As in, are they both pointing to the same DLL), or do you have two copies of it, one for each? Try temporarily adding a simple public void Test() { } to Percentage, and see if you can call it from the test suite.

                          Proud to have finally moved to the A-Ark. Which one are you in?
                          Author of the Guardians Saga (Sci-Fi/Fantasy novels)

                          P 1 Reply Last reply
                          0
                          • I Ian Shlasko

                            The IDE knows that it's a subclass of Discount, so it could be showing you the Calculate() from the parent class. It doesn't necessarily know whether Percentage has it implemented. I'm trying to eliminate the possibility that you're calling the wrong "Percentage" class, or the wrong version of it. So do you have one common implementation of Percentage that both the server and client reference (As in, are they both pointing to the same DLL), or do you have two copies of it, one for each? Try temporarily adding a simple public void Test() { } to Percentage, and see if you can call it from the test suite.

                            Proud to have finally moved to the A-Ark. Which one are you in?
                            Author of the Guardians Saga (Sci-Fi/Fantasy novels)

                            P Offline
                            P Offline
                            Phillip Donegan
                            wrote on last edited by
                            #13

                            Hmm, just added Test() to the percentage class and the test suite could not see it. So that would that support my argument that I need to expose the Calculate method in Percentage to the WCF so that it knows its implemented?

                            I 1 Reply Last reply
                            0
                            • P Phillip Donegan

                              Hmm, just added Test() to the percentage class and the test suite could not see it. So that would that support my argument that I need to expose the Calculate method in Percentage to the WCF so that it knows its implemented?

                              I Offline
                              I Offline
                              Ian Shlasko
                              wrote on last edited by
                              #14

                              Again, this has nothing to do with WCF, since it's compile-time. WCF basically does two things, in this context: 1) Allows ServiceContract classes, and associated callbacks, to call methods across a remote connection 2) Automatically serializes and de-serializes DataContract classes Anything in a DataContract class needs to have a visible implementation on the client side. No method calls in a DataContract class go over the network, so the client has to have a full implementation. If this is meant to run on the server side, it needs to be part of your ServiceContract class.

                              Proud to have finally moved to the A-Ark. Which one are you in?
                              Author of the Guardians Saga (Sci-Fi/Fantasy novels)

                              P 1 Reply Last reply
                              0
                              • I Ian Shlasko

                                Again, this has nothing to do with WCF, since it's compile-time. WCF basically does two things, in this context: 1) Allows ServiceContract classes, and associated callbacks, to call methods across a remote connection 2) Automatically serializes and de-serializes DataContract classes Anything in a DataContract class needs to have a visible implementation on the client side. No method calls in a DataContract class go over the network, so the client has to have a full implementation. If this is meant to run on the server side, it needs to be part of your ServiceContract class.

                                Proud to have finally moved to the A-Ark. Which one are you in?
                                Author of the Guardians Saga (Sci-Fi/Fantasy novels)

                                P Offline
                                P Offline
                                Phillip Donegan
                                wrote on last edited by
                                #15

                                Ian Shlasko wrote:

                                Anything in a DataContract class needs to have a visible implementation on the client side. No method calls in a DataContract class go over the network, so the client has to have a full implementation. If this is meant to run on the server side, it needs to be part of your ServiceContract class.

                                Ok, so the Calculate method of Percentage should be run server side not client side. So how can I add this method to the Service Contract? This method is only called when a different method which is in the service contract is called. Its almost at the wrong level allow me to explain: The methods that are in the service contract are for manipulating a shopping cart. So AddItem, AddPromotionCode, SetDelivery, ViewBasket etc etc. The calculate method is a function that is called when the ViewBasket operation is called. This then checks to see if a promotion is applied and if true, what the value of the discount is. So this calculate method is an internal function and shouldn't be possible to be called directly. And its a functions of the basket not the shopping cart. All the methods in the service contract are for manipulating the shopping cart, not the basket directly. So Shopping Cart -- Service Contract at this level | | \/ Basket -- which has the Calculate method So if I add Calculate to the Service Contract i'm kind of breaking the architecture of the solution :/

                                I 1 Reply Last reply
                                0
                                • P Phillip Donegan

                                  Ian Shlasko wrote:

                                  Anything in a DataContract class needs to have a visible implementation on the client side. No method calls in a DataContract class go over the network, so the client has to have a full implementation. If this is meant to run on the server side, it needs to be part of your ServiceContract class.

                                  Ok, so the Calculate method of Percentage should be run server side not client side. So how can I add this method to the Service Contract? This method is only called when a different method which is in the service contract is called. Its almost at the wrong level allow me to explain: The methods that are in the service contract are for manipulating a shopping cart. So AddItem, AddPromotionCode, SetDelivery, ViewBasket etc etc. The calculate method is a function that is called when the ViewBasket operation is called. This then checks to see if a promotion is applied and if true, what the value of the discount is. So this calculate method is an internal function and shouldn't be possible to be called directly. And its a functions of the basket not the shopping cart. All the methods in the service contract are for manipulating the shopping cart, not the basket directly. So Shopping Cart -- Service Contract at this level | | \/ Basket -- which has the Calculate method So if I add Calculate to the Service Contract i'm kind of breaking the architecture of the solution :/

                                  I Offline
                                  I Offline
                                  Ian Shlasko
                                  wrote on last edited by
                                  #16

                                  My suggestion would be to separate the business logic (Calculate()) from the data package (Basket). Keep your DataContract classes as code-free as possible... Just properties, fields, and formatting/transformation methods. Instead of putting a Calculate there, maybe give the server a BasketCalculator static class... BasketCalculator.Calculate(myBasket); Either that, or have the server work with a rich, self-calculating Basket class, but actually send a simplified version to the client (Copy the data to a lightweight DataContract object). The client would just get the equivalent of a database record, with only the data it needs to display.

                                  Proud to have finally moved to the A-Ark. Which one are you in?
                                  Author of the Guardians Saga (Sci-Fi/Fantasy novels)

                                  P 1 Reply Last reply
                                  0
                                  • I Ian Shlasko

                                    My suggestion would be to separate the business logic (Calculate()) from the data package (Basket). Keep your DataContract classes as code-free as possible... Just properties, fields, and formatting/transformation methods. Instead of putting a Calculate there, maybe give the server a BasketCalculator static class... BasketCalculator.Calculate(myBasket); Either that, or have the server work with a rich, self-calculating Basket class, but actually send a simplified version to the client (Copy the data to a lightweight DataContract object). The client would just get the equivalent of a database record, with only the data it needs to display.

                                    Proud to have finally moved to the A-Ark. Which one are you in?
                                    Author of the Guardians Saga (Sci-Fi/Fantasy novels)

                                    P Offline
                                    P Offline
                                    Phillip Donegan
                                    wrote on last edited by
                                    #17

                                    Ok, I'll give that a go, thanks for the help Ian, many Kudos!

                                    1 Reply Last reply
                                    0
                                    Reply
                                    • Reply as topic
                                    Log in to reply
                                    • Oldest to Newest
                                    • Newest to Oldest
                                    • Most Votes


                                    • Login

                                    • Don't have an account? Register

                                    • Login or register to search.
                                    • First post
                                      Last post
                                    0
                                    • Categories
                                    • Recent
                                    • Tags
                                    • Popular
                                    • World
                                    • Users
                                    • Groups