Edvin Tenovimas Edvin Tenovimas - 22 days ago 6
ASP.NET (C#) Question

Message contract is generated for all string-type methods

I'm using Visual Studio 15.3.5 and I'm trying to create a Web Service. I have selected ASP.NET Web Application (.Net Framework) with target framework: .Net framework 4.6.1. I have a pretty simple code in WebServiceMain.asmx file:

using System.Web.Services;

namespace WebServiceServer
{
[System.SerializableAttribute()]
[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
[System.ComponentModel.ToolboxItem(false)]

public class WebServiceMain : System.Web.Services.WebService
{
[WebMethod]
public int getSum(int a, int b)
{
return (a + b);
}

[WebMethod]
public string getName(string code)
{
return code;
}
}
}


I also have a different project that works as a client. I have added a service (let's call it ServiceReference1). I have updated service references and this is the part of a generated code:

namespace WebServiceClient.ServiceReference1 {


[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "4.0.0.0")]
[System.ServiceModel.ServiceContractAttribute(ConfigurationName="ServiceReference1.WebServiceMainSoap")]
public interface WebServiceMainSoap {

[System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/getSum", ReplyAction="*")]
int getSum(int a, int b);

[System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/getSum", ReplyAction="*")]
System.Threading.Tasks.Task<int> getSumAsync(int a, int b);

// CODEGEN: Generating message contract since element name code from namespace http://tempuri.org/ is not marked nillable
[System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/getName", ReplyAction="*")]
WebServiceClient.ServiceReference1.getNameResponse getName(WebServiceClient.ServiceReference1.getNameRequest request);

[System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/getName", ReplyAction="*")]
System.Threading.Tasks.Task<WebServiceClient.ServiceReference1.getNameResponse> getNameAsync(WebServiceClient.ServiceReference1.getNameRequest request);
}

// etc.
}


And also in client main() I have written:

ServiceReference1.WebServiceMainSoap clientReference = new ServiceReference1.WebServiceMainSoapClient();
Console.WriteLine(clientReference.getSum(2, 6));
Console.WriteLine(clientReference.getName("T100"));


The problem is that any method that returns string is not formatted properly in client side. For example,
clientReference.getSum(2, 6)
works fine but
clientReference.getName("T100")
does not and I get:


CS1061 'WebServiceMainSoap' does not contain a definition for
'getModuleName' and no extension method 'getModuleName' accepting a
first argument of type 'WebServiceMainSoap' could be found (are you
missing a using directive or an assembly reference?)

CS1503 Argument 1: cannot convert from 'string' to 'WebServiceClient.ServiceReference1.getNameRequest


In generated code I see this comment:
// CODEGEN: Generating message contract since element name code from namespace http://tempuri.org/ is not marked nillable
so I assume I need to write
nillable
somewhere, but I have tried something like in here, in here and searched in here but it doesn't work because WSDL file is found only in client application but is being overwritten if I update service references.

I would like something like this to solve (which, of course, is not valid):

[WebMethod(nillable = true)]
public string getName(string code)
{
return code;
}

Win Win
Answer Source

By default, ASMX uses HttpPost method instead of HttpGet. If you want to allow HttpGet, you will need [ScriptMethod(UseHttpGet = true)].

FYI: If you want to pass string as parameter, I highly suggest not to use HttpGet which could cause URL invalid.

[WebMethod]
[ScriptMethod(UseHttpGet = true)]
public int getSum(int a, int b)
{
    return (a + b);
}

[WebMethod]
public string getName(string code)
{
    return code;
}

Another thing is since you want to return string, the service requires getNameRequest object, and returns getNameResponse object.

getNameResponse response = 
   clientReference.getName(new getNameRequest(new getNameRequestBody("T100")));
Console.WriteLine(response.Body.getNameResult);