PDA

View Full Version : Preserve some attributes when exposing PONO as WebService


fspirit
02-13-2007, 11:56 AM
Hi All!

I'm trying to expose a PONO like:

public class CustomerService : ICustomerService
{
IStorage<Customer> m_storage;

public CustomerService( IStorage<Customer> m_storage )
{
this.m_storage = m_storage;
}

public Customer Get( long id )
{
return (Customer) m_storage.Get( id );
}
}


as WebService, but Customer is an abstract class and actual return objects will be Individual or Organization.

If it was a common WebService i would use XmlInclude arttribute like:

[WebMethod()]
[XmlInclude(typeof(Individual)), XmlInclude(typeof(Organization))]
public Customer Get( long id )
{
return (Customer) m_storage.Get( id );
}


what can i use when exposing such an object by the means of Spring.NET?
there's an example like:

<object id="HelloWorldExporter" type="Spring.Web.Services.WebServiceExporter, Spring.Web">
<property name="TargetName" value="HelloWorld"/>
<property name="Namespace" value="http://myCompany/services"/>
<property name="Description" value="My exported HelloWorld web service"/>
<property name="MemberAttributes">
<dictionary>
<entry key="HelloWorld">
<object type="System.Web.Services.WebMethodAttribute, System.Web.Services">
<property name="Description" value="My Spring-configured HelloWorld method."/>
<property name="MessageName" value="ZdravoSvete"/>
</object>
</entry>
</dictionary>
</property>
</object>


but i need smth, that looks similar to:

<object id="CustomerWebService" type="Spring.Web.Services.WebServiceExporter, Spring.Web">
<property name="TargetName" value="CustomerService"/>
<property name="Namespace" value="http://Prototype/WebServices"/>
<property name="Description" value="Prototype Web Service"/>
<property name="MemberAttributes">
<dictionary>
<entry key="Get">
<list>
<object type="System.Xml.Serialization.XmlIncludeAttribute, System.Xml">
<constructor-arg index="0" expression=""/>
</object>
<object type="System.Xml.Serialization.XmlIncludeAttribute, System.Xml">
<constructor-arg index="0" expression=""/>
</object>
</list>
</entry>
</dictionary>
</property>
</object>


I just dont khow howto specify params of type [System.Type]. Can anyone help?

Bruno Baia
02-13-2007, 12:46 PM
Hi,

you should use property setter as possible, try something like that :


<object id="CustomerWebService" type="Spring.Web.Services.WebServiceExporter, Spring.Web">
<property name="TargetName" value="CustomerService"/>
<property name="Namespace" value="http://Prototype/WebServices"/>
<property name="Description" value="Prototype Web Service"/>
<property name="MemberAttributes">
<dictionary>
<entry key="Get">
<list>
<object type="System.Xml.Serialization.XmlIncludeAttribute, System.Xml">
<property name="Type" value="MyNamepsace.Individual, MyAssembly"/>
</object>
<object type="System.Xml.Serialization.XmlIncludeAttribute, System.Xml">
<property name="Type" value="MyNamepsace.Organization, MyAssembly"/>
</object>
</list>
</entry>
</dictionary>
</property>
</object>


Hope this helps,
Bruno

Aleks Seovic
02-13-2007, 01:07 PM
Unfortunately, you cannot do what Bruno is proposing because XmlIncludeAttribute doesn't have a default constructor. However, you can specify type the same way for a constructor-arg: you simply specify fully-qualified type name within the value attribute and let Spring do the conversion.

If you want to use expression instead of value, you can find necessary information on how to specify Type within expression in the reference docs (http://www.springframework.net/doc-latest/reference/html/expressions.html#expressions-types), but in this particular case using special kind of constructor expression (http://www.springframework.net/doc-latest/reference/html/expressions.html#expressions-ctor) that allows you to create attribute instances using one-liner will actually work better.

Basically, you can do what you need using this definition:


<object id="CustomerWebService" type="Spring.Web.Services.WebServiceExporter, Spring.Web">
<property name="TargetName" value="CustomerService"/>
<property name="Namespace" value="http://Prototype/WebServices"/>
<property name="Description" value="Prototype Web Service"/>
<property name="MemberAttributes">
<dictionary>
<entry key="Get">
<list>
<expression value="@[XmlInclude(T(MyNamespace.Individual, MyAssembly))]" />
<expression value="@[XmlInclude(T(MyNamespace.Organization, MyAssembly))]" />
</list>
</entry>
</dictionary>
</property>
</object>


Of course, you need to register appropriate type aliases per documentation (http://www.springframework.net/doc-latest/reference/html/objects.html#context-configuration), or use fully-qualified type names, including assembly. My recommendation is to configure an "XmlInclude" alias for the XmlIncludeAttribute and use fully-qualified names for Individual and Organization types, which is what the example above reflects.

HTH,

Aleks

fspirit
02-13-2007, 03:30 PM
Thanks, guys!!
Actually it was

<expression>@[XmlInclude(T(Prototype.DomainModel.Individual, Prototype.DomainModel))]</expression>

that helped :)

Now, the second issue, client tells me that:
System.InvalidOperationException: The specified type was not recognized: name='Individual', namespace='http://Prototype/WebServices', at <GetResult xmlns='http://Prototype/WebServices'>.

What to do to make client recognize that type? I'm sure there's smth i have to do with WebServiceClientFactory, but i dont know what exactly.

Bruno Baia
02-13-2007, 04:28 PM
Hi,

You need to reference you domain assembly Prototype.DomainModel in your client application.


Bruno

Aleks Seovic
02-14-2007, 01:01 PM
Thanks, guys!!
Actually it was

<expression>@[XmlInclude(T(Prototype.DomainModel.Individual, Prototype.DomainModel))]</expression>

that helped :)


Actually, this is the old syntax for <expression> element, which has been modified to <expression value="exprString"> in the latest builds in order to allow users to specify root context and variables for the expression.

Your best option is to download and use the latest nightly build and the new <expression> syntax. Otherwise, you'll have to modify your configuration files when you upgrade to RC1.

Regards,

Aleks

fspirit
02-16-2007, 09:58 AM
Client assembly does reference Prototype.DomainModel assembly, still doesnt work. What could it be?

Bruno Baia
02-16-2007, 05:18 PM
Of course, you need to register appropriate type aliases per documentation (http://www.springframework.net/doc-latest/reference/html/objects.html#context-configuration), or use fully-qualified type names, including assembly. My recommendation is to configure an "XmlInclude" alias for the XmlIncludeAttribute and use fully-qualified names for Individual and Organization types, which is what the example above reflects.


Have you done this to recognize the XmlInclude alias type ?


<configuration>

<configSections>
<sectionGroup name="spring">
<section name="context" type="Spring.Context.Support.ContextHandler, Spring.Core"/>
<section name="objects" type="Spring.Context.Support.DefaultSectionHandler, Spring.Core" />
<section name="typeAliases" type="Spring.Context.Support.TypeAliasesSectionHandler, Spring.Core"/>
</sectionGroup>
</configSections>

<spring>

<context>
[...]
</context>

<typeAliases>
<alias name="XmlInclude" type="System.Xml.Serialization.XmlIncludeAttribute, System.Xml"/>
</typeAliases>

[...]



Bruno

fspirit
05-25-2007, 07:56 AM
I want to mark return value of method, which is then wrapped by spring and published as web-method, with the attribute:

[return: System.Xml.Serialization.XmlArrayItemAttribute(Nam espace="http://schemas.marti.sitels.ru/CustomerManagement/Types/")]


What i have to do to make spring work properly in this way?

Bruno Baia
06-26-2007, 02:29 PM
Hi,

Unfortunately, you cannot do that by configuration.
Actually we can't specify return attributes or parameter attributes. This will be possible with the future poincut expression (after 1.1 release).

What you can do is to put the attribute in the code directly. If you are using a recent version of Spring (like 1.1 M1), the attribute will be copied to the proxy so it should work.


HTH,
Bruno