Taylohtio/GeneralApi/GeneralApi.WcfService/Pox/CustomWebHttpErrorHandler.cs

210 lines
9.1 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.ServiceModel.Dispatcher;
using System.ServiceModel.Web;
using System.Text;
using WcfRestContrib.ServiceModel.Channels;
using WcfRestContrib.ServiceModel.Description;
using WcfRestContrib.ServiceModel.Dispatcher;
using WcfRestContrib.ServiceModel.Web;
using WebException = WcfRestContrib.ServiceModel.Web.Exceptions.WebException;
namespace Taloyhtio.GeneralApi.WcfService
{
// Custom error handler shows error message instead of generic Internal Server Error.
// NOTE: this error handler doesn't help when exception occurs in http module (e.g. UnitOfWork).
// In this case generic Internal Server Error is shown
public class CustomWebHttpErrorHandler : IErrorHandler
{
// [DataContract(Name = "Error", Namespace = "")]
// private class WebExceptionContract : IWebExceptionDataContract
// {
// public void Init(WebException exception)
// {
// this.Message = exception.Message;
// this.Status = (int)exception.Status;
// }
//
// Properties
// [DataMember(Name = "Message")]
// public string Message { get; set; }
// [DataMember(Name = "Status")]
// public int Status { get; set; }
// }
bool IErrorHandler.HandleError(Exception error)
{
return true;
}
// Wraps all exceptions thrown in the service in common wrapper (FaultException<CustomFaultException>)
// so clients will be able to get exception details
/*void IErrorHandler.ProvideFault(Exception error, MessageVersion version, ref Message fault)
{
string errorMsg = error != null ? error.Message : "";
var faultException = new FaultException<CustomFaultException>(
new CustomFaultException{Reason = errorMsg});
var msgFault = faultException.CreateMessageFault();
fault = Message.CreateMessage(version, msgFault, faultException.Action);
var statusCode = HttpStatusCode.InternalServerError;
if (error is WebException)
{
statusCode = ((WebException)error).Status;
}
var rmp = new HttpResponseMessageProperty {StatusCode = statusCode};
fault.Properties.Add(HttpResponseMessageProperty.Name, rmp);
}*/
void IErrorHandler.ProvideFault(Exception error, MessageVersion version, ref Message fault)
{
var statusCode = HttpStatusCode.InternalServerError;
// 2011-06-12: although it is real REST to provide StatusCode, it is not easy to do
// with json endpoints because WebScriptEnablingBehavior is sealed and we can't do the same
// thing for it. So for consistentcy I disabled it for pox as well
// if (error is WebException)
// {
// statusCode = ((WebException) error).Status;
// }
string errorMsg = error != null ? error.Message : "";
//string body = ErrorBodyWriter.GetBody(statusCode, error.Message);
fault = Message.CreateMessage(version, null,
new ErrorBodyWriter {Code = statusCode, Message = errorMsg});
var rmp = new HttpResponseMessageProperty();
rmp.StatusCode = statusCode;
// 2011-06-12: if we use custom status description it will causes "protocol violation" error
// use body as description. On client side WCF will use this property for exception.Message
//rmp.StatusDescription = string.Format("{0}: {1}", statusCode, error.Message);
// convert error msg to base64 and store it in custom header. Client will read it via custom message inspector
if (!string.IsNullOrEmpty(errorMsg))
{
rmp.Headers[Common.Constants.HttpHeaders.Error] = Convert.ToBase64String(Encoding.UTF8.GetBytes(errorMsg));
}
fault.Properties.Add(HttpResponseMessageProperty.Name, rmp);
}
/*void IErrorHandler.ProvideFault(Exception error, MessageVersion version, ref System.ServiceModel.Channels.Message fault)
{
WebException webException;
WebErrorHandlerConfigurationBehavior behavior;
if (error != null)
{
if (error is WebException)
{
webException = (WebException) error;
}
else
{
// string unhandledErrorMessage;
// behavior = GetWebErrorHandlerConfiguration();
// if (behavior.ReturnRawException)
// {
// unhandledErrorMessage = error.ToString();
// }
// else
// {
// unhandledErrorMessage = ((behavior != null) && (behavior.UnhandledErrorMessage != null)) ? behavior.UnhandledErrorMessage : "An error has occured processing your request.";
// }
webException = new WebException(error, HttpStatusCode.InternalServerError, error.Message,
new object[0]);
}
}
else
{
webException = new WebException(HttpStatusCode.InternalServerError, "An error has occured processing request.");
}
webException.UpdateHeaders(WebOperationContext.Current.OutgoingResponse.Headers);
WebOperationContext.Current.OutgoingResponse.StatusCode = webException.Status;
WebOperationContext.Current.OutgoingResponse.StatusDescription = webException.Status.ToString();
WebDispatchFormatter webDispatchFormatter = null;
if (OperationContext.Current.OutgoingMessageProperties.ContainsKey("WebDispatcherFormatter"))
{
webDispatchFormatter = OperationContext.Current.OutgoingMessageProperties["WebDispatcherFormatter"] as WebDispatchFormatter;
}
if (webDispatchFormatter != null)
{
IWebExceptionDataContract exceptionContract = new WebExceptionContract();
// behavior = GetWebErrorHandlerConfiguration();
// if ((behavior != null) && behavior.HasExceptionDataContract)
// {
// exceptionContract = behavior.CreateExceptionDataContract();
// }
// else
// {
// exceptionContract = new WebExceptionContract();
// }
exceptionContract.Init(webException);
fault = webDispatchFormatter.Serialize(exceptionContract, typeof(WebExceptionContract), WebOperationContext.Current.IncomingRequest.GetAcceptTypes());
}
else
{
WebOperationContext.Current.OutgoingResponse.ContentType = "text/html";
fault = Message.CreateMessage(MessageVersion.None, (string)null, (BodyWriter)new BinaryBodyWriter(GenerateResponseText(webException.Message)));
fault.SetWebContentFormatProperty(WebContentFormat.Raw);
}
fault.UpdateHttpProperty();
}*/
// private static WebErrorHandlerConfigurationBehavior GetWebErrorHandlerConfiguration()
// {
// return OperationContext.Current.Host.Description.FindBehavior<WebErrorHandlerConfigurationBehavior, WebErrorHandlerConfigurationAttribute>(delegate(WebErrorHandlerConfigurationAttribute x)
// {
// return x.BaseBehavior;
// });
// }
// private static string GenerateResponseText(string message)
// {
// return string.Format("<html><body style=\"font-family:Arial;font-size:11pt;\">{0}</body></html>", message);
// }
}
internal class ErrorBodyWriter : BodyWriter
{
public HttpStatusCode Code { get; set; }
public string Message { get; set; }
public ErrorBodyWriter()
: base(true)
{
}
protected override void OnWriteBodyContents(System.Xml.XmlDictionaryWriter writer)
{
string errorMsg = GetBody(Code, Message);
System.Xml.Linq.XElement xElement = System.Xml.Linq.XElement.Load(new System.IO.StringReader(errorMsg));
xElement.WriteTo(writer);
}
public static string GetBody(HttpStatusCode statusCode, string msg)
{
string format = "<?xml version=\"1.0\" encoding=\"utf-8\"?>";
format += "<error>";
format += " <code>{0}</code>";
format += " <msg>{1}</msg>";
format += "</error>";
string errorMsg = string.Format(format, statusCode, msg);
return errorMsg;
}
}
}