Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

WCF will not return an int

Tags:

c#

wcf

I am building a WCF in C#, and a client to consume it at the same time. For some reason I am having trouble getting a method to return an int. Here is my contract:

[ServiceContract]
public interface IMData
{
  [OperationContract]
  int ReturnAnInt();

  [OperationContract]
  String HelloWorld();
}

Here is where I have implemented it:

public class MData : IMData
{
  public String HelloWorld()
  {
    return "Hello World";
  }

  public int ReturnAnInt()
  {
    return 5;
  }
}

I'm using Visual Studio, and for the client, I imported this WCF as a Web Reference. Now for some reason when I declare an instance of MData and try to call HelloWorld, there is no problem, but I get a compile error when calling ReturnAnInt.

MData m = new MData();
String helloWorld = m.HelloWorld();
int result = m.ReturnAnInt();

The error I get with ReturnAnInt is: "No overload for method 'ReturnAnInt' takes 0 arguments" So then I mouse over to see what Visual Studio is expecting, and it says that the method should look like:

void MData.ReturnAnInt(out int ReturnAnIntResult, out bool ReturnAnIntResultSpecified)

I have been banging my head against a wall over this for hours now and can find nothing on Google, and it has my coworkers baffled as well. Why did it add two out parameters that aren't in the definition, and change the return type? Any help would be greatly appreciated. I apologize if I left out any information that would be helpful.

like image 477
Maddie Lowe Avatar asked Oct 18 '12 22:10

Maddie Lowe


2 Answers

Can you import it as a Service Reference (newer tech) instead of a Web Reference (older tech)? I work with WCF services through service references and haven't seen such an issue - I've only seen a Specified property (and that as a property alongside the int, not as two out params) when the service definition allows no int to be specified (WCF-generated service definitions have, in my experience, worked as expected).

If you can't find a better solution, here's a workaround using partial classes: (this would have to be done any time you return a struct, not just ints)

public partial class MData
{
    public int ReturnAnInt()
    {
        int result;
        bool specified;
        this.ReturnAnInt(out result, out specified);
        if (!specified) throw new InvalidOperationException();
        return result;
    }
}

Update http://www.codeproject.com/Articles/323097/WCF-ASMX-Interoperability-Removing-the-Annoying-xx has a (somewhat klunky) solution, and informs us that the root cause is that WCF generates poor (arguably inaccurate) WSDLs - they have a minOccurs="0" on elements that really don't need it. Web References reads this as-is, and generates klunky code to deal with it, which is what you're trying to deal with. Based on his article, you can return this type instead of an int:

[MessageContract(IsWrapped = false)]
public class MyInt
{
    [MessageBodyMember]
    public int Result { get; set; }

    public static implicit operator MyInt(int i)
    {
        return new MyInt { Result = i };
    }

    public static implicit operator int(MyInt m)
    {
        return m.Result;
    }
}

Along with modifying the return type of the method:

[ServiceContract]
public interface IMData
{
    [OperationContract]
    MyInt ReturnAnInt();

    [OperationContract]
    String HelloWorld();
}
public class Service1 : IMData
{
    public MyInt ReturnAnInt()
    {
        return 4;
    }

    public string HelloWorld()
    {
        return "Hello World";
    }
}
like image 86
Tim S. Avatar answered Nov 11 '22 05:11

Tim S.


You import it as a Service Reference (with name space MData) instead Web Reference.

And use the below code,

MDataClient m = new MDataClient(); 
String helloWorld = m.HelloWorld(); 
int result = m.ReturnAnInt();

There is nothing wrong in your code. It should works fine if you add Service Reference and use the above snippet.

like image 35
Prasad Kanaparthi Avatar answered Nov 11 '22 07:11

Prasad Kanaparthi