8

我做了我的自定义异常,每次发生错误时都会在 try-catch 中抛出:

[Serializable]
public class CustomException : Exception
{
    public CustomException() { }

    public CustomException(string message)
        : base(message) { }

    public CustomException(string message, Exception innerException)
        : base(message, innerException) { }
}  

我有两个服务,REST 和 SOAP。对于 SOAP 服务,我在抛出自定义异常时没有任何问题。但是在 REST 中,我遇到了很多困难。

下面是抛出 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 是一个类,它具有一些我用来放置我需要的所有信息的属性。

我使用此方法在 REST 服务中引发异常:

    public static CustomException GetFault(ServiceFaultTypes fault)
    {
        string message = fault.ToString();
        CustomException cusExcp = new CustomException(message, new Exception(message));
        throw cusExcp;
    }  

一个示例 REST 服务(登录方法):

    [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;
        }
    }  

MVC部分:

控制器:

    [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
        });
    }  

我使用 ServiceCaller.Invoke 调用 REST API 并检索响应: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;
    }
}  

我期待 REST 服务在客户端返回这个:

在此处输入图像描述

但最后,它总是返回:

在此处输入图像描述

我应该怎么办?请帮忙。

编辑

这是调用soap服务时的示例响应:

[FaultException: InvalidLogin]
   System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(IMessage reqMsg, IMessage retMsg) +9441823  

您看到“无效登录”了吗?这就是我想从 REST 服务的响应中看到的。
来自 REST 的示例响应:

[WebException: The remote server returned an error: (500) Internal Server Error.]
   System.Net.HttpWebRequest.GetResponse() +6115971  

我扔了一个WebFaultException,但我收到了一个WebException
如果我无法在 REST 上获取确切的错误消息,我会选择 SOAP。
感谢您的回答。

4

3 回答 3

4

使用HttpWebRequest(或 Javascript 客户端)时,您的自定义异常对它们没有任何意义。只是 Http 错误代码(如500 Internal server error)和响应内容中的数据。

所以你必须自己处理异常。例如,如果您捕获WebException了内容(错误消息),则可以根据您的服务器配置以 Xml 或 Json 格式读取内容(错误消息)。

catch (WebException ex)
{
    var error = new StreamReader(ex.Response.GetResponseStream()).ReadToEnd();
    //Parse your error string & do something
}
于 2012-06-05T08:17:26.730 回答
0

几分钟前我刚刚遇到了类似的问题。也许它有帮助。我试图为我的所有服务调用使用扩展程序,如下所示:

这是一段不好的代码:

public static void ExecuteServiceMethod(this IMyRESTService svc, Action svcMethod)
{ 
    try
    {
       // try to get first last error here
       string lastError = svc.CommHandler.CH_TryGetLastError();
       if (!String.IsNullOrEmpty(lastError))
          throw new WebFaultException<string>(lastError, System.Net.HttpStatusCode.InternalServerError);

       // execute service method
       svcMethod();
    }
    catch (CommHandlerException ex)
    {
       // we use for now only 'InternalServerError'
       if (ex.InnerException != null)
           throw new WebFaultException<string>(ex.InnerException.Message, System.Net.HttpStatusCode.InternalServerError);
       else
           throw new WebFaultException<string>(ex.Message, System.Net.HttpStatusCode.InternalServerError);
     }
     catch (Exception ex)
     {
        throw new WebFaultException<string>(ex.Message, System.Net.HttpStatusCode.InternalServerError);
     }
}

这是固定的代码:

public static void ExecuteServiceMethod(this IMyRESTService svc, Action svcMethod)
{
    // try to get first last error here
    string lastError = svc.CommHandler.CH_TryGetLastError();
    if (!String.IsNullOrEmpty(lastError))
       throw new WebFaultException<string>(lastError, System.Net.HttpStatusCode.InternalServerError);

    try
    {
       // execute service method
       svcMethod();
    }
    catch (CommHandlerException ex)
    {
       // we use for now only 'InternalServerError'
       if (ex.InnerException != null)
           throw new WebFaultException<string>(ex.InnerException.Message, System.Net.HttpStatusCode.InternalServerError);
       else
           throw new WebFaultException<string>(ex.Message, System.Net.HttpStatusCode.InternalServerError);
     }
     catch (Exception ex)
     {
        throw new WebFaultException<string>(ex.Message, System.Net.HttpStatusCode.InternalServerError);
     }
}

所以...可能您注意到第一个throw, 被处理到catch (Exception ex)再次抛出的块中,使其始终显示:'Internal Server Error ' 。也许它有帮助,因为我看到你也有一个全球性的

捕获(异常异常){ 抛出异常;}

这可能是它的原因。

于 2012-07-18T14:28:51.560 回答
0

1)将故障合同添加到方法/操作

2) 抛出 WebFaultException 或 WebFaultException

3) 在客户端捕获到 webexception 然后读取异常响应

catch (WebException exception)
{
var resp = new StreamReader(exception.Response.GetResponseStream()).ReadToEnd();
}

与问题陈述中提到的相同的问题,并且能够通过 LB 提到的答案解决,并遵循其他一些帖子。所以总结了以下步骤

于 2015-12-30T10:06:59.137 回答