Tôi quan tâm đến việc xử lý đúng các lỗi trong một máy khách WCF REST Service. Trong khi sử dụng bất kỳ WebClient, WebRequest, hoặc HttpWebRequest như vậy:Làm thế nào để xử lý/phân tích lỗi cho phần còn lại WCF được gọi là sử dụng WebClient
try
{
HttpWebRequest req = (HttpWebRequest)HttpWebRequest.Create(uri);
req.Method = "GET";
HttpWebResponse resp = (HttpWebResponse)req.GetResponse();
// ...process...
}
catch (WebException wex)
{
string exMessage = wex.Message;
if (wex.Response != null)
{
using (StreamReader r = new StreamReader(wex.Response.GetResponseStream()))
exMessage = r.ReadToEnd();
// the fault xml is available here, really need to parse? and how?
}
}
tôi có thể nhìn thấy trong Fiddler mà tôi đang nhận được một XML định dạng đẹp "lỗi" tin nhắn (hoặc mặc định vì includeExceptionDetailInFaults = true, hoặc một lỗi tùy chỉnh qua IErrorHandler :: ProvideFault). Tuy nhiên, chỉ có 500 lỗi nội bộ WebException đang được ném.
Tôi muốn có được một FaultException được ném trên máy khách hoặc ít nhất có thể phân tích lỗi. Chúng tôi không sử dụng "Dịch vụ tham khảo" vì vậy không có proxy (xin vui lòng sửa tôi nếu có một cách tốt hơn để làm điều này cho một khách hàng WCF REST). Có cách nào chung để phân tích lỗi đó bất kể loại T thực tế của nó (FaultException) hay thậm chí đối với loại cụ thể làm điểm bắt đầu? Cảm ơn!
Dựa trên câu trả lời từ degorolls:
public SomeContract ThrowErrorTest()
{
try
{
return TryCatchExtractAndRethrowFaults<SomeContract>(() =>
{
// Call web service using WebClient, HttpWebRequest, etc.
return SomeContract;
});
}
catch (FaultException<CustomFault> fexCustom)
{
Dbg.WriteLine(fexCustom.Message);
}
catch (FaultException fex)
{
Dbg.WriteLine(fex.Message);
}
catch (WebException wex)
{
Dbg.WriteLine(wex.Message);
}
catch (Exception ex)
{
Dbg.WriteLine(ex.Message);
}
return null;
}
static public T TryCatchExtractAndRethrowFaults<T>(Func<T> doWebRequest)
{
try
{
return doWebRequest();
}
catch (WebException wex)
{
FaultException fe = ConvertWebExceptionIntoFault(wex);
if (fe != null)
throw fe;
throw; // not a fault, just re-throw
}
}
static protected FaultException ConvertWebExceptionIntoFault(WebException wex)
{
if (wex.Response == null)
return null;
XmlDictionaryReader xdr = XmlDictionaryReader.CreateTextReader(
wex.Response.GetResponseStream(),
new XmlDictionaryReaderQuotas());
Message msg = Message.CreateMessage(MessageVersion.None, "ParseFaultException", xdr);
// If the start element of the message is "Fault" convert it into a FaultException
//
using (MessageBuffer msgBuffer = msg.CreateBufferedCopy(65536))
using (Message msgCopy = msgBuffer.CreateMessage())
using (XmlDictionaryReader reader = msgCopy.GetReaderAtBodyContents())
if (reader.IsStartElement("Fault"))
{
// Must make a copy for the converter
msg.Close();
msg = msgBuffer.CreateMessage();
return ConvertMessageToFault(msg);
}
return null;
}
static FaultException ConvertMessageToFault(Message msg)
{
EnvelopeVersion ev = msg.Version.Envelope;
var fault = MessageFault.CreateFault(msg, 65536);
if (fault.HasDetail)
{
string faultName = fault.GetReaderAtDetailContents().Name;
switch (faultName)
{
case "ExceptionDetail": // handle the default WCF generated fault
ExceptionDetail exDetail = fault.GetDetail<ExceptionDetail>();
return new FaultException<ExceptionDetail>(exDetail, fault.Reason, fault.Code);
case "CustomFault": // handle custom faults
CustomFault cstmDetail = fault.GetDetail<CustomFault>();
return new FaultException<CustomFault>(cstmDetail, fault.Reason, fault.Code);
default:
throw new Exception("Unrecognized fault detail '" + faultName +
"' while re-constructing fault.");
}
}
return null;
}
Điều đó dường như khiến tôi gần gũi. Trên MessageFault.CreateFault() tôi nhận được khiếu nại innerException về không gian tên không phải là ".../soap-envelope" thay vì ".../envelope/none". Biết cách tốt để giải quyết vấn đề không gian tên? Nó thực sự đến từ máy chủ là ".../envelope/none". – crokusek
Tôi đã thay đổi đối số thành Message.CreateMessage() thành MessageVersion.None thay vì MessageVersion.Default và đã khắc phục sự cố không gian tên. Vì tôi bắt đầu với một WebException đã kết thúc việc tạo thông báo từ luồng wex.Response. Sẽ đăng những gì đã kết thúc làm việc ở cuối câu hỏi. – crokusek
Bạn có nhận được WebException ngay cả sau khi đặt FaultExceptionEnabled = true không? –