How to deserialize object from OData Atom feed? - wcf

I am trying to parse response from an OData REST service. When response is in JSON format, it is easy to use ReadAsJsonDataContract method from WCF REST starter kit. However things seem to be more complicated in case the response is an Atom feed. This is an example:
<?xml version="1.0" encoding="iso-8859-1" standalone="yes"?>
<entry xml:base="http://localhost:64172/BookshopService.svc/" xmlns:d="http://schemas.microsoft.com/ado/2007/08/dataservices" xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata" xmlns="http://www.w3.org/2005/Atom">
<id>http://localhost:64172/BookshopService.svc/Books(89)</id>
<title type="text"></title>
<updated>2010-11-08T09:44:21Z</updated>
<author>
<name />
</author>
<link rel="edit" title="Books" href="Books(89)" />
<link rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/OrderLines" type="application/atom+xml;type=feed" title="OrderLines" href="Books(89)/OrderLines" />
<category term="BookshopModel.Books" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" />
<content type="application/xml">
<m:properties>
<d:Id m:type="Edm.Int32">89</d:Id>
<d:Author>Martin Fowler</d:Author>
<d:Title>Analysis Patterns</d:Title>
<d:Price m:type="Edm.Decimal">50.20</d:Price>
</m:properties>
</content>
</entry>
So the actual object is serialized in "content/m:properties" element. And of course this can't be handled by DataContractSerializer that expects a different schema.
Does anyone know what technique can be used to deserialize the content of OData atom m:properties element?

WCF Data Services has a client which can be used to consume the responses and materialize CLR object from those. Take a look at the System.Data.Services.Client.DataServiceContext class and all related classes.
In fact, in VS you can "Add Service Reference" to your OData services and it will generate client-side classes for the services as well as a derived class from the DataServiceContext for you to use.
If you already have the client side classes you can use the DataServiceContext.Execute<T> method to issue any query and materialize its results into the client side types.

Related

Register component with PerWcfOperation lifestyle (using config file)

How is it possible to register a component in Castle Windsor 3.0 with PerWcfOperation lifestyle? I could only find examples of registering components in code.
Here is my config:
<castle>
<facilities>
<facility id="wcf"
type="Castle.Facilities.WcfIntegration.WcfFacility, Castle.Facilities.WcfIntegration" />
</facilities>
<components>
<component id="Settings"
service="SomeNamespace.IApplicationSettings, SomeAssembly"
type="SomeOtherNamespace.ApplicationSettings, SomeOtherAssembly"
lifestyle="PerWcfOperation" />
</components>
</castle>
When I try to do it as in the config above, I get ConvertException 'Could not convert from 'PerWcfOperation' to Castle.Core.LifestyleType.'
It's not supported because XML configuration is considered legacy.
Use configuration in code instead.
XML and code are generally mostly equivalent (where that's possible) although this case is an exception - there's currently no way out of the box to specify scoped lifestyle (and that is what per-wcf-operation lifestyle is) in XML.
Obviously that doesn't mean there's no way to get this working. With a simple IContributeComponentModelConstruction you can implement support for that in a few LOC.

Easier way to Call a SOAP Service with Many Parameters?

My web services are rusty so I hope I'm just missing something kind of obvious.
I have a WCF service that, in part, relays calls it receives to a third party SOAP service. The service receives an object that matches the body of the SOAP message that needs to be sent.
I've added a service reference based on the SOAP service's WSDL to the project and created and instance of the service proxy class. The service method I want to call has 30+ parameters.
I could call it with MyService.TheMethod(obj.value1, obj.value2, obj.value3...), but it would be nice to just pass the original object on or XML serialize it and pass the XML as a body.
Is there something that would allow an easier approach or do I need to individually pass obj's properties onto the SOAP method?
UPDATE
Clarifying the underlying issue.
My .NET service accepts something "Group"
public class Person { string Name; int Age;}
public class Group { string Name; Person[] Individuals; }
I then need to call the third party web service (TPWS). The proxy class generated from the WSDL winds up like:
public class WSPerson { string Name; uint Age;}
public class WSGroup { string Name; WSPerson[] Individuals; }
I'd been doing earlier prototyping and working with the TPWS through SoapUI and using tags matching my original (.NET) classes' naming:
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ws="http://ws.myabc123.com" xmlns:ns="http://schemas.datacontract.org/2004/07/" xmlns:sys="http://schemas.datacontract.org/2004/07/System" xmlns:arr="http://schemas.microsoft.com/2003/10/Serialization/Arrays">
<soapenv:Header>
<ws:ServiceCredentials>
<ws:SubscriberId>ABC</ws:SubscriberId>
<ws:SubscriberUser>Joe</ws:SubscriberUser>
<ws:SubscriberPassword>12345</ws:SubscriberPassword>
<!--Optional:-->
<ws:SubscriberIdentityStore></ws:SubscriberIdentityStore>
</ws:ServiceCredentials>
</soapenv:Header>
<soapenv:Body>
<Group>
<Name>Cool People</Name>
<Individuals>
<Person>
<Name>Tom</Name>
<Age>25</Age>
</Person>
<Person>
<Name>Jane</Name>
<Age>27</Age>
</Person>
</Individuals>
</Group>
</soapenv:Body>
</soapenv:Envelope>
There's no easy way to do what you want. If the service you're calling has 30 parameters, you'll just have to call it with 30 parameters.
Perhaps this will help others. I'm pursuing the idea of calling the web service through HTTP POST.
The reason is that this general problem will be repeated in similar ways over and over. I control the incoming data contract and the format of the XML that the 3rd party mapping tool ultimately expects. But it generates its own contract for the service. If it can recognize the raw XML that I can produce through XmlSerializer I won't have to map my class just to get the 3rd party tool to in turn perform its own mapping functions.

How to remove xmlns:xsd, xmlns:xsi, xsi:type from the WCF output using XMLSerializer

Using WCF Restful service with XmlSerializer I get the below response.
<?xml version="1.0" encoding="utf-8"?>
<availabilityResponse xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://xyz.com/ABCService">
<availabilityResult>
<title xsi:type="Availability_1">
<titleId>0010327457</titleId>
<availability>
<purchasable>false</purchasable>
<availableCopies>0</availableCopies>
<totalCopies>0</totalCopies>
</availability>
</title>
</availabilityResult>
</availabilityResponse>
(I wish to remove xmlns:xsd, xmlns:xsi and xsi:type tags)
"Availability_1" is one my derived type i used in my code. I really do not want to show this in the response.
I am using XmlSerialzer by specifying [XmlSerializerFormat] at the service contract.
WCF is able to serialize my response properly but the only issue i have is with the extra xmlns tags. Yes, I know they are useful stuff there. But, the client is interested only in the plain xml.
By looking at various posts in stackoverflow i understood i could do this by overriding few of the methods of XmlTextWriter. But the problem I have is how to let the WCF know to use my customXmlWriter (inherited from XmlTextWriter) instead of generic XmlTextWriter while serialization.
How to pass my customXmlTextWriter to the XmlSerializer which i do not have any control at this point.
I just created my data classes and defined the service contract methods from my end but did not have to do any of the serialization stuff from my side as the WCF takes care of it on its own.
A slightly different idea, but it's in the line of separation of concerns, as writing custom serialisers to actually make the responses sort of "invalid" seen from a true compliancy principe can be seen as an anti-pattern.
My idea is to develop your own IIS custom HTTP handlers and add it to the IIS processing pipeline. Doing so, will allow you to expose both the tweaked responses and the fully compliant ones.
The custom HTTP handler could use a simple XSLT to remove the required namespaces.
Have a look at this article to get started - http://www.iis.net/learn/develop/runtime-extensibility/developing-iis-modules-and-handlers-with-the-net-framework

wcf - customizing service document

I am new to WCF programming and its syndication classes etc. I am trying to produce a AtomPub service document programmatically when someone tries to access root address of my service. I am able to do that only to some extent using ServiceDocument, ResourceCollectionInfo, Workspace classes -
<service>
<app:workspace>
<a10:title type="text">Sample Repository</a10:title>
<app:collection href="http://some_url">
<a10:title type="text">Root Collection</a10:title>
</app:collection>
</app:workspace>
</service>
However I would like to add some custom attributes and elements as can be seen below. Please notice the xmlns attributes, cmisra elements etc.
<service
xmlns:cmis="http://docs.oasis-open.org/ns/cmis/core/200908/"
xmlns:atom="http://www.w3.org/2005/Atom"
xmlns:app="http://www.w3.org/2007/app"
xmlns:cmisra="http://docs.oasis-open.org/ns/cmis/restatom/200908/">
<workspace>
<atom:title>Sample Repository</atom:title>
<collection href="http://some_url">
<atom:title>Root Collection</atom:title>
<cmisra:collectionType>root</cmisra:collectionType>
</collection>
</workspace>
</service>
There is nothing much available on msdn website or elsewhere. Any inputs on how to achieve this would be appreciated.
Thanks!
Thanks.
The ResourceCollectionInfo class has two properties ElementExtensions and AttributeExtensions which can be used to customize the serialization of a ResourceCollectionInfo. Please note that most of the syndication elements have those extensions, which work with both the RSS and Atom formatters.

How to customize XmlResponse in WCF service using WebHttpBinding

I need to intercept the response of a service created using WCF with webHttpBinding (REST based service).
Now I want the XML emitted in a customized way. For e.g, currently a service method returns output like this:
<User xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<UserCellInfo>+91-98102239</UserCellInfo>
<UserDepartment>.NET Projects</UserDepartment>
<UserID>A10129</UserID>
<UserName>Jeff Thomson</UserName>
</User>
but I want it in a different custom way.Something like below
<?xml version="1.0" encoding="UTF-8"?>
<rsp>
<User>
<UserCellInfo>+91-98102239</UserCellInfo>
<UserDepartment>.NET Projects</UserDepartment>
<UserId>A10129</UserId>
<UserName>Jeff Thomson</UserName>
</User>
</rsp>
In MSDN, I read that I need to use IDispatchMessageInspector to intercept the XML that goes out. But I couldn't find any code reference or example for it.
Any good ideas how to achieve this?
So I assume your WCF service method returns an instance of a User object in this method call, right?
Why not just define a wrapper class called rsp that contains the User instance? Then returning the rsp object would render in the desired style. Just a nice clean wrapper - no messy XML manipulation on the fly......