[Mono-aspnet-list] R: creating new web service from wsdl

Ing. Antonio Anzivino anzivino at studenti.unina.it
Fri Sep 3 09:54:03 EDT 2010


Hello,

You have to use override keyword when you need to implement a method that
was declared abstract in an abstract class (see C# reference).

I have had a very similar problem with the Logbus-ng project. In your case,
you compiled the WSDL into an abstract class. I used Visual Studio’s WSDL
and got an interface (public interface 
), but almost the same error at
runtime.

 

In a few words, if you implement the web service from 3rd party ASMX (or a
“standardized” ASMX you create with a different editor) Mono doesn’t handle
inherited attributes correctly. I don’t remember if your error is the same
as mine, but we had cross-platform issues because .NET handles everything
correctly.

In order to get a general and tested tutorial on how to work with 3rd party
WSDL, please look at what I had to do in my code: I had to understand the
differences between Mono 2.7 and .NET 3.5

 

1.       Compiled source file (example code
<http://logbus-ng.svn.sourceforge.net/viewvc/logbus-ng/trunk/logbus-core/It.
Unina.Dis.Logbus/Schemas/logbus-control.wsdl?revision=305&view=markup> )
with wsdl /server and get the interface’s .cs file

2.       Decorated the attributes with “#if MONO” attributes in order to
ignore them when running in Mono (example code
<http://logbus-ng.svn.sourceforge.net/viewvc/logbus-ng/trunk/logbus-core/It.
Unina.Dis.Logbus/IChannelManagement.cs?revision=308&view=markup> )

3.       Created the web service as a class that inherits the given
interface, your IDE shall create all method prototypes for you

4.       Copied all the attributes and decorated them with #if MONO in order
to compile attributes only when running in Mono (example code
<http://logbus-ng.svn.sourceforge.net/viewvc/logbus-ng/trunk/logbus-core/It.
Unina.Dis.Logbus/WebServices/ChannelManagementService.cs?revision=308&view=m
arkup> )

5.       When compiling in Mono, make sure that the MONO compilation
constant is defined in xbuild, usually creating a proper build configuration

 

What does it do? If you now look at both the last two code examples at the
same time, you can notice that if you compile the solution with MONO flag
enabled, the interface gets compiled as a plain C# interface without
attributes, but the concrete class, inheriting WebService, gets compiled
with all the attributes it needs. When compiling in .NET, these attributes
are instead inherited from the base class. This has only to do with the
behaviour of the reflector inside the ASP.NET pipeline’s WSDL skeleton: MS
and Mono implementations are different, and MS scans for Web Service
attributes through all the hierarchy of the concrete class. If you just
duplicate the attributes without setting the #if flags, then .NET comes
paranoid as it finds the same attributes declared more than one time, which
is illegal; this time, Mono looks for the attributes only within the final
class and doesn’t say anything about the presence of the attributes in the
ancestor classes.

 

Please also bear in mind that when you create a “good” WSDL with
input/output parameters defined as types from a well-formed XML Schema,
wsdl.exe adds extra attributes to input or return parameters of the methods,
like the following one from 3rd code example:

[System.Xml.Serialization.XmlElementAttribute("channel-creation", Namespace
= "http://www.dis.unina.it/logbus-ng/wsdl")] ChannelCreationInformation
channelcreation

 

These attributes define serialization constraints for classes. They are not
useful if you use strings, integers, etc. but they are required to be at
least in the concrete class’s body, no matter what you do from the
interface, otherwise you will eventually get an error when invoking the
method. In your case of a “MathService” you don’t need such attributes.

Unfortunately, we don’t have good English research documentation about this
issue as I’ve been required to write a couple of Italian paragraphs about
all this. But I don’t remember if I filed a bug for this.

 

I hope you can learn extra skills from my experience with web services,

Antonio Anzivino

 

Da: Devin Venable [mailto:venable.devin at gmail.com] 
Inviato: giovedì 2 settembre 2010 19:41
A: Alberto León
Cc: mono-aspnet-list at lists.ximian.com
Oggetto: Re: [Mono-aspnet-list] creating new web service from wsdl

 

I believe I've answered my own question, so for the record, it seems you
need to also redeclare the [WebMethod] declaration in braces.  (What do you
call these things?)  Here's a complete example that works. (Imagine that
MathServiceBase.cs was generated by running wsdl2 from existing interface
file.)

 

MathServiceBase.cs:

 

using System;

using System.Web;

using System.Web.Services;

 

namespace MathService

{

            [WebService (Namespace = "http://tempuri.org/NumberService")]

            public abstract partial class MathServiceBase : WebService

            {

                        [WebMethod]

                        public abstract int AddNumbers (int number1, int
number2);

                        

 

                        [WebMethod]

                        public abstract int SubtractNumbers (int number1,
int number2);

            }

}

 

Now you have to inherit, add override to the methods, and copy the [ ]
blocks from the generated file.

 

MathService.asmx:

 

<%@ WebService Language="C#" Class="MathService.MathService" %>

 

using System;

using System.Web.Services;

 

namespace MathService

{

            [WebService (Namespace = "http://tempuri.org/NumberService")]

            public class MathService : MathServiceBase

            {

                        [WebMethod]

                        public override int AddNumbers (int number1, int
number2)

                        {

                                   return number1 + number2;

                        }

 

                        [WebMethod]

                        public override int SubtractNumbers (int number1,
int number2)

                        {

                                   return number1 - number2;

                        }

            }

}

 

2010/9/2 Devin Venable <venable.devin at gmail.com>

And with NEW I get this error:

 

TestService.asmx.cs(58,58): Error CS0533:
`blah.blah.EnrollTransmitter(blah.TransmitterEnrollmentRequest)' hides
inherited abstract member
`blah.blahGenerated.EnrollTransmitter(blah.WidgetEnrollmentRequest)'
(CS0533) (TestSOAP2)

 

 

2010/9/2 Devin Venable <venable.devin at gmail.com>

When I don't inherit, I get this compile warning:

 

TestService.asmx.cs(54,54): Warning CS0114:
`MyService.MyService.EnrollTransmitter(GTPServices.WidgetEnrollmentRequest)'
hides inherited member
`MyService.MyServiceGenerated.EnrollTransmitter(TestService.WidgetEnrollment
Request)'. To make the current member override that implementation, add the
override keyword. Otherwise add the new keyword (CS0114) (TestSOAP2)

 

Should I use the new keyword?

 

2010/9/2 Alberto León <leontiscar at gmail.com>

Y do not need to override WidgetEnrollmentResponse.

 

2010/9/2 Devin Venable <venable.devin at gmail.com>

Simple inheritance didn't seem to work, at least not using my pattern.  Here
is a fragment of the code (variable names changed to protect the innocent):

 

In TestService.asmx:

 

<%@ WebService Language="C#" Class="MyService.MyService" %>

 

In MyServiceGenerated.cs:

 

namespace MyService

{

 

/// <remarks/>

[System.Web.Services.WebServiceAttribute(Namespace="http://tempuri.org/")]

[System.Web.Services.WebServiceBinding(Name="BasicHttpBinding_IMyServices",
Namespace="http://tempuri.org/")]

public abstract partial class MyServiceGenerated :
System.Web.Services.WebService {

    

    [System.Web.Services.WebMethodAttribute()]

 
[System.Web.Services.Protocols.SoapDocumentMethodAttribute("http://tempuri.o
rg/IMyServices/EnrollTransmitter", RequestNamespace="http://tempuri.org/",
ResponseNamespace="http://tempuri.org/",
ParameterStyle=System.Web.Services.Protocols.SoapParameterStyle.Wrapped,
Use=System.Web.Services.Description.SoapBindingUse.Literal)]

    [return: System.Xml.Serialization.XmlElementAttribute(IsNullable=true)]

    public abstract WidgetEnrollmentResponse
EnrollTransmitter([System.Xml.Serialization.XmlElementAttribute(IsNullable=t
rue)] WidgetEnrollmentRequest request);

    ...

 

In TestService.asmx.cs:

 

namespace MyService

{

public class MyService : MyServiceGenerated

{

 

public override WidgetEnrollmentResponse
EnrollTransmitter(WidgetEnrollmentRequest request)

{

                        // TODO implement

return null;

}

 

 

Okay, so now when I deploy this, the web page shows up and there are no
visible service methods.  What am I doing wrong, or better yet, what is the
best practice for what I'm trying to do?

 

And thanks for the help!

 

2010/9/2 Alberto León <leontiscar at gmail.com>

 

You need inherit MyServices in other class.
An abtract class can't be instantiated, created, and can't store data.
Allways need to be inherited.



2010/9/2 Devin Venable <venable.devin at gmail.com>

Background:  Linux developer new to .NET.  In the past I've successfully
deployed simple web services by creating asmx files and running them under
Apache via XSP.

Need: Create web service implementation from WSDL defined by 3rd party

 

This is what I've tried so far...

 

1. Used wsdl2 to generate server stubs.

 

wsdl2 -server MyServices.wsdl 

Web Services Description Language Utility

Mono Framework v2.0.50727.1433

 

There where some warnings while generating the code:

 

  MyServices.wsdl

    - This web reference does not conform to WS-I Basic Profile v1.1

        R2718: A wsdl:binding in a DESCRIPTION MUST have the same set of

        wsdl:operations as the wsdl:portType to which it refers.

          * Binding 'BasicHttpBinding_IMyServices', in Service Description

            ' <http://tempuri.org/> http://tempuri.org/'

 

 

(should this warning make me nervous?)

 

2. Renamed resulting cs file to MyServices.asmx

3. Added header to file:

 

<%@ WebService Language="c#" Codebehind="MyServices.asmx.cs"
Class="MyServices" %>

 

This KINDA worked.  I can load up and view the page in my browser:

 

 <http://localhost/MyServices.asmx> http://localhost/MyServices.asmx

 

But when I try to invoke a method on the service from the web forms that
display, I get a message like:

 

500 - Internal Server Error

System.MissingMethodException: Cannot create an abstract class 'MyServices'.
  at System.Activator.CheckAbstractType (System.Type type) [0x00000] 
  at System.Activator.CreateInstance (System.Type type, Boolean nonPublic)
[0x00000] 
  at System.Activator.CreateInstance (System.Type type) [0x00000] 
  at System.Web.Services.Protocols.WebServiceHandler.CreateServerInstance ()
[0x00000] 
  at System.Web.Services.Protocols.HttpSimpleWebServiceHandler.Invoke
(System.Web.Services.Protocols.LogicalMethodInfo method, System.Object[]
parameters) [0x00000] 
  at
System.Web.Services.Protocols.HttpSimpleWebServiceHandler.ProcessRequest
(System.Web.HttpContext context) [0x00000] 

 

 

Though I'm not a .NET developer, I'm a developer and can see why trying to
create an instance of an abstract class would be an issue.  What I'm not
clear on is what is the best

pattern to implement the concrete methods.   I've tried implementing a
concrete class with all of the methods in the asmx and made the class
inherit from the class generated by

wsdl2, but when I run the application, the methods disappear.  I'm guessing
I need to copy all of the blocks that look like this into the concrete
class:

 

 [System.Web.Services.WebMethodAttribute()]

 
[System.Web.Services.Protocols.SoapDocumentMethodAttribute("http://tempuri.o
rg/IGTPServices/EnrollTransmitter", RequestNamespace="http://tempuri.org/",
ResponseNamespace="http://tempuri.org/",
ParameterStyle=System.Web.Services.Protocols.SoapParameterStyle.Wrapped,
Use=System.Web.Services.Description.SoapBindingUse.Literal)]

    [return: System.Xml.Serialization.XmlElementAttribute(IsNullable=true)]

 

If anyone can point me to a short tutorial for creating a web service in
Mono using an existing WSDL, or give me tips herre, I would appreciate it.

 

 

_______________________________________________
Mono-aspnet-list mailing list
Mono-aspnet-list at lists.ximian.com
http://lists.ximian.com/mailman/listinfo/mono-aspnet-list

 

 


_______________________________________________
Mono-aspnet-list mailing list
Mono-aspnet-list at lists.ximian.com
http://lists.ximian.com/mailman/listinfo/mono-aspnet-list

 

 

 

 

-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.ximian.com/pipermail/mono-aspnet-list/attachments/20100903/5b9220f2/attachment-0001.html 
-------------- next part --------------
A non-text attachment was scrubbed...
Name: smime.p7s
Type: application/pkcs7-signature
Size: 4496 bytes
Desc: not available
Url : http://lists.ximian.com/pipermail/mono-aspnet-list/attachments/20100903/5b9220f2/attachment-0001.bin 


More information about the Mono-aspnet-list mailing list