1

I was getting the dreaded "client found response content type of "text/html" but expected "test/xml" error, but after some googling I found this post about how to return a SoapException.

So I went ahead and implemented that, but now I'm still getting the same error. Are there changes that I need to make on the client-side to be able to accept the SoapException (I wouldn't think so, everything just inherits from Exception, right?)

Why am I still getting that dreaded response on the client side?

    [WebMethod]
    [SoapHeader("authenticationHeader")]
    [WebServiceAuthentication(AuthenticationRequired = false)]
    public DataSet GetConversionErrors()
    {
        try
        {
            return Components.PWD.GetConversionErrors();
        }
        catch (Exception ex)
        {
            PublishingManager.Publish(ex, HttpContext.Current.User.Identity.Name);
            throw Components.SoapException.GenerateSoapException(ex, Context);
        }
    }

Edit: I know that the exception in this catch block is exactly what I need to see, but I'm still getting the System.InvalidOperationException on the client-side.

Edit2: I'm connecting to the webservices via a WebReference (calling a *.asmx file) if that helps/matters.

Edit3: Here's what's getting written to our exceptionlog server-side (in the PublishingManager.Publish() call). My thought was that this should be what is returned to the client...

Exception Details:
Exception Type: System.Exception
Message: Test the text/html text/xml message. 
Method: PWD.Components.PWD.GetConversionErrors 
Username: xxxxxx Created 5/22/2012 4:20:53 PM 
Application: xxxx Application Identity: NT AUTHORITY\IUSR 
Source: xxxx Severity 2 
Machine: xxxxxxxxx IP Address 127.0.0.1 
AppDomain /LM/W3SVC/1/ROOT-1-129821937733610609 
Stack Trace    at PWD.Components.PWD.GetConversionErrors() in C:\Vault\Development-New\Web\Main_Logging\PWD\Components\PWD.cs:line 73 
   at PWD.PWD.GetConversionErrors() in C:\Vault\Development-New\Web\Main_Logging\PWD\PWD.asmx.cs:line 44 
Additional Information:
  +System.Exception: 
    Message: Test the text/html text/xml message. 
    Data: System.Collections.ListDictionaryInternal 
    InnerException:  
    TargetSite: System.Data.DataSet GetConversionErrors() 
    StackTrace:    at PWD.Components.PWD.GetConversionErrors() in C:\Vault\Development-New\Web\Main_Logging\PWD\Components\PWD.cs:line 73 
   at PWD.PWD.GetConversionErrors() in C:\Vault\Development-New\Web\Main_Logging\PWD\PWD.asmx.cs:line 44 
    HelpLink:  
    Source: xxxx 
     UserName: xxxxxxx 
     TypeName: PublishingManager 
     MachineName: xxxxxxxxx 
     TimeStamp: 5/22/2012 4:20:54 PM 
     FullName: Services.Publishing, Version=3.5.0.0, Culture=neutral, PublicKeyToken=null 
     AppDomainName: /LM/W3SVC/1/ROOT-1-129821937733610609 
     ThreadIdentity:  
     WindowsIdentity: NT AUTHORITY\IUSR 
     Severity: 2 
     MachineIPAddress: 127.0.0.1 

Edit3: Just want to throw this extra code chunk so people see how I'm testing these exceptions (and maybe it's the wrong way to test...). In my first code chunk, I have the call inside the try block to "return Components.PWD.GetConversionErrors();", here's that method:

    public static DataSet GetConversionErrors()
    {
        DB db = new DB();

        try
        {
            //return db.ExecuteDataset(Configuration.GenericConfig.AppConnectionString, CommandType.Text, spGetConversionErrors);
            throw new Exception("Test the text/html text/xml message.");
        }
        catch
        {
            throw;
        }
    }

As you can see, I've commented out the actual call, and just threw in my own line that will throw an exception everytime for testing purposes...

Edit4: @gbvb Here's the new method:

    [WebMethod]
    [SoapHeader("authenticationHeader")]
    [WebServiceAuthentication(AuthenticationRequired = false)]
    public DataSet GetConversionErrors()
    {
        try
        {
            return Components.PWD.GetConversionErrors();
        }
        catch (Exception ex)
        {
            //PublishingManager.Publish(ex, HttpContext.Current.User.Identity.Name);
            //throw Components.SoapException.GenerateSoapException(ex, Context);

            System.Xml.XmlDocument xmlDoc = new System.Xml.XmlDocument();
            System.Xml.XmlNode detailNode = xmlDoc.CreateNode(System.Xml.XmlNodeType.Element, System.Web.Services.Protocols.SoapException.DetailElementName.Name, System.Web.Services.Protocols.SoapException.DetailElementName.Namespace);
            detailNode.InnerText = ex.ToString();

            throw new System.Web.Services.Protocols.SoapException(ex.Message, System.Web.Services.Protocols.SoapException.ClientFaultCode, System.Web.HttpContext.Current.Request.Url.AbsoluteUri, detailNode, ex.InnerException);
        }
    }

Edit5: What Fiddler2 saw:

HTTP/1.1 500 Internal Server Error
Cache-Control: private
Content-Type: text/html
Server: Microsoft-IIS/7.5
X-Powered-By: ASP.NET
Date: Wed, 23 May 2012 19:25:56 GMT
Content-Length: 1208

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1"/>
<title>500 - Internal server error.</title>
<style type="text/css">
<!--
body{margin:0;font-size:.7em;font-family:Verdana, Arial, Helvetica, sans-serif;background:#EEEEEE;}
fieldset{padding:0 15px 10px 15px;} 
h1{font-size:2.4em;margin:0;color:#FFF;}
h2{font-size:1.7em;margin:0;color:#CC0000;} 
h3{font-size:1.2em;margin:10px 0 0 0;color:#000000;} 
#header{width:96%;margin:0 0 0 0;padding:6px 2% 6px 2%;font-family:"trebuchet MS", Verdana, sans-serif;color:#FFF;
background-color:#555555;}
#content{margin:0 0 0 2%;position:relative;}
.content-container{background:#FFF;width:96%;margin-top:8px;padding:10px;position:relative;}
-->
</style>
</head>
<body>
<div id="header"><h1>Server Error</h1></div>
<div id="content">
 <div class="content-container"><fieldset>
  <h2>500 - Internal server error.</h2>
  <h3>There is a problem with the resource you are looking for, and it cannot be displayed.</h3>
 </fieldset></div>
</div>
</body>
</html>

If anyone knows out to nicely format this section, please do :)

John Saunders
  • 160,644
  • 26
  • 247
  • 397
ganders
  • 7,285
  • 17
  • 66
  • 114
  • 1
    "So I went ahead and implemented that, but now I'm still getting the same error" I've heard that and said that before. Are you sure you've fully *implemented* your changes and deployed them to the environment you are testing in? – Josh Stodola May 22 '12 at 20:11
  • 1
    Also, it is critical to know what version of .NET you are running – Josh Stodola May 22 '12 at 20:14
  • I believe so, I'm running the webservices on my "localhost" and just calling that. I can setup breakpoints both server-side and client-side...but when it stops on the client-side, the actual exception being returned from the server is the InvalidOperationException instead of the SoapException. – ganders May 22 '12 at 20:14
  • My bad, running .NET 3.5 client-side, and ASP.NET 2.0 server-side. – ganders May 22 '12 at 20:16
  • Are you sure `PublishingManager.Publish` is not bombing out before you throw the SoapException? – Josh Stodola May 22 '12 at 20:19
  • Can you use GET/POST end points on the web pages to see what HTML is being returned? You can read the output from HTML and see what it is complaining about. Sometimes, you can glean information out of that. – gbvb May 22 '12 at 20:22
  • Yes. That is publishing the actual exception to our exceptionlog table (which I have verified exists), and I can step thru that code and watch it hit the "throw Components.SoapException......part. I just commented that line out just to confirm again and it still gives the same results. – ganders May 22 '12 at 20:24
  • @gbvb Isn't that for web pages? I'm calling the web services via WinForms. – ganders May 22 '12 at 20:26
  • Does it matter? if you have a web service, it might be callable through HTTP GET/POST directly or at the very least, inspect the response that is text/html. It should have text in it that you can read which might lead you down what condition is it seeing. – gbvb May 22 '12 at 20:47
  • What is this "WebServiceAuthentication" attribute? – John Saunders May 23 '12 at 14:38
  • Also, how are you consuming the service? "Add Service Reference"? Is there any way you can switch to WCF? ASMX doesn't support faults. – John Saunders May 23 '12 at 14:40
  • @JohnSaunders it was a custom authentication process, but they have since been switched to "AuthenticationRequired = false" so they don't get called anymore...just never removed the attribute. I'm consuming the webservices via a WebReference (old style .NET 1.1). It would be a major task to change to WCF because we have over 100 webservices inside our website. – ganders May 23 '12 at 15:08
  • 1
    It's not that difficult to switch from ASMX to WCF in most cases. The client-side code need not even know about the switch. Also, it will be a lot easier to switch this year than it will be to switch in five or ten years when nobody even remembers what ASMX used to be. Also, like I said, ASMX doesn't support faults properly. – John Saunders May 23 '12 at 15:13
  • @JohnSaunders is [this](http://archdipesh.blogspot.com/2008/02/convert-existing-asmx-net-web-service.html) the suggested approach to do the conversion? If so, does that mean I need to add the 100-some service endpoints to my web.config file? If that's true, then I'd need to add those same 100-some endpoints to my build process to update their values... – ganders May 23 '12 at 16:57
  • 1
    It's something like that, but that's several years old. In particular, the service configuration is _far_ simpler in .NET 4.0, so i'm not certain you'll have to add individual endpoints to the web.config. If you did, you would probably only need to specify the URL of each endpoint and little else - the rest would default. Also, in .NET 4.0 your build process won't need to update them. You would use web.config transforms. – John Saunders May 23 '12 at 20:15
  • Ok, I've converted the web service/method that I'm testing to use WCF and my code is still receiving text/html exception instead of a soap exception. Do I need to convert ALL of the web methods in my web service to WCF, because I ONLY converted the one I'm testing. I added the [ServiceContract(Namespace = "blah")] attribute to the web service, and [OperationContract] to the method, then added the tag to my web.config. #frustrated – ganders Jun 06 '12 at 17:57

2 Answers2

1

So, I got it to work. Here's what I found out:

When viewing the properties of my website in IIS, then choosing "Modules", there is an entry called "CustomErrorModule" that is trying to process the errors that are getting thrown by the website/web service.

The fix is to either remove that entry "CustomErrorModule", or update my configuration file from:

<httpErrors errorMode="Custom" existingResponse="Replace">

to:

<httpErrors errorMode="Custom" existingResponse="Auto">

Thanks everyone for the help, it steered me in the right direction. (BTW, I'm updating the config file so I don't have to mess with the module stuff)

Also, here's a link explaining this situation.

ganders
  • 7,285
  • 17
  • 66
  • 114
0

Just for giggles, can you try explicitly throwing new SoapException() with the SoapException.ClientFaultCode as the type from that call? obviously, you have several layers that could be failing in the code you show above and it is easy to mess up (believe me, I know :)). And dont call the other methods such as Publisher.publish.. that will point at whether it is the message declaration (i.e. ASMX infrastructure) or is it your code that is messing with the exception..

gbvb
  • 866
  • 5
  • 10
  • I'll try those right-away...I'll also try just throwing a regular exception instead of a SoapException. – ganders May 23 '12 at 14:09
  • Code edit seems right and you are still seeing the same issue? – gbvb May 23 '12 at 16:17
  • correct, still seeing the same response. Is it because of what JohnSaunders replied with about "ASMX doesn't support faults properly", or is that fault not the same as the fault that I'm seeing? – ganders May 23 '12 at 16:47
  • hmm. While I agree that ASMX does not do faults properly, I do think that it usually works somewhat okay. The way you are showing it seems to be configuration of the end point. You should use some network sniffer like fiddler to see what is being sent back. That said, I agree with just going with either WCF or the new WebAPIs to simplify your life if you have a choice. – gbvb May 23 '12 at 17:00
  • Ok, I've run Fiddler2 against this, it looks like the part we're looking for has this for an error message: "There is a problem with the resource you are looking for, and it cannot be displayed." I'll add edit #5 with the actual response that Fiddler caught. – ganders May 23 '12 at 19:28
  • 1
    Check this KB out: http://support.microsoft.com/kb/942031 . and try Resolution 7 since it seems to be exactly what you are seeing.. :) – gbvb May 24 '12 at 13:07
  • Excuse my ignorance here, I read the article, but still a little confused on how to implement the change. Should the dll that needs added to the handler mappings be the client-side dll that is trying to access the webservice? So for my example, my client-side dll is called PWD.dll, so I just add that to the website's handler mappings? I'll try it out in the meantime...(if this works, please add this as an answer so I can give you credit :)) – ganders May 24 '12 at 15:10
  • 1
    It is not the client. You need to review the server! something on the server might have been misconfigured. It might be resolution 4 but in any event, check the server if it allows web service (asmx) to actually be handled by the server. That seems to be the issue from what I am seeing here. – gbvb May 24 '12 at 20:38
  • So that link says I need to add a Handler Mapping to be able to get rid of the error message that I'm seeing. But I'm trying to just return a System.Web.Services.Protocols.SoapException, wouldn't that already be handled by ASP.NET? – ganders Jun 12 '12 at 14:16