I made my custom exception that will be thrown inside try-catch each time an error is occured:
[Serializable]
public class CustomException : Exception
{
public CustomException() { }
public CustomException(string message)
: base(message) { }
public CustomException(string message, Exception innerException)
: base(message, innerException) { }
}
I have two services, REST and SOAP. For SOAP services, I don't have any problem on throwing my custom exception. But in REST, I encountered a lot of difficulties.
Here is the method for throwing a WebFaultException:
public static WebFaultException RestGetFault(ServiceFaultTypes fault)
{
ServiceFault serviceFault = new ServiceFault();
serviceFault.Code = (int)fault;
serviceFault.Description = ConfigAndResourceComponent.GetResourceString(fault.ToString());
FaultCode faultCode = new FaultCode(fault.ToString());
FaultReasonText faultReasonText = new FaultReasonText(serviceFault.Description);
FaultReason faultReason = new FaultReason(faultReasonText);
WebFaultException<ServiceFault> webfaultException = new WebFaultException<ServiceFault>(serviceFault, HttpStatusCode.InternalServerError);
throw webfaultException;
}
ServiceFault is a class where it has some properties which I use to put all information I need.
I use this method to throw an exception inside REST service:
public static CustomException GetFault(ServiceFaultTypes fault)
{
string message = fault.ToString();
CustomException cusExcp = new CustomException(message, new Exception(message));
throw cusExcp;
}
A sample REST Service (log in method):
[WebInvoke(UriTemplate = "Login", Method = "POST", ResponseFormat = WebMessageFormat.Json, RequestFormat = WebMessageFormat.Json, BodyStyle = WebMessageBodyStyle.WrappedRequest)]
public Session Login(ClientCredentials client, LogCredentials loginfo)
{
try
{
// Login process
return copied;
}
catch (LogicClass.CustomException ex)
{
LogicClass.RestGetFault(LogicClass.EnumComponent.GetServiceFaultTypes(ex.Message));
throw ex;
}
}
The MVC part:
Controller:
[HttpPost]
public ActionResult Login(LoginCredentials loginfo)
{
try
{
string param = "{\"client\":" + JSonHelper.Serialize<ClientAuthentication>(new ClientAuthentication() { SessionID = Singleton.ClientSessionID })
+ ", \"loginfo\":" + JSonHelper.Serialize<LoginCredentials>(loginfo) + "}";
string jsonresult = ServiceCaller.Invoke(Utility.ConstructRestURL("Authenticate/Login"), param, "POST", "application/json");
UserSessionDTO response = JSonHelper.Deserialize<UserSessionDTO>(jsonresult);
}
catch (Exception ex)
{
return Json(new
{
status = ex.Message,
url = string.Empty
});
}
return Json(new
{
status = "AUTHENTICATED",
url = string.IsNullOrWhiteSpace(loginfo.r) ? Url.Action("Index", "Home") : loginfo.r
});
}
I use ServiceCaller.Invoke to call REST API and retrieve the response: ServiceCaller.cs
public class ServiceCaller
{
public static string Invoke(string url, string parameters, string method, string contentType)
{
string results = string.Empty;
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(new Uri(url));
request.Method = method;
request.ContentType = contentType;
if (!string.IsNullOrEmpty(parameters))
{
byte[] byteArray = Encoding.UTF8.GetBytes(parameters);
request.ContentLength = byteArray.Length;
Stream dataStream = request.GetRequestStream();
dataStream.Write(byteArray, 0, byteArray.Length);
dataStream.Close();
}
try
{
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
if (HttpStatusCode.OK == response.StatusCode)
{
Stream responseStream = response.GetResponseStream();
int length = (int)response.ContentLength;
const int bufSizeMax = 65536;
const int bufSizeMin = 8192;
int bufSize = bufSizeMin;
if (length > bufSize) bufSize = length > bufSizeMax ? bufSizeMax : length;
byte[] buf = new byte[bufSize];
StringBuilder sb = new StringBuilder(bufSize);
while ((length = responseStream.Read(buf, 0, buf.Length)) != 0)
sb.Append(Encoding.UTF8.GetString(buf, 0, length));
results = sb.ToString();
}
else
{
results = "Failed Response : " + response.StatusCode;
}
}
catch (Exception exception)
{
throw exception;
}
return results;
}
}
I am expecting the REST service to return this on client side:
But in the end, it always return this:
What should I do? Please help.
EDIT
Here is the sample response when calling the soap service:
[FaultException: InvalidLogin]
System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(IMessage reqMsg, IMessage retMsg) +9441823
Did you see the "InvalidLogin" ? That is what I want to see on the response from REST servivce.
Sample response from REST:
[WebException: The remote server returned an error: (500) Internal Server Error.]
System.Net.HttpWebRequest.GetResponse() +6115971
I throw a WebFaultException
but I receive a WebException
.
If I won't be able to fetch the exact error message on REST, I will go for SOAP.
Thanks for the answers.
When using HttpWebRequest
(or a Javascript client), your custom exception has no meaning for them. Just Http error codes(like 500 Internal server error) and the data in the response's content.
So you have to handle the exception by yourself. For example, if you catch WebException
you can read the content(the error message) in Xml or Json format depending on your server configurations.
catch (WebException ex)
{
var error = new StreamReader(ex.Response.GetResponseStream()).ReadToEnd();
//Parse your error string & do something
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With