.NET 2.0 Web Services WSDL Fault element being ignored? - c#

I have a web service method where I would like to throw some custom exceptions e.g. SomeException, SomeOtherException etc which the web service would then turn into a SOAP fault which the client would be able to handle. In Java I can have wsdl:fault elements within the wsdl:operation element in the WSDL. It appears it .NET that this is not catered for and that there is no way of putting attributes on a WebMethod to show what SOAP faults may occur.
If I create a Java web service which has wsdl:fault elements and add a web reference to a .NET project I would have expected the wsdl:fault elements to cause appropriately named exceptions to be created just as the other entities are created, this however does not seem to be the case.
Is it the case that wsdl:fault elements in a WSDL are completly ignored by .NET? They are part of the WSDL specification defined at http://www.w3.org/TR/wsdl so this wasn't the behaviour I was expecting.
If this is the case possible work arounds might be returning a result object which contains a success/failure boolean value and an error message/enum. Or by using SoapExceptions. If I choose to use SoapExceptions I am then putting the emphesis on the user of my web service to handle these and deserialize it properly. Both of these don't seem a great way of handling this and add extra problems and code to workaround this.
Any advice?

Since you ask for .net 2.0 i guess you know that this is "fixed" in WCF where you can add the attribute [FaultContract(typeof(YourCustomException))].
The "normal" way this was done in 2.0 is as you says, add a Response message with a success-boolean, Result and a Error property.
You can typically see how this is done in EntLib.

ASMX web services did not support the wsdl:fault element, either on the client or the server. They never will.
As ThorHalvor has said, the bug fix for this is called "WCF".
I have successfully hand-written a WSDL that includes wsdl:fault elements, then returned those faults through an ASMX web service by including the fault message as the Detail property of a SoapException. Java and WCF clients then properly saw this as an exception of the appropriate kind.

[return: System.Xml.Serialization.XmlElementAttribute("ResultWS", typeof(ResultWS), Namespace = "http://...")]
[return: System.Xml.Serialization.XmlElementAttribute("ResultFaultWS", typeof(ResultFaultWS), Namespace = "http://...")]
public object SumTest_Operation([System.Xml.Serialization.XmlElementAttribute(Namespace = "http://...")] ParamWS param)
{
ResultWS result = null;
try
{
result.Value = param.P1 + param.P2;
}
catch (Exception)
{
ResultFaultWS resultFault = new ResultFaultWS();
resultFault.Status = noOK;
return resultFault;;
}
return result;
}

Related

Using SoapService Class with WCF web service

I need to create a web service to receive a SOAP request that a customer uses to send out information to various systems, all I have is an example xml payload. I have created a test WCF web service using
https://www.c-sharpcorner.com/article/create-simple-wcf-service-and-host-it-on-console-application/
and was going to just create a class along the lines of
public class WebServiceSOAP : IWebServiceSOAP
{
public string SetProductInfo(string strSOAPRequest)
{
// Parse the xml received, validate etc
string response = ParseSOAPData(strSOAPRequest);
// response depends on if data passes validation or not.
return response;
}
}
and host it in a console App. I then came across SoapService Class during my googling but I am not clear on how this fits in with a normal WCF service as the example here
https://msdn.microsoft.com/en-gb/library/ms819935.aspx
seems to use Microsoft.Web.Services2/3 instead of System.ServiceModel does this mean I can use the same method to set up my webservice as the example I have previously followed? Including the App.config. The example seems for System.ServiceModel seems completely different to the setup of the WCF service I followed. I am clearly missing something. I can't inherit from both the interface and SoapService, plus I would have a function with a [OperationContract] and a [SoapMethod] attribute.
It looks like I could receive the SOAPEnvelope and use SoapEnvelope.GetBodyObject to get the body / payload but I am not clear if it returns xml or if the body still has all the < replaced with < etc Can I just take the result of SoapEnvelope.GetBodyObject and parse the xml?

c# SOAP with service reference is not showing real response

I'm creating an UWP app, that needs to connect to asmx service. I've done that by using service reference, which works with TempConvert but not with my asmx service
This is how my code looks like
HelpdeskSoapClient HPsoapClient = new HelpdeskSoapClient();
getIncInput input = new getIncInput();
input.username = "450";
getIncResponse realresponse;
realresponse= await HPsoapClient.getIncAsync(input);
Debug.Write(realresponse);
but response is not an XML file or something else, but "DTS.helpdesk.getIncResponse"
Any clues ?
getIncResponse is the object that is returned by the service when you make the call.
When you pass realResponse into the Debug.Write, since it's an object, the base functionality of ToString() is called, which unless overridden in the object will return the fully qualified type name - i.e., DTS.helpdesk.getIncResponse.
You should be able to access the properties of the object to get the data, similar to how you set the username on the getIncInput object (input.username = "450";).
The temperature conversion service worked because it returns a simple type (string), not a complex type (getIncResponse). There is no error here.

Why the result from the web service references and Service references are different?

I am bit curious about one thing which has happen while trying to understand the concept of Service References and Web Service References.
What I did is?
In my project I have added a web service as a Service Reference and trying to get my script run through the use of client.
But while getting result it is throwing an exception as in the following image:
I have tried to trace out the cause but not able to get the proper answer for that.
I have following code for the resultant object.
[
ComVisible(false),
Serializable,
SoapTypeAttribute("RecordList", "http://www.someadd.com/dev/ns/SOF/2.0"),
XmlType(TypeName="RecordList", Namespace="http://www.someadd.com/dev/ns/SOF/2.0")
]
public class MyRecordListWrapper
{
private IxRecordList recordList = null;
private const string XMLW3CSchema = "http://www.w3.org/2001/XMLSchema";
[SoapElement("Headers")]
public Header[] Headers = null;
[SoapElement("Records")]
public Record[] Records = null;
// some methods to work on intialization
public SmRecordListWrapper(ref IxRecordList p_RecordList)
{
recordList = p_RecordList;// record list initialization
Headers = CreateWrapperHeaders(); // will return header class object
Records = CreateWrapperRecords(); // will return record object
}
}
Can anyone tell me why this error is showing for me?
While adding reference as a Web Service Reference
when I add the same reference as a web reference that time the program is not showing any error and runs successfully?
So can anyone tell me what is the difference in working with the same code using service reference and web service reference?
and Which is a correct way to ass references?
Hope I will get some more described answers to make the things easy to understand.
Thanks in advance.
Adding a web reference, visual studio uses xsd.exe to generate the classes from the service metadata. This uses XmlSerializer under the hood.
Adding a service reference, visual studio uses svcutil.exe to generate the classes from the metadata. This uses DataContractSerializer under the hood.
Two separate tools, two outcomes. For general information, DataContractSerializer is a lot less forgiving when it comes to generating classes from metadata.

Utilizing IHeaderHandler with wcf

I have a rather outdated assembly that I'm using to communicate via SOAP with software my company writes. As it stands right now, getting the assembly updated is not an option, so please don't suggest it.
In previous iterations the normal method of communication was done utilizing the MS Soap Toolkit 3.0 (MSSOAPLIB30). You would call the login() method of the assembly and it would return an instance derived from IHeaderHandler that you would then assign to the instance of the soap client. Please refer here for more information on how this worked.
Well, I would like to use a more updated approach for communication with this web service. Thus far I have been able to successfully reference the web service with wcf, however I'm running into issues figuring out how to bridge the IHeaderHandler instance to something that the wcf proxy can comprehend. In other words, I'm trying to bridge two generations of technologies together. I've verified that using the method mentioned in the link above does actually work. Now it's just a matter of figuring out how to make this instance of IHeaderHandler useful.
Here is some example code for the old approach:
string strBasicWsdlUrl = "http://" + _strDeviceName + "/MetasysIII/WS/TimeManagement/TimeService.asmx";
object[] Parameters1 = new object[] { strBasicWsdlUrl, "", "", "" };
bool[] Parameters2 = new bool[] { true, true, true, true };
TSClient = Activator.CreateInstance(Type.GetTypeFromProgID("MSSOAP.SoapClient30"));
NewLateBinding.LateGet(TSClient, null, "MSSoapInit", Parameters1, null, null, Parameters2);
Parameters1 = new object[] { NewLateBinding.LateGet(JCISecurity, null, "HeaderHandler", new object[0], null, null, null) };
NewLateBinding.LateSet(TSClient, null, "HeaderHandler", Parameters1, null, null);
As you can see, a new instance of the soap client is initialized with the wsdl file and then the HeaderHandler attribute from the JCISecurity instance (which is the aforementioned assembly I'm using to authenticate with the software) which is derived from IHeaderHandler is passed to the HeaderHandler of the soap client. This process then ensures that all future requests from the soap client have this header attached.
It's also important to note that the proxy class generated from WCF for my web service has two interesting parameters attached to all web methods: EncryptedCertificate and LoginResult. I'm assuming these values will exist in the IHeaderHandler instance as the original documentation of the service does not reference these two parameters. However, I cannot verify this is the case because I've yet to be able to figure out how to access the content embedded in the IHeaderHandler instance.
As it stands, I see two possible solutions at this point: Figure out a way to make the WCF proxy class directly use the IHeaderHandler instance being generated with the assembly or figure out a way to extract the necessary information from the IHeaderHandler instance and use Message Inspectors to manually attach the details to the headers.
WCF is very extensible. One of those extension points is Message Inspectors:
A message inspector is an extensibility object that can be used in the service model's client runtime and dispatch runtime programmatically or through configuration and that can inspect and alter messages after they are received or before they are sent.
See also WCF Extensibility Samples and Extending WCF.

Dynamic C#.NET Webservice

I am using a class in a C# ASP.NET project to allow a script written in some random scripting language to expose webservice methods dynamically - in other words, the script should be able to expose a method of any name with any signature (as long as it's valid, anyway) to the outside world through this SOAP interface (able to add and remove them at will, without needing a hard code change), and as such I need to be able to create a webservice class in C# while being able to dynamically add and remove methods at runtime.
Now, the best plan I've been able to come up with so far is (runtime) generating C# code to represent the webservice, using System.Reflection.Emit to compile it and then loading the assembly at runtime - all whenever the script adds or removes a method to/from the service (should not happen very often, mind).
Does anyone have a better idea than this?
You can modify WSDL by using SoapExtensionReflector class. From Kirk Evans Blog:
The SoapExtensionReflector is called when your type is being reflected over to provide the WSDL definition for your service. You can leverage this type to intercept the reflection call and modify the WSDL output.
The following example removes the first method out of 2 web service methods:
[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
[System.ComponentModel.ToolboxItem(false)]
public class Service1 : System.Web.Services.WebService
{
[WebMethod]
public string HelloWorld()
{
return "Hello World";
}
[WebMethod]
public int Multiply(int a, int b)
{
return a * b;
}
}
Create a class inherited from SoapExtensionReflector:
namespace TestWebservice
{
public class MyReflector : SoapExtensionReflector
{
public override void ReflectMethod()
{
//no-op
}
public override void ReflectDescription()
{
ServiceDescription description = ReflectionContext.ServiceDescription;
if (description.PortTypes[0].Operations.Count == 2)
description.PortTypes[0].Operations.RemoveAt(0);
if (description.Messages.Count == 4)
{
description.Messages.RemoveAt(0);
description.Messages.RemoveAt(0);
}
foreach (Binding binding in description.Bindings)
{
if (binding.Operations.Count == 2)
binding.Operations.RemoveAt(0);
}
if (description.Types.Schemas[0].Items.Count == 4)
{
description.Types.Schemas[0].Items.RemoveAt(0);
description.Types.Schemas[0].Items.RemoveAt(0);
}
}
}
}
Add this to configuration/system.web section in web.config:
<webServices>
<soapExtensionReflectorTypes>
<add type="TestWebservice.MyReflector, TestWebservice" />
</soapExtensionReflectorTypes>
</webServices>
This should give you a starting point to dynamically removing methods from WSDL document. You would also need to throw NotImplementedException from web method if it is disabled.
Finally, you need to disable web service documentation produced by invoking .asmx endpoint without ?WSDL parameter. Set href attribute of wsdlHelpGenerator element to some URL. You can use DefaultWsdlHelpGenerator.aspx as a starting point for your own documentation handler. See question on web service documentation in XML Files, August 2002.
XMLRPC is fairly dead, isn't it?
SOAP implies a WSDL. How do you generate the WSDL dynamically?
You should look into using WCF. I expect you'll be able to take control of the process of generating the WSDL (and other metadata), yet you should also be able to take control of the processing of incoming messages. In particular, you will be able to examine the incoming messages to determine which script to run, what parameters to pass, etc.
You could create a WCF service with an input and output type of xs:any and handle the incoming request as a raw Message. That would allow you to accept any type of data and return any type of data. You would not use data contracts or static types, just a Message in and a Message out.
The problem with this approach is that generating a proxy from the WSDL really does nothing to help the consumer other than provide a wrapper to call the method. Providing data that is acceptable to the method would require hand-rolling data types, etc which is not that hard, it is just not as intuitive as a hard, typed contract.
Does it have to be a SOAP interface? That sounds like it might be more suitable to a route/REST/etc based API. You could do something in ASP.NET MVC (with a custom IController.Execute method that resolves the action to the method) pretty easily (in fact, I'm working on something very similar for some of my own code at the moment).
For example, you might have routes:
http://myserver/myservice/mymethod
that accepts (either in the body or args) the payload (parameters), and returns the result in the response. In non-MVC you should be able to do something similar with a wildcard-mapped generic handler.
Here is a suggestion:
Use WCF.
Create a WSDL from WCF using
information in the following blog
post:
http://www.pluralsight.com/community/blogs/kirillg/archive/2006/06/18/28380.aspx
You can then publish this information
using MEX.
The services are then open for your
clients to down load the meta data
and call the services.

Categories

Resources