I've seen no need to upgrade my services to WCF, but I have been using WCF clients for some time to access ASMX services from .NET 3.5 ASP.NET. I figured eventually I'd hit a wall in this mismatch and I just did - but with Silverlight.
When using Silverlight to access ASMX web services I get an error like this in a popup :
An exception occurred during the operation, making the result invalid. Check InnerException for exception details.
If I'm debugging I get this error :
The 开发者_高级运维remote server returned an error: NotFound.
If I look in Fiddler the exception/fault is there just fine :
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<soap:Body><soap:Fault>
<faultcode>soap:Server</faultcode>
<faultstring>Server was unable to process request. ---> ID does not match</faultstring>
<detail /></soap:Fault></soap:Body></soap:Envelope>
How do I actually get to this exception in the Silverlight client.
I need the error to be accessible at runtime with no fiddler and no debugger.
There is a property includeexceptiondetailinfaults
that belongs in <behaviors>
in the web.config - but this is for server side only as far as I can tell.
Am I correct in assuming that I will need to convert my asmx
to svc
to be able to get actual exception details in the silverlight client?
If you're happy to wrap the asmx SOAP request in your own IHttpHandler, you can force-feed a Response.StatusCode = 200 after the System.Web.Script.Services.ScriptHandlerFactory does it's work. Here's a sample;
static void ProcessService(HttpContext context)
{
//
// I'm also using this to fake/hide the path of my asmx so that
// domain.com/xml becomes the service end-point..
//
string asmx = "/Services/Some.Service.asmx";
string method = context.Request.Path.Substring("/xml".Length);
//
// ScriptHandlerFactory and friends are sealed so have to use reflection..
//
IHttpHandlerFactory fact = (IHttpHandlerFactory)Activator.CreateInstance(Type.GetType("System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions"));
Type vpt = Type.GetType("System.Web.VirtualPath, System.Web, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a");
System.Reflection.MethodInfo mi = vpt.GetMethod("Create", new Type[] { typeof(string) });
object vp = mi.Invoke(null, new object[] { context.Request.Path });
System.Reflection.FieldInfo fi = context.Request.GetType().GetField("_pathInfo", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic);
System.Reflection.FieldInfo _virtualPath = vpt.GetField("_virtualPath", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic);
_virtualPath.SetValue(vp, method);
fi.SetValue(context.Request, vp);
IHttpHandler handler = fact.GetHandler(context, context.Request.RequestType, asmx, context.Server.MapPath(asmx));
try
{
// This will trap your asmx Exception and output 500 status and soap fault
handler.ProcessRequest(context);
// force 200 status for Silverlight to receive fault code
context.Response.StatusCode = 200;
context.ApplicationInstance.CompleteRequest();
}
finally
{
fact.ReleaseHandler(handler);
}
}
No client ever gets exceptions from web services. Web services don't send exceptions - they send faults.
The details of the fault are contained in the <detail/>
element of the fault message. some platforms, including WCF, parse this information in order to translate from the fault to a platform-specific exception.
Since there is no information in the <detail/>
element, no translation is likely to occur.
精彩评论