I'm afraid I'm out of ideas what's going on here. My scenario is quite
simple - I declare a string resource, which I want to return as an XML
data contract (in order not to make a distinction of cases when it
comes to GETting resources):
ResourceSpace.Has.ResourcesOfType<string>()
.AtUri(uris.CreateFolderPathUri)
.HandledBy<FolderPathCreationHandler>()
.AsXmlDataContract();
Now, if I enter the URI into the browser, everything is fine - I get
the string wrapped into a data contract. However, if I try to GET the
resource in code, I end up with a resource of type text/plain that
returns the bare string. As far as I can tell, my request is exactly
the same, and I'm debugging the exact same server process (OR runs in
a separate VS instance).
The debug output of OR is a 100% equal, with one difference: The
number of available codecs (5 vs. 3) and the selection of the codec.
However, again: I only have one instance of OR running, and the debug
output was taken from the same session, and both invocations hit the
break point in VS.
Browser request:
12-[2010-03-10 18:21:49Z] Information(0) Selected codec
XmlDataContractCodec out of 5 codecs for entity of type String and
negotiated media type application/xml; q=0.5.
Programmatic GET (separate instance of VS)
8-[2010-03-10 18:19:31Z] Information(0) Selected codec TextPlainCodec
out of 3 codecs for entity of type String and negotiated media type
text/plain; q=0.5.
This practically screams that I'm overlooking something, but I guess I
need a pointer into the right direction. Any idea what's happening
here?
Thanks for your advice,
Philipp
First, if your client wants application/xml, it's the client's job to put Accept: application/xml as a request header.
Second, in your situation I assume the programmatic get is using an Accept: */* or no accept header at all, in which case both the xml and the text/plain codecs will be registered. When two codecs have the same quality parameter (here 0.5), the behaviour should fallback to selecting the closest distance between the type the codec is registered for (here string for the xml codec, aka distance of 0, object for the text/plain codec, aka distance of 1). This doesn't seem to be the caase in this example, so I'd be happy for you to add a bug to TRAC for that specific scenario.
And if you want to change the default, just bump up the q value for the codec you want: .AsXmlDataContract().ForMediaType("application/xml;q=1") for example.
Also note that you should really consider using a custom media type rather than application/xml.
Thanks for the tips. But what's with my handler that *explicitly*
declares the resource as an XML data contract? That shouldn't be
ignored, should it? (And even if I declare the resource with the
DataContractCodec instead, it still uses the other codec). What's odd
is the reduced number of available codecs - I assume OR did some kind
of filtering before even looking at the resource (based on the
headers?).
However, what's more important: I wouldn't want my clients to be
responsible to set the headers anyway (I'm only the consumer of the
service in my test scenario). My service provides a resource,
serialized in XML that can be retrieved via HTTP GET on a given URI -
shouldn't that be sufficient? After all, all my other resources (not
of type string) are properly returned as data contracts in all
scenarios, and I never seen an service documentation that went beyond
URIs and methods. Currently, I don't even get the same results when
sending the GET via FireFox (XML) vs. IE (plain text), which both
accept XML.
Shouldn't this be the responsibility of the framework depending on the
handler configuration without having to do further customizations?
Here's what's requested/returned with IE
GET http://127.0.0.1:56789/folders/combinedpath?parentfolder=/&foldername=readme.txt
HTTP/1.1
Accept: application/x-ms-application, image/jpeg, application/xaml
+xml, image/gif, image/pjpeg, application/x-ms-xbap, application/
vnd.ms-excel, application/vnd.ms-powerpoint, application/msword,
application/x-shockwave-flash, */*
Accept-Language: de-CH
User-Agent: Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; WOW64;
Trident/4.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR
3.0.30729; Media Center PC 6.0; InfoPath.2; .NET4.0C; .NET4.0E)
Accept-Encoding: gzip, deflate
Connection: Keep-Alive
Host: 127.0.0.1:56789
HTTP/1.1 200 OK
Server: ASP.NET Development Server/9.0.0.0
Date: Wed, 10 Mar 2010 19:08:52 GMT
X-AspNet-Version: 2.0.50727
Content-Length: 11
Cache-Control: private
Content-Type: text/plain; charset=ISO-8859-1
Connection: Close
/readme.txt
And here's what's requested / returned with Firefox:
GET http://127.0.0.1:56789/folders/combinedpath?parentfolder=/&foldername=readme.txt
HTTP/1.1
Host: 127.0.0.1:56789
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.2)
Gecko/20100115 Firefox/3.6
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/
*;q=0.8
Accept-Language: en-us,en;q=0.5
Accept-Encoding: gzip,deflate
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
Keep-Alive: 115
Connection: keep-alive
HTTP/1.1 200 OK
Server: ASP.NET Development Server/9.0.0.0
Date: Wed, 10 Mar 2010 19:12:35 GMT
X-AspNet-Version: 2.0.50727
Content-Length: 131
Cache-Control: private
Content-Type: application/xml
Connection: Close
<?xml version="1.0" encoding="utf-8"?>
<string xmlns="http://schemas.microsoft.com/2003/10/Serialization/">/
readme.txt</string>
It's not odd, the accept headers are different, OpenRasta has different set of choices for rendering based on the Accept header.
Content negotiation is at the core of OpenRasta, so the Accept header *is* very important.
On a side note, you don't declare handlers in your configuration, you declare resources. :)
> However, what's more important: I wouldn't want my clients to be
> responsible to set the headers anyway (I'm only the consumer of the
> service in my test scenario).
It's HTTP. If you don't want your clients to deal with HTTP, you need to control what codecs are associated with a resource. In a word, you need to control the default, you will only be able to do it on your own type.
Aka, don't use strings if you want to control what serializations are available for a resource.
> ... I never seen an service documentation that went beyond
> URIs and methods.
Meh. Two wrongs don't do a right, declaring URIs and methods is unrestful, not useful, tightly coupled... As you can imagine, none of that will make it to anything doing with OpenRasta, it's just wrong.
A good ReST service declares a custom media type, which in OpenRasta you map to custom resource types associated with a custom media type. Navigation is done by following links and forms inside your media type, so you never know in advance what URIs and methods are going to be available.
> Currently, I don't even get the same results when
> sending the GET via FireFox (XML) vs. IE (plain text), which both
> accept XML.
> Shouldn't this be the responsibility of the framework depending on the
> handler configuration without having to do further customizations?
No. It's the job of the client to announce to the server the formats it understands so content negotiation can happen. It's the job of the resource owner to decide what media types are available for a resource. Its the job of the framework to make content negotiation easy on consumers and producers.
I see your point, but I'm not sure whether this will help OR in the
long run - the variance between declaration, discovery and chosen
serialization strategies might present a real issue once OR hits the
market. I think the possibilities of OR are huge, but then, what I
would primarily use it for is maybe the POD services you've been
referring to sometimes (although Google couldn't tell me what this
means, actually ;)
I followed your recommendation about custom types, and ended up with a
hack by just wrapping my string into a simple generic DTO. In the end,
it makes my API much more simpler than having to do additional coding
on both server and client side in order to receive my data in XML.
Thanks for your help!
Philipp
In case anybody's running into the same issue, here's the wrapper:
public class Wrapped<T>
{
public T Value { get; set; }
public Wrapped()
{
}
public Wrapped(T value)
{
Value = value;
When you do that, OpenRasta won't be able to help you very much, as it requires you to do so, as it is after all a Resource-Oriented framework.
If you only want a quick way to do xml over http that's focusing on what code gets executed, (aka POD services), you can already do that with asmx with less friction and I'd recommend just using this.
In other words, if it hurts when you do something, stop doing it.
-----Original Message-----
From: open...@googlegroups.com [mailto:open...@googlegroups.com] On Behalf Of Philipp Sumi