开发者

Consumed WCF service returns void although return type (& value) specified

I have a WCF service that I am attempting to connect to via a console application for testing (although will move to WPF for the final interface). I have generated the proxy, added the service reference to my project in visual studio and I can see all the methods I have created in my WCF interface:

SupportStaffServiceClient client = new SupportStaffServiceClient("WSHttpBinding_ISupportStaffService");
client.myMethod(message);

However when I call a method, which in the WCF interface is specified as returning a value, the method returns void in the console application.

client.getMethod(message);

The WCF service method is definitely returning a message, I'm just unsure as to why the client cannot "see" the return.

[service code]

[ServiceContract(Namespace="http://localhost/supportstaff")]
public interface ISupportStaffService  
{
[OperationContract]
TutorMessage AddTutor(TutorMessage message);  
}

[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)]
public class SupportStaff : ISupportStaffService
{
    private ITutorService tutors;

    public SupportStaff()
    {

        // Create the bind开发者_JAVA技巧ing
        WSHttpBinding logBind = new WSHttpBinding();
        // Create the channel factory to the logging service
        ChannelFactory<ILogger> logFactory = new ChannelFactory<ILogger>(logBind, "http://localhost:8000/logger");
        // Create the connection to the logging service
        this.logger = logFactory.CreateChannel();

        // Create the binding
        WSHttpBinding tutorBind = new WSHttpBinding();
        // Create the channel factory to the Tutor service
        ChannelFactory<ITutorService> tutorFactory = new ChannelFactory<ITutorService>(tutorBind, "http://localhost:8001/tutors");
        // Create the connection to the Tutor service
        this.tutors = tutorFactory.CreateChannel();
    }
    TutorMessage ISupportStaffService.AddTutor(TutorMessage message)
    {
        // First log that we have received an add Tutor message
        // Create a log message
        LogMessage logMessage = new LogMessage();
        logMessage.Time = message.Time;
        logMessage.Message = "[Supprt Staff Service] Add Tutor message received";
        // Send the log message to the logging service
        logger.Log(logMessage);

        // Create a request to add the Tutor to the Tutor service
        TutorMessage request = new TutorMessage();
        request.Time = DateTime.Now;
        request.Tutor = message.Tutor;
        // Send the add Tutor message to the Tutor message
        tutors.AddTutor(request);

        // Display the message
        Console.WriteLine("Added Tutor " + message.Tutor.Number);
        // Log the message
        logMessage = new LogMessage();
        logMessage.Time = DateTime.Now;
        logMessage.Message = "[Support Staff Service] Added Tutor " + message.Tutor.Number;
        logger.Log(logMessage);

        // Create the return message
        TutorMessage toReturn = new TutorMessage();
        toReturn.Time = DateTime.Now;
        toReturn.Tutor = message.Tutor;
        // Return the return message
        return toReturn;
    }
}

[ServiceContract(Namespace = "http://localhost/tutors")]
public interface ITutorService
{
    [OperationContract]
    void AddTutor(TutorMessage message);
}

[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)]
public class TutorService : ITutorService
{
    private Dictionary<string, Tutor> tutors = new Dictionary<string, Tutor>();

    void ITutorService.AddTutor(TutorMessage message)
    {
        // First log the fact that we have received an Add message
        // Create the log message
        LogMessage logMessage = new LogMessage();
        logMessage.Time = message.Time;
        logMessage.Message = "[Tutor Service] Tutor add message received";
        // Send the log message to the logging service
        logger.Log(logMessage);

        // Now add the new Tutor to the collection of Tutors
        tutors[message.Tutor.Number] = message.Tutor;

        // Display message that Tutor is added
        Console.WriteLine("Added tutor : " + message.Tutor.Number);
        // Log the new Tutor
        logMessage = new LogMessage();
        logMessage.Time = DateTime.Now;
        logMessage.Message = "[Tutor Service] Added tutor : " + message.Tutor.Number;
        logger.Log(logMessage);
    }
}

[client code]

class Program
{
    static void Main(string[] args)
    {
        SupportStaffServiceClient client = new SupportStaffServiceClient("WSHttpBinding_ISupportStaffService");
        try
        {
            localhost.tutor.tutor t1 = new localhost.tutor.tutor();
            t1.name = "Big Dave";
            t1.number = "t123";
            DateTime time = DateTime.Now;

            client.AddTutor(ref time, ref t1);

            localhost.tutor.tutor t2 = new localhost.tutor.tutor();
            client.RetrieveTutor(ref time, ref t1);
        }
        catch (Exception ex)
        {
            Console.WriteLine("Error: " + ex.Message.ToString());
        }
        finally
        {
            Console.WriteLine("Press <RETURN> to exit");
            Console.ReadLine();
        }
    }
}

[svcutil generated code]

[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "3.0.0.0")]
public partial class SupportStaffServiceClient : System.ServiceModel.ClientBase<ConsoleApplication1.SupportStaffService.ISupportStaffService>, ConsoleApplication1.SupportStaffService.ISupportStaffService {

    public SupportStaffServiceClient() {
    }

    public SupportStaffServiceClient(string endpointConfigurationName) : 
            base(endpointConfigurationName) {
    }

    public SupportStaffServiceClient(string endpointConfigurationName, string remoteAddress) : 
            base(endpointConfigurationName, remoteAddress) {
    }

    public SupportStaffServiceClient(string endpointConfigurationName, System.ServiceModel.EndpointAddress remoteAddress) : 
            base(endpointConfigurationName, remoteAddress) {
    }

    public SupportStaffServiceClient(System.ServiceModel.Channels.Binding binding, System.ServiceModel.EndpointAddress remoteAddress) : 
            base(binding, remoteAddress) {
    }

    public string HelloWorld(string name) {
        return base.Channel.HelloWorld(name);
    }

    [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
    ConsoleApplication1.SupportStaffService.TutorMessage ConsoleApplication1.SupportStaffService.ISupportStaffService.AddTutor(ConsoleApplication1.SupportStaffService.TutorMessage request) {
        return base.Channel.AddTutor(request);
    }

    public void AddTutor(ref System.DateTime time, ref ConsoleApplication1.SupportStaffService.tutor tutor) {
        ConsoleApplication1.SupportStaffService.TutorMessage inValue = new ConsoleApplication1.SupportStaffService.TutorMessage();
        inValue.time = time;
        inValue.tutor = tutor;
        ConsoleApplication1.SupportStaffService.TutorMessage retVal = ((ConsoleApplication1.SupportStaffService.ISupportStaffService)(this)).AddTutor(inValue);
        time = retVal.time;
        tutor = retVal.tutor;
    }
}


I've never seen svcutil generate a method with ref parameters before - how did it do that? Anyway, it looks like you want to call the method above that in the generated code - this one takes and returns a TutorMessage object. So you could do

TutorObject returnedTutor = client.AddTutor(inputTutorObject);

Or, it looks like if you call the method with the ref parameters, as you're currently doing, the "return" value is put into those same ref parameters. So you pass in time and t1, call AddTutor, and now those variables you've passed in will contain the returned values. So, you could do

t1.name = "Big Dave";
t1.number = "t123";
DateTime time = DateTime.Now;

client.AddTutor(ref time, ref t1);

// time now contains the returned DateTime from the service
// t1 now contains the returned Tutor from the service


I had a similar problem where we'd forgottent to mark a custom MessageContract on our Response Class with the MessageBodyMemberAttribute our messageResponse Class didn't expose any members in it's data contract thus the Call to the service returned void.

Before...

[MessageContract]
public class MyCustomResponse
{
    public string Response { get; set; }
}
...

After...

[MessageContract]
public class MyCustomResponse
{
    [MessageBodyMember(Namespace = "http://MyNamespace")]
    public string Response { get; set; }
}

After adding the MessageBodyMember to the Response member, the svcutil generates code that hides the details of the custom Message Contract and just returns the Response as a string return value from my service's proxy.


I had the same problem with outer service (couldn't change its notation). I've added /mc parameter to svcutil - it helped.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜