views:

210

answers:

3

Hi.

I am having problems accessing methods in my WCF class library and am wondering if somebody could explain why?

I have a web project that has a single DLL file - WebAPILibrary.DLL in its /bin folder. The SVC files in my Web Site are pointing to the corresponding contracts contained in the DLL file. So, for example, under the namespace WebProject.WebAPI.Auth I have:

   [DataContract]
    public class Auth
    {
        [DataMember]
        public string LoginUser;
    }


    [ServiceBehavior]
    public class AuthService : IAuthService
    {

     string IAuthService.LoginUser(string Email, string Password)
     {
            //do some stuff
     }

     }


    [ServiceContract(Namespace="WebAPI.Authentication")]
    public interface IAuthService
    {

        [OperationContract(Name = "LoginUser")]
        string LoginUser(string Email, string Password);

    }

Now, when I instantiate AuthService auth = new AuthService() in my web project, I would expect auth.LoginUser(string Email, string Password) but auth does not expose any of my defined methods. As a test, I instantiated IAuthService and get what I want. Since IAuthService is implemented by AuthService, shouldn't I be able to do the same by instantiating AuthService?

Also, when i point to the URL of any of my SVC files, they load as expected.

Thanks for your time.

A: 

You should put "public" in front of "string IAuthService.LoginUser(string Email, string Password)" in your implementation, so it should be

public string IAuthService.LoginUser(string Email, string Password)
{
    // do some stuff
}
vucetica
+1  A: 

When you "instantiate" IAuthService - probably by means of creating a client proxy for that service contract - you see the service contract view of the class, e.g. you see everything that's exposed on the [ServiceContract] as a [OperationContract] - the service methods. This is what gets exposed in your service description (the WSDL of your service) and it's totally irrelevant what visibility those methods have in .NET world.

However, if you directly instantiate the service class as a .NET class (and not via the WCF service runtime), then obviously, you're limited by the .NET visibility constraints, and members of a class are internal by default, e.g. not visible to the outside.

So basically, you need to distinguish whether you're looking at your class as a representation of a WCF service contract, or as a classic .NET class.

Marc

UPDATE: if you want to use your DLL "as a WCF service", you'll need to go the WCF client proxy way in order to use it. This can be done several ways:

  • create a client proxy using svcutil.exe from the command line
  • in Visual Studio, use "Add Service Reference" and let VS create your client proxy for you
  • or create the client proxy yourself, in code - not that hard to do really!

In code, you could do something like

ChannelFactory<IAuthService> factory = new ChannelFactory<IAuthService>();

IAuthService proxy = factory.CreateChannel();

Now, on your proxy class, you should see and be able to use your Login method.

To make all work, of course, you'll need the right set of config entries and all in your web.config.

Does that help?

marc_s
Agree 100%. A WCF service must be spun up in a ServiceHost to be guarenteed all of the demands it may make of the runtime through various attributes that are applied. Instantiating it as a "pure" .NET class and calling method is just... wrong. :)
Drew Marsh
Thanks again Marc (and Drew). To answer your question Marc, I am looking at my class as a representation of a WCF Service Contract, not as a .NET class (this was not my intention). Actually, this thread is the product of a previous dialog with Drew where I both had my WebAPILibrary DLL referenced in my /bin directory (which loaded automatically) and my WCF Web Service reference. Apparently, one was conflicting with the other so I removed the WCF Web reference. So - how do I reference the DLL as a WCF Service contract and expose the methods correctly? Thanks for any help.
Code Sherpa
Sorry Marc - I didn't see your update until now. That does help - I think I have been doing this when I do "add service reference" to access the endpoints I have created in my class library. My proxy works fine but I am wrestling with a DLL conflict issue (see below). But, for the purposes of the title of this thread, you have answered my question and thank you.
Code Sherpa
A: 

You can slightly modify your code to the following

[ServiceBehavior]
public class AuthService : IAuthService
{    
 public string IAuthService.LoginUser(string Email, string Password)
 {
        //do some stuff
 }    
}

In your code, you have implemented the interface explicitly without making the access modifier public, therefore LoginUser method is visible only when the variable's declaring type is the specific interface. This is useful when you implement different interfaces with same member definition.

public interface ITest1
{
 void Hello();
}

public interface ITest2
{
 void Hello();
}

Explicit Impl

public class Impl : ITest1, ITest2
{
   void ITest1.Hello(){ ... }
   void ITest2.Hello(){ ... }
}

ITest1 obj1 = new Impl();
obj1.Hello() // this is calling ITest1.Hello()

ITest2 obj2 = new Impl();
obj2.Hello() // this is calling ITest2.Hello()

Or Implicit impl that only needs to have one member implemented.

public class Impl : ITest1, ITest2
{
   public void Hello(){ ... }
}
codemeit
This is definitely why the method is not showing up, but @Marc_s it spot on that the approach of just instantiating the service as a "pure" .NET class is completely flawed.
Drew Marsh
Thanks. Maybe I misunderstood your previous suggestion that I remove my service reference and use my DLL to avoid my original "conflict error". My intention is not to use the WCF service as a stand-alone class. But, when I add my Web Service references back (when I do I can see my methods) I get error again: Type 'Authentication.IAuthService' exists in both 'c:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\Temporary ASP.NET Files\web\51fdee26\assembly\dl3\WebAPILibrary.DLL' and 'c:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\Temporary ASP.NET Files\web\51fdee26\App_WebReferences.mzmqypyv.dll'.
Code Sherpa
The quick fix is to delete all the files under C:\Windows\Microsoft.NET\Framework\v2.0.50727\Temporary ASP.NET Filesif you can not delete the files (IIS are locking them), just run iisreset in the command prompt to restart IIS server.
codemeit
Thanks Codemeit. I tried the deletion suggestion before. It didn't work. When I recompile I get the same error. I do notice that a second folder called /root is created in the TEMP directory with the same files. Not sure if that is causing the error or not but the /root directory is not in the error message. I am self-hosting for development and not using IIS yet so the iisreset command won't work. I have also tried removing all but one file in my App_Code folder. It looks like the DLL in my /bin folder and my Web Service reference is causing the overlap.
Code Sherpa
Have you tried to restart the selfhost server and do clean rebuild.
codemeit