提问人:Sanam 提问时间:10/31/2019 最后编辑:Abraham QianSanam 更新时间:11/1/2019 访问量:1385
如何捕获/处理 WCF 中由于类型强制转换或在通过 postman 调用时将无效值传递给变量而发生的异常
How to catch/handle exceptions in WCF that occur due to type casting or passing invalid values to the variables while calling through postman
问:
我是 WCF 的初学者。在构建 RestFul API 时,我遇到了一些崩溃问题。
在我通过 WCF 处理异常的过程中,我从各种来源获得了帮助,如下所示:
WCF 异常处理策略 https://blogs.msdn.microsoft.com/pedram/2008/01/25/wcf-error-handling-and-some-best-practices/ https://riptutorial.com/csharp/example/5460/implementing-ierrorhandler-for-wcf-services
通过实现全局错误处理程序,应用程序的内部异常可以顺利处理(通过在 try catch clock 中处理它们)。但我不确定如何处理铸造异常。即,如果变量获得无效值,则导致应用程序崩溃的异常。
编辑:
我有一个以下 DataContract 类
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Runtime.Serialization;
using System.Web;
namespace StilaarAPI.DataContracts
{
[DataContract]
public class Products
{
[DataMember]
[Required(ErrorMessage = "product Name is required")]
[StringLength(50, MinimumLength = 5, ErrorMessage = "Address Feild length should be between 5 and 50")]
public string ProductName { get; set; }
[Required(ErrorMessage = "ProductID is requied")]
[DataMember]
public int ProductID { get; set; }
}
}
然后(启用 Ajax 的 WCF 服务使用上面的 DataContract 类作为输入参数)
[OperationContract]
[WebInvoke(Method = "POST", RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json, BodyStyle = WebMessageBodyStyle.Wrapped)]
public string GetProduct(Products pro)
{
try
{
string test = "Every thing works fine :D";
return test;
//ResultDo<List<ProblemTypesDo>> result = new ResultDo<List<ProblemTypesDo>>();
//var problemTypes = _riderOrderDeliveryBL.GetProblemType();
}
catch (NotFoundException ex)
{
NotFoundFault fault = new NotFoundFault();
fault.Error = "Product Not Found";
fault.StatusCode = HttpStatusCode.NotFound;
throw new WebFaultException<NotFoundFault>(
fault, HttpStatusCode.NotFound);
}
}
从邮递员调用上述服务只是给出流畅的简单结果:
这很好,现在如果我在输入变量上运行不同的输入场景: 从将 null 值设置为产品名称开始,它给了我以下结果
不错,因为我的验证有效并且正在处理异常,所以我得到了上述结果。 现在进入下一个场景,如果我将 ID 设置为 null,则会出现以下输出:
现在,我的问题是我能做些什么来防止应用程序像这样崩溃:
以下是我的 IError 处理程序类:
public class GlobalErrorBehaviorAttribute : Attribute, IServiceBehavior
{
private readonly Type errorHandlerType;
/// <summary>
/// Dependency injection to dynamically inject error handler if we have multiple global error handlers
/// </summary>
/// <param name="errorHandlerType"></param>
public GlobalErrorBehaviorAttribute(Type errorHandlerType)
{
this.errorHandlerType = errorHandlerType;
}
#region IServiceBehavior Members
void IServiceBehavior.Validate(ServiceDescription description,
ServiceHostBase serviceHostBase)
{
}
void IServiceBehavior.AddBindingParameters(ServiceDescription description,
ServiceHostBase serviceHostBase,
Collection<ServiceEndpoint> endpoints, BindingParameterCollection parameters)
{
}
/// <summary>
/// Registering the instance of global error handler in dispatch behavior of the service
/// </summary>
/// <param name="description"></param>
/// <param name="serviceHostBase"></param>
void IServiceBehavior.ApplyDispatchBehavior(ServiceDescription description,
ServiceHostBase serviceHostBase)
{
IErrorHandler errorHandler;
try
{
errorHandler = (IErrorHandler)Activator.CreateInstance(errorHandlerType);
}
catch (MissingMethodException e)
{
throw new ArgumentException("The errorHandlerType specified in the ErrorBehaviorAttribute constructor must have a public empty constructor.", e);
}
catch (InvalidCastException e)
{
throw new ArgumentException("The errorHandlerType specified in the ErrorBehaviorAttribute constructor must implement System.ServiceModel.Dispatcher.IErrorHandler.", e);
}
foreach (ChannelDispatcherBase channelDispatcherBase in serviceHostBase.ChannelDispatchers)
{
ChannelDispatcher channelDispatcher = channelDispatcherBase as ChannelDispatcher;
channelDispatcher.ErrorHandlers.Add(errorHandler);
}
}
#endregion IServiceBehavior Members
}
public class GlobalErrorHandler : IErrorHandler
{
public bool HandleError(Exception error)
{
return true;
}
public void ProvideFault(Exception error,System.ServiceModel.Channels.MessageVersion version,ref System.ServiceModel.Channels.Message fault)
{
//if (error is FaultException)
// return;
var jsonError = new CustomFault
{
Error = "Something went wrong",
Details = error.GetType().FullName
};
fault = Message.CreateMessage(version, "", jsonError,
new DataContractJsonSerializer(typeof(CustomFault)));
// Tell WCF to use JSON encoding rather than default XML
var wbf = new WebBodyFormatMessageProperty(WebContentFormat.Json);
fault.Properties.Add(WebBodyFormatMessageProperty.Name, wbf);
// Modify response
var rmp = new HttpResponseMessageProperty
{
StatusCode = HttpStatusCode.BadRequest,
StatusDescription = "Bad Request",
};
rmp.Headers[HttpResponseHeader.ContentType] = "application/json";
fault.Properties.Add(HttpResponseMessageProperty.Name, rmp);
}
}
public class ExtendedWebHttpBehavior : WebHttpBehavior
{
protected override void AddServerErrorHandlers(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher)
{
// clear default erro handlers.
endpointDispatcher.ChannelDispatcher.ErrorHandlers.Clear();
// add our own error handler.
endpointDispatcher.ChannelDispatcher.ErrorHandlers.Add(new GlobalErrorHandler());
//BehaviorExtensionElement
}
}
我该如何处理它,以便我可以向客户端发送干净的错误消息
编辑: 邮递员一般例外:
?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE html
PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Request Error</title>
<style>
BODY {
color: #000000;
background-color: white;
font-family: Verdana;
margin-left: 0px;
margin-top: 0px;
}
#content {
margin-left: 30px;
font-size: .70em;
padding-bottom: 2em;
}
A:link {
color: #336699;
font-weight: bold;
text-decoration: underline;
}
A:visited {
color: #6699cc;
font-weight: bold;
text-decoration: underline;
}
A:active {
color: #336699;
font-weight: bold;
text-decoration: underline;
}
.heading1 {
background-color: #003366;
border-bottom: #336699 6px solid;
color: #ffffff;
font-family: Tahoma;
font-size: 26px;
font-weight: normal;
margin: 0em 0em 10px -20px;
padding-bottom: 8px;
padding-left: 30px;
padding-top: 16px;
}
pre {
font-size: small;
background-color: #e5e5cc;
padding: 5px;
font-family: Courier New;
margin-top: 0px;
border: 1px #f0f0e0 solid;
white-space: pre-wrap;
white-space: -pre-wrap;
word-wrap: break-word;
}
table {
border-collapse: collapse;
border-spacing: 0px;
font-family: Verdana;
}
table th {
border-right: 2px white solid;
border-bottom: 2px white solid;
font-weight: bold;
background-color: #cecf9c;
}
table td {
border-right: 2px white solid;
border-bottom: 2px white solid;
background-color: #e5e5cc;
}
</style>
</head>
<body>
<div id="content">
<p class="heading1">Request Error</p>
<p xmlns="">The server encountered an error processing the request. Please see the <a rel="help-page"
href="https://localhost:44326/ServiceContracts/CustomerAccount.svc/help">service help page</a> for
constructing valid requests to the service.</p>
</div>
</body>
</html>
调试器异常:
不能将值 '' 分析为类型 'Int32'。{“格式化程序 在尝试反序列化消息时抛出异常:有 尝试反序列化参数 :p ro.这 InnerException 消息为“反序列化 StilaarAPI.DataContracts.Products 类型的对象。值 '' 不能 解析为类型“Int32”。有关详细信息,请参阅 InnerException 详细信息。
答:
请求正文未以本地 JSON 格式进行身份验证。它不满足 JSON 架构,这意味着请求尚未到达服务器,因此服务器不会根据 IErrorHandler 接口对其进行处理。
它应该像下面的形式一样,以便请求可以到达服务器。
{"Id":null,"Name":"Apple"}
如果有什么我可以帮忙的,请随时告诉我。
更新。
不要干扰 IErrorhandler 接口中的序列化过程,请考虑使用以下代码来处理错误。
public void ProvideFault(Exception error, MessageVersion version, ref Message fault)
{
MyError myerror = new MyError()
{
Details = error.Message,
Error = "Hello"
};
fault = Message.CreateMessage(version, "messsagefault", myerror);
}
或者,我们可以直接发送错误详细信息。
FaultException faultException = new FaultException(error.Message);
MessageFault messageFault = faultException.CreateMessageFault();
fault = Message.CreateMessage(version, messageFault, error.Message);
此外,我们可以处理 IClientMessageFormatter/IDispatcherMessageFormatter 中消息的序列化。
https://learn.microsoft.com/en-us/dotnet/framework/wcf/extending/custom-message-formatters
评论
Address
评论
address
address