[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 Studios 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 doesnt handle
inherited attributes correctly. I dont 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 interfaces .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 pipelines 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 doesnt 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 classs 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 dont need such attributes.
Unfortunately, we dont have good English research documentation about this
issue as Ive been required to write a couple of Italian paragraphs about
all this. But I dont 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