Easier way to Call a SOAP Service with Many Parameters? - wcf

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.

Related

Can you ignore incoming namespaces in requests to a WebAPI method?

Coming to new to WebAPI and i am having a namespace issue
I have a POST method in my WebAPI that accepts an object as JSON or XML however the method is to be consumed by a BizTalk service which adds its own namespace to the xml.
<ns0:Person xmlns:ns0="http://Acme/Esb/DestinationSchemas/Person/v1.0">
<WorkEmail>Someemail#acme.com</WorkEmail>
<PersonId>10</PersonId>
<UserName>Shouldhaveone</UserName>
</ns0:Person>
and my WebAPI Post method is defined as follows
<Person xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<PersonId>10</PersonId>
<WorkEmail>Someemail#acme.com</WorkEmail>
<UserName>Shouldhaveone</UserName>
</Person>
As you can see the namespaces are different and whenever the Post called the object is null. Can someone please advise me of the best approach to ignore the namespaces of incoming requests
Many thanks
Option 1 is to switch to using XmlSerializer in GlobalConfiguration:
config.Formatters.XmlFormatter.UseXmlSerializer = true;
Option 2 is to decorate your models with
[DataContract(Namespace="")]
(and if you do so, you'd need to decorate the members with [DataMember] attributes).
original post
Remove namespace in XML from ASP.NET Web API
The answer was to add XmlMediaFormatter to ignore namespaces
all thanks to Jan Jonas
http://blog.janjonas.net/2012-09-07/asp_net-mvc_4_rc-web-api-implementing-custom-xmlmediatypeformatter-ignore-xml-namespace

Do I need to send the XSD files with WSDL for implementation

I am developing a WCF service in .net and would like to give the wsdl file to the customer who can consume our service. I successfully Generated the wsdl which includes the xsd import statement
<xsd:import schemaLocation="https://URL/Service-v1.svc?xsd=xsd1" namespace="Service-v1" />
<xsd:import schemaLocation="https://URL/PricingService-v1.svc?xsd=xsd3" />
etc
But what I would like to know is is that is enough to just send the wsdl to the customer or do I need to send them the XSD files as well..
How can I generate separate XSD files for each class like class1.xsd, class2.xsd, class3.xsd
here is my project structure
DataModel
Class1.cs
Class2.cs
Class3.cs
Response.cs
Contract
IService1 with the following contracts
Response GetQuote1(Class1 class1Request);
Response GetQuote2(Class2 class2Request);
Response GetQuote2(Class2 class2Request);
Service
Service1 : Iservice1
public Response GetQuote1(Class1 class1Request)
{
return response;
}
public Response GetQuote2(Class2 class2Request)
{
return response;
}
public Response GetQuote3(Class3 class3Request)
{
return response;
}
I search on the internet but couldn't be able to decide on the best option as we have no control over the other end who is going to implement our WCF service.
I don't know about .net but I have had experience both consuming and providing web services to 3rd parties.
The WSDL is basically a list of functions that can be called on a remote server and how to connect. Each function is going to have an XML format for the request and response. It is possible to embed the schema for these in the WSDL itself. If this is the case then you only have to send this one file. It sounds to me that your auto-generated WSDL has the schemas for the request and response params in seperate files. If this is the case then they'll need both the WSDL and XSD's.
If you just provide the WSDL then they'll know how to package up the SOAP request but they won't know the format of the XML that goes in the body. A bit like knowing someones telephone number but not knowing the language they speak, not much use! If I was the customer I would rather have just the XSD's than just the WSDL. With the inputs and outputs defined I can start coding. Then once I have access to the full WSDL and XSD's I can generate a stub to call the appropriate service and hook up the code I've already written. Of course if the XSD's and WSDL are both ready then by all means please send me the lot.
If you're using .NET with WCF, the service description page will generally include a link such as:
http://localhost:12345/Foo.svc?singleWsdl
If you right-click and save that file from the browser, it's an all-inclusive, WSDL + schema for each call, that contains all the information a consumer would need for the service.

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

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......

Controlling WCF Message Body serialization

I need to create a WCF service that will emulate some third-party service. That service has very complicated messages and wrappers for them, so I will simplify them in description.
I have WSDL of that service and created proxy class. But here the first problem occurs: all methods in proxy have
[System.ServiceModel.OperationContractAttribute(Action = "", ReplyAction = "*")]
So it is impossible to create WCF service with many methods: each for one method in proxy because every method must have unique Action. I think that third-party service has one method that handles all requests. And I created such method with needed KnownType attributes on RequestTypeBase and ResponceTypeBase. All proxy-class methods have one parameter of type, derived from RequestTypeBase.
And here is the main problem and question: when WCF service tries to deserialize message body, it throws an exception saying that expected elementName is "Process" (the name of my mega-method that processes all requests) but existing elementName is "RequestType1" (the name class with data that must be passed to "Process" method as parameter). So how can I receive such message?? Is there some attribute in WCF to not require the methodName as root of Message body? And I even not understand for what does WCF need that MethodName there if he already knows what method is called? Looks like redundancy with action specification.
Maybe simple MessabeBody example that is successfully processing by WCF, will help to understand what I mean:
<s:Body>
<TestMethod xmlns="someNamespace">
<x>1</x>
<str>param2</str>
</TestMethod>
</s:Body>
You could skip WCF deserialization completely on the service side by using the "universal service contract":
[ServiceContract]
public interface IUniversalRequestResponseContract
{
[OperationContract(Action="*", ReplyAction="*")]
Message ProcessMessage(Message msg);
}
and then handle deserialization yourself working with the Message instance received.
If you are writing a stub emulation of some external service for testing purposes (I'm guessing), that is a good approach anyway because you can control exactly what is sent in the response.