|
Try this, looks like there is an API
Never underestimate the power of human stupidity
RAH
|
|
|
|
|
Hi,
I'm experimenting with a Web Service, using .NET 2.0 and IIS7. This is the entire Web Service source (demo1.asmx):
<%@ WebService Language="C#" Class="Demo1ns.Demo1class" %>
using System;
using System.Web.Services;
namespace Demo1ns {
[WebService (Name="Demo1", Description="Test color result")]
public class Demo1class {
[WebMethod (Description="Get a size")]
public System.Drawing.Size GetSize() {
return new System.Drawing.Size(12,34);
}
[WebMethod (Description="Get a color")]
public System.Drawing.Color GetColor() {
return System.Drawing.Color.Yellow;
}
}
}
Browsing to http://localhost/services/Demo1.asmx I get the web page presenting both methods. Invoking the first works fine as it returns:
<Size>
<Width>12</Width>
<Height>34</Height>
</Size>
However the GetColor method (both variants) fails and simply returns:
<Color/>
whatever I try, a Color is never returned.
So why is it handling Size and not Color, both are pretty much similar structs. How does one fix this?
|
|
|
|
|
Ummm... because the XmlSerializer doesn't know how you want it serialized?
What would you like?
Have you tried -- "#" + System.Drawing.Color.Yellow.ToArgb().ToString ("X8")
or similar?
Or you could use -- System.Drawing.Color.Yellow.ToKnownColor()
|
|
|
|
|
I'm new to the whole Xml and WebService things. I managed to transfer lots of types including structs (such as Size) and DateTime, without worrying about formatting. In what I'm after Color is the only problem, I don't really care how it arrives at the client as all structs become class instances anyway on the client side (the Size struct becomes a Size-like class with a Width and a Height member), so if I want to use them as CLR types, I need to convert them anyway.
So please show me the simplest magic that gives me say the ARGB value, or something similar while keeping the server-side code simple (I don't want to add method calls everywhere (there are multiple color returns throughout the code, sometimes inside a result struct) if I can avoid it, otherwise I would have communicated the ToArgb() result.
TIA
|
|
|
|
|
You needs codez? Sounds Urgentz.
Just for the heck of it, I was just playing around with a Color wrapper class, with decent results.
[System.SerializableAttribute()]
public class Color : System.Xml.Serialization.IXmlSerializable
{
private static readonly System.Text.RegularExpressions.Regex reg ;
static Color
(
)
{
reg = new System.Text.RegularExpressions.Regex
(
@"^\#(?'Digits'[0-F]{8})$"
,
System.Text.RegularExpressions.RegexOptions.IgnoreCase
) ;
return ;
}
public System.Drawing.Color color { get ; set ; }
public System.Xml.Schema.XmlSchema
GetSchema
(
)
{
return ( null ) ;
}
public void
WriteXml
(
System.Xml.XmlWriter Writer
)
{
Writer.WriteString ( "#" + this.color.ToArgb().ToString ( "X8" ) ) ;
return ;
}
public void
ReadXml
(
System.Xml.XmlReader Reader
)
{
System.Text.RegularExpressions.MatchCollection mat =
reg.Matches ( Reader.ReadString() ) ;
if ( mat.Count == 1 )
{
int i ;
if
(
System.Int32.TryParse
(
mat [ 0 ].Groups [ "Digits" ].Value
,
System.Globalization.NumberStyles.HexNumber
,
null
,
out i
)
)
{
this.color = System.Drawing.Color.FromArgb ( i ) ;
}
}
return ;
}
}
I'm think of adding implicit conversions to it (and making the field private).
I probably won't be able to respond again until tomorrow afternoon (UTC -7:00).
|
|
|
|
|
wow. I was hoping for a magic attribute of some kind, and you offer 70+ lines of code. It will be a while before I have digested that.
Thanks.
|
|
|
|
|
What's a line?
Besides, maybe I'll need it someday.
If you like it, please send chocolate.
|
|
|
|
|
PIEBALDconsult wrote: What's a line?
When you have some amount of text, anything that sits between the beginning and the end gets chopped into smaller amounts (called "lines") either by newlines (you know them well) or by wrapping (you may be unfamiliar with that phenomenon).
PIEBALDconsult wrote: If you like it, please send chocolate
I would like it a lot if the deserializer method would get transferred automatically from server to client, just like the data members are when using WSDL.EXE to obtain the proxy class. Unfortunately only data members get through, as Keith stated.
PIEBALDconsult wrote: please send chocolate
I'll try some first, just to make sure.
Thanks again for your input.
|
|
|
|
|
The XML you transfer in web service calls are pretty much just bags of data that allow you to populate objects at either end. Unfortunately this is hidden from the outset in the .net framework tools. For example, you can create a "proper" object with methods, but these are lost on the client side if you just use the generated proxy classes the messages are deserialized into (at least not without extra developer jiggery-pokery).
Web services should theoretically be interoperable (e.g. a Java/ C++ clients should be able to call a .net web-service) if the Color object was directly serializable across the web service it would break this pattern as it is specific to .net. You have two [easy] ways to handle your problem: send the hex colour value as a string or (better) convert it to an integer. Obviously this will involve a little work to re-create the System.Color value.
|
|
|
|
|
Keith Barrow wrote: developer jiggery-pokery
One of my favorite things.
Edit:
Keith Barrow wrote: if you just use the generated proxy classes
So don't do that.
modified on Saturday, September 25, 2010 1:14 PM
|
|
|
|
|
Yes, in the mean time I discovered no methods make it across when using WSDL.EXE, all the client gets for free is a little class with data members (which is great by itself). As MSDN isn't very informative on jiggery-pokery (I myself am not familiar with such techniques) I'll probably go for the ToArgb() approach.
Many thanks for the information.
|
|
|
|
|
That's up to the client.
I was playing around with WCF last April/May and didn't have such trouble. It helped that the client is in the same solution as the server, but that isn't necessary.
I've been meaning to get back to that; I'll see if there are any snippets I can send to demonstrate what I did.
Here's a quick little diagram based on my recollections:
|------------------|
| Client |
|------------------|
| |
| | <-- (Jiggery pokery happens here, but it's perfectly valid)
|---------| |
| Service | |
|---------| |
| |
| |
|------------------|
| Classes in a DLL |
|------------------|
|
|
|
|
|
OK, let me provide some context. I'm preparing a proposal specification for a CodeProject Web Service, something that would provide information about members, articles, messages, etc, so several existing and future applications (such as CP Vanity) could use it to their advantage, which would be much preferred over fetching web pages and scraping HTML. The proposal would be discussed amongst interested members before Chris might commit to it and implement it.
I expect the CP data model (as well as the subset we want access to) will evolve just like anything else, and I do want future old clients not to break under future new service versions. So I'm looking for a simple data model and a reliable communication protocol. I'm rather pleased with what IIS and WSDL are offering, as it works perfectly for basic types such as int, float, bool, string, as well as DateTime; it works pretty well for Size too.
FYI: WSDL.EXE is a utility that interrogates the service (using WSDL, an XML-based language) and creates a proxy class to be used by the client.
I mainly see two shortcomings:
1.
Color does not get through by default; it needs extra code at both ends. The extra code (e.g. client-side deserialization) cannot be transmitted automatically by WSDL, so there is a risk for future compatibility problems.
Color sure isn't the only type that wouldn't get across, however from the types I think we need, it is the only one that fails.
2.
Everything that was a class or struct at the server side becomes a class (never a struct) of a different type at the client. So one can send a System.Graphics.Size without any problem, but one gets a lookalike class instance at the client, so when a real System.Graphics.Size is required, one must recreate it. No big deal, just not very elegant.
I welcome your thoughts.
|
|
|
|
|
Luc Pattyn wrote: WSDL.EXE
For my experimentation last spring I used: svcutil http://localhost:8000/junkyard?wsdl /out:JunkyardClient.cs /noconfig
which creates the proxy class file (JunkyardClient.cs). I then wrap the proxy class in another class and add other stuff:
public class JunkyardProxy : JunkyardClient , Junk.Types.IJunkyard
The Client then uses that class:
using
(
Junk.Types.IJunkyard junk
=
new Junk.Types.JunkyardProxy()
)
{
|
|
|
|
|
I'm not familiar with svcutil.
Your example with WSDL would be WSDL http://localhost:8000/junkyard
but then maybe svcutil has some options that could be useful. I'll have to check that.
And yeah, I started thinking along such lines too, extending the proxy class. Chances are the wrapper class itself can be small and pretty stable as it probably only offers some utilitarian methods (one might consider using extension methods nowadays) regarding a few stubborn CLR types that don't get across properly without some help.
Are you using any reflection in your wrapper? Did you publish an actual article or example somewhere, something I could/should read?
Thanks.
|
|
|
|
|
Luc Pattyn wrote: Are you using any reflection in your wrapper?
Not at this time.
Luc Pattyn wrote: extending the proxy class
I was happily surprised that some of the generated classes are partial. If they all were I could simply add more partial code rather than wrap the classes.
Luc Pattyn wrote: Did you publish an actual article or example somewhere, something I could/should read?
I was going to, but I was in school all June/July and then got a job in August so until today I hadn't touched this stuff since May. I was thinking of writing "How to a write WCF Web Service the PIEBALD way" -- it's kinda funny that the test client outputs "Hello, World".
Anyway, I'll see about passing a color (colour) through this thing, see what happens, and let you know.
|
|
|
|
|
Great. Thanks a lot.
|
|
|
|
|
DAGNABIT!!
Microsoft hates me sucks today!
Without the Colour property, the service works just fine, the proxy file begins this way:
namespace Junk.Types
{
using System.Runtime.Serialization;
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.Runtime.Serialization", "4.0.0.0")]
[System.Runtime.Serialization.DataContractAttribute(Name="Record", Namespace="http://schemas.datacontract.org/2004/07/Junk.Types")]
public partial class Record : object, System.Runtime.Serialization.IExtensibleDataObject
::snip::
With the Colour property, the proxy file is totally different:
using System.Data;
::snip::
/// <remarks/>
[System.CodeDom.Compiler.GeneratedCodeAttribute("svcutil", "4.0.30319.1")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(Namespace="http://schemas.datacontract.org/2004/07/Junk.Types")]
public partial class Record
{
private System.Data.DataSet favouriteColourField;
::snip::
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute(IsNullable=true, Order=0)]
public System.Data.DataSet FavouriteColour
{
get
{
return this.favouriteColourField;
}
set
{
this.favouriteColourField = value;
}
}
::snip::
The Record class is no longer in the Junk.Types namespace! And other problems as well.
Maybe I should try it as a Color...
|
|
|
|
|
Hmm. I did get a DataSet at some point from WSDL.EXE too. And I didn't like it a bit.
I still have a lot to explore, I'm not giving in yet!
BTW: Keith Barrow just added quite a message to this thread, you might be interested as well.
|
|
|
|
|
Luc Pattyn wrote: DataSet ... And I didn't like it a bit.
Ditto.
Plus, when the property is a Color, it wants to serialize the Color type.
What I have now is I'm passing a string through the service, but accessing it as a Colour. It's pretty ugly... fugly, even.
Luc Pattyn wrote: Keith Barrow
If it's one the ones I already read, I already read it.
|
|
|
|
|
Luc Pattyn wrote: OK, let me provide some context. I'm preparing a proposal specification for a CodeProject Web Service, something that would provide information about members, articles, messages, etc, so several existing and future applications (such as CP Vanity) could use it to their advantage, which would be much preferred over fetching web pages and scraping HTML. The proposal would be discussed amongst interested members before Chris might commit to it and implement it.
Finally . WCF might be a better technology in the long run, you can still expose a vanilla SOAP front end from a WCF service, but WCF is designed to be extensible. IIRC WCF is much better at versioning.
Luc Pattyn wrote:
I expect the CP data model (as well as the subset we want access to) will evolve just like anything else, and I do want future old clients not to break under future new service versions.
This is tricky if the service doesn't allow for this at the outset.
Luc Pattyn wrote: I'm rather pleased with what IIS and WSDL are offering, as it works perfectly for basic types such as int, float, bool, string, as well as DateTime; it works pretty well for Size too.
You can send custom objects types too. The web services are "contract" based, if you let the service know you it returns as type of MyObject as long as this has been correctly defined it will serialize its properties properly. Some framework classes will get though as they are serializable, though obviously the instance changes
Luc Pattyn wrote: Color does not get through by default; it needs extra code at both ends.
This is a limitation of web services as a whole (a common interview question is explain the differences/conflicts between web services and Object Orientated systems - this is one of the points) even if you provide a client API that does the aforementioned jiggery-pokery , it doesn't guarantee against someone generating / creating their own client class. Conversely, it is good if your service is designed to cope with this, for example the Objective C required for an iPhone App wouldn't play with MS objects coming over the wire. This is why I suggested sending the value to the client, an iPhone app would be able to convert this to a hex value.
The "classical" way of proceeding with a web services is to convert the sever object model information into the serializable message classes (which flatten also often flatten out the object graph), send those across the wire. The client is then responsible for converting the deserialized [proxy generated] class out into the client's object model. It is possible to provide an API dll with the client classes pre-defined (it may even be desirable for .net clients, I have done this in the past) but it is a good idea to make the system interop with other technologies. I'd love an iPhone app, as would others I'd expect, not to mention Android phone users etc.
If you need a hand with this, feel free to e-mail me, I've a fair amount of WCF experience and a bit of Vanilla SOAP services stuff. I've felt the CP has lacked this feature for some time, so I'd be happy to help.
|
|
|
|
|
Hi Keith,
thanks for all the information and the insight.
I had set out to define the kind of information one would need from CodeProject, and having gotten that together to some degree, I decided to perform some mock-up experiments, as I often do while writing specs. So I created a little web service and discovered WSDL, and got a few things up and running quite easily, until I got surprised by DateTime and Size working and Color not working.
In the mean time I learned a lot, and reading your message and also PIEBALD's, I feel a hiatus in not knowing a thing about WCF, which I'll have to remedy soon.
You raised an excellent point about support for non-Windows clients. Even when they don't know about .NET or C#, we probably should not ignore them, in fact I'm inclined to fully consider them and to make their support no more difficult than necessary.
So I'm going to split my proposal efforts in two parts now; one concentrating on the functional level, to be discussed with people who already did some HTML scraping clients. The other about the underlying server-client and communication technology. I'll study and experiment some more, but I think I also may take you up on your kind offer.
Regards, and thanks again.
|
|
|
|
|
Luc Pattyn wrote: non-Windows clients ... should not ignore them
F-'em!
But seriously, WCF uses "industry standard protocols", so they shouldn't have any particular problem consuming .net Web Services. They'll have to do a bit of work regardless, there's not much you can do about that. What you can do is make things easier for .net practitioners, without unduly affecting non-.net practitioners.
|
|
|
|
|
PIEBALDconsult wrote: without unduly affecting non-.net practitioners
that sounds about right.
I guess you did read it then.
|
|
|
|
|
I have a copy of this[^].
|
|
|
|
|