Client code unwraps the class that is passed. (from previous board)

Topics: General Discussion Forum
Jan 25, 2007 at 7:14 PM
This is under Service Interface folder:

I have the following 3 Data Contracts
public partial class ClubMemberInformation
public partial class CreditCardInformation
public partial class WinePreference

I have the following 2 Message Contracts
public class RegisterClubMemberRequest
{
public DataContracts.WinePreference Preference;
public DataContracts.ClubMemberInformation MemberDetails;
public DataContracts.CreditCardInformation CreditCardDetails;
}
public class RegisterClubMemberResponse
{
public System.String MemberNumber;
public System.Int32 ConfirmationCode;
}

I have the following Service Contract
public interface IClubMembershipService
{
public RegisterClubMemberResponse RegisterNewMember(RegisterClubMemberRequest request)
{
// My code
}
}



This is under Tests folder:

Now I use the WCF "Add Service Reference" Recipe to create the proxy for the client. It generates the following code:
public partial class ClubMembershipServiceClient : System.ServiceModel.ClientBase<Coho.ClubServices.Membership.Client.ClubMembershipService.IClubMembershipService>, Coho.ClubServices.Membership.Client.ClubMembershipService.IClubMembershipService
{
public string RegisterNewMember(Coho.ClubServices.Membership.Client.ClubMembershipService.WinePreference Preference, Coho.ClubServices.Membership.Client.ClubMembershipService.ClubMemberInformation MemberDetails, Coho.ClubServices.Membership.Client.ClubMembershipService.CreditCardInformation CreditCardDetails, out int ConfirmationCode)
{
Coho.ClubServices.Membership.Client.ClubMembershipService.RegisterClubMemberRequest inValue = new Coho.ClubServices.Membership.Client.ClubMembershipService.RegisterClubMemberRequest();
inValue.Preference = Preference;
inValue.MemberDetails = MemberDetails;
inValue.CreditCardDetails = CreditCardDetails;
Coho.ClubServices.Membership.Client.ClubMembershipService.RegisterClubMemberResponse retVal = ((Coho.ClubServices.Membership.Client.ClubMembershipService.IClubMembershipService)(this)).RegisterNewMember(inValue);
ConfirmationCode = retVal.ConfirmationCode;
return retVal.MemberNumber;
}
}


So the question is why are the Message Contracts being unwrapped? Why are the DataContracts becoming the parameters of the Web Method?

Shouldn't the proxy for the Web Method be:
public RegisterClubMemberResponse RegisterNewMember(RegisterClubMemberRequest)
{
...
}


Thanks,
Mark
Jan 26, 2007 at 7:21 PM
Is the answer to use the /messageContract option for svcutil.exe?

For example:
svcutil.exe http://localhost:2044/Coho.ClubServi
ces.Membership.Host/ClubMembershipService.svc /messageContract

Produces
public partial class ClubMembershipServiceClient : System.ServiceModel.ClientBase<IClubMembershipService>, IClubMembershipService
{
public RegisterClubMemberResponse RegisterNewMember(RegisterClubMemberRequest request)
{
return base.Channel.RegisterNewMember(request);
}
}

Where without
svcutil.exe http://localhost:2044/Coho.ClubServi
ces.Membership.Host/ClubMembershipService.svc
It Produces:
public partial class ClubMembershipServiceClient : System.ServiceModel.ClientBase<IClubMembershipService>, IClubMembershipService
{
public string RegisterNewMember(coho.clubservices.membership.datacontracts.2007.01.WinePreference Preference, coho.clubservices.membership.datacontracts.2007.01.ClubMemberInformation MemberDetails, coho.clubservices.membership.datacontracts.2007.01.CreditCardInformation CreditCardDetails, out int ConfirmationCode)
{
RegisterClubMemberRequest inValue = new RegisterClubMemberRequest();
inValue.Preference = Preference;
inValue.MemberDetails = MemberDetails;
inValue.CreditCardDetails = CreditCardDetails;
RegisterClubMemberResponse retVal = ((IClubMembershipService)(this)).RegisterNewMember(inValue);
ConfirmationCode = retVal.ConfirmationCode;
return retVal.MemberNumber;
}
}


Thanks for any help.
Jan 26, 2007 at 7:47 PM
For the svcutil.exe does the option
/messageContract - Generate Message Contract types. (Short Form: /mc)

a replacement for the /tm option?

From older Indigo documentation
Generating Client Code for Typed Messages
The Svcutil tool generates typed message classes by default. If your service uses typed messages, specify the /tm switch on the Svcutil command line to generate the appropriate typed message classes.

I no longer see /tm as an option for svcutil.

And if /messageContract is the option I want, is this a Best Practice to have the proxy of the method take Message Contracts as parameter and return type or is it Best Practice for the Method to take the Data Contracts as parameters?

Under the ASMX version of the Software Factory it uses Message Types as the parameter and return type to the Method in the generated proxy.

What is best?
How do you reconcile the two, method in the proxy for ASMX and the method in the proxy for WCF?
Do you reconcile the two?


Jan 26, 2007 at 9:11 PM
Found the following in the WCF Guidance Package Source Code:
Source file : GenerateProxyAction.cs

#region ConfigurableAction Implementation
/// <summary>
/// See <see cref="M:Microsoft.Practices.RecipeFramework.IAction.Execute"/>.
/// </summary>
public override void Execute()
{
if(String.IsNullOrEmpty(this.svcUtilPath))
{
//TODO: Add Resources
throw new ArgumentException(Properties.Resources.InvalidArgumentException, "SvcUtilPath");
}

Process process = new Process();
process.StartInfo.FileName = this.SvcUtilPath;
process.StartInfo.Arguments = string.Format( CultureInfo.InvariantCulture, "/noLogo /o:{0} /config:{1} {2}", this.proxyFile, this.configFile, this.serviceUri);
process.StartInfo.UseShellExecute = false;
process.StartInfo.RedirectStandardError = true;
process.StartInfo.CreateNoWindow = true;
process.Start();

process.WaitForExit();

this.exitCode = process.ExitCode;
}

//Not Implemented
public override void Undo()
{
//Not Implemented
}

#endregion

It appears that the following options are hard coded for svcutil.exe:
/noLogo /o:{0} /config:{1}

Is there a way to add additional svcutil options to the Recipe without updating the source code?
Can they be added in some xml config file?

Jan 26, 2007 at 10:26 PM
That class is currently not used and was added just for testing and demo purposes.
For the time being there's no way to modify the proxy generation out of config files/recipes. However, it's pretty straightforward to change an argument in a class and generate a service proxy with typed messages.
Steps:
Open the SecureClientConfigPresenter class and go to OnInspectMetadataCompleted method.
Look for, ContractGenerationOptions options = new ContractGenerationOptions();
(Line 109) and after that add the following code:
options.GenerateTypedMessages = true;
You may also explore other settings here.
Recompile the GP and try generating the service proxy again.

Hernan
Jan 29, 2007 at 4:23 PM
Thank You I have found where to update the code.

However, more importantly could someone please comment on what is the Best Practice and why the difference between the ASMX and WCF versions.

For the svcutil.exe does the option
/messageContract - Generate Message Contract types. (Short Form: /mc)

a replacement for the /tm option?

From older Indigo documentation
Generating Client Code for Typed Messages
The Svcutil tool generates typed message classes by default. If your service uses typed messages, specify the /tm switch on the Svcutil command line to generate the appropriate typed message classes.

I no longer see /tm as an option for svcutil.

And if /messageContract is the option I want, is this a Best Practice to have the proxy of the method take Message Contracts as parameter and return type or is it Best Practice for the Method to take the Data Contracts as parameters?

Under the ASMX version of the Software Factory it uses Message Types as the parameter and return type to the Method in the generated proxy.

What is best?
How do you reconcile the two, method in the proxy for ASMX and the method in the proxy for WCF?
Do you reconcile the two?