提供WCF Webhttp绑定的例外 [英] Provide exceptions for wcf webhttpbinding
问题描述
我必须使用基本身份验证和ssl将wcf Web服务的绑定从tcpbinding更改为webhttpbinding.
I have to change a binding for wcf webservices from tcpbinding to webhttpbinding with basic authentication and ssl.
Web服务是自动托管在控制台应用程序和Windows生产版本的服务中.某些本地服务具有命名管道绑定,即使一个服务调用另一个服务也是如此.
Webservices are self hosted in a console application and in a windows service for production version. Some of local services are with named pipe binding, just if a service call another service.
一切正常,但不能使用全局错误管理器(实现IErrorHandler接口的类)
All works perfectly but not the global error manager (a class that implement IErrorHandler interface)
某些DAL或业务方法在自定义消息中引发异常,并且此消息已正确提供给客户端(一段时间进行单元测试).但是由于更改绑定,单元测试中捕获的异常始终是500错误,内部服务器错误和自定义消息不在异常对象中.
Some of DAL or business methods throw an exception with a custom message and this message was correctly provide to client (unit test for a while). But since I change binding, exceptions caught in unit test are always a 500 error, internal server error and custom messages are not in exception object.
服务器代码:
// Création de l'URI
var baseAddress = new Uri($"https://localhost/blablabla/{typeof(TBusiness).Name}");
// Création du Host avec le type de la classe Business
var host = new ServiceHost(typeof(TBusiness), baseAddress);
// Liaison WebHttpBinding sécurité transport
var binding = new WebHttpBinding
{
MaxBufferSize = 2147483647,
MaxReceivedMessageSize = 2147483647,
Security = new WebHttpSecurity
{
Mode = WebHttpSecurityMode.Transport
},
};
binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Basic;
// Permet de renvoyer du xml et du json
var webBehavior = new WebHttpBehavior
{
AutomaticFormatSelectionEnabled = true
};
var ep = host.AddServiceEndpoint(typeof(TContracts), binding, "");
ep.Behaviors.Add(webBehavior);
var sdb = host.Description.Behaviors.Find<ServiceDebugBehavior>();
sdb.HttpHelpPageEnabled = false;
// Activation https
var smb = new ServiceMetadataBehavior
{
HttpGetEnabled = false,
HttpsGetEnabled = true,
};
host.Description.Behaviors.Add(smb);
// Ajout de l'authentification
var customAuthenticationBehavior = new ServiceCredentials();
customAuthenticationBehavior.UserNameAuthentication.UserNamePasswordValidationMode = UserNamePasswordValidationMode.Custom;
customAuthenticationBehavior.UserNameAuthentication.CustomUserNamePasswordValidator = new SessionAuthentication();
host.Description.Behaviors.Add(customAuthenticationBehavior);
// Démarrage du host
host.Open();
抛出异常的业务方法:
public TOUser GetUserByLogin(string login)
{
using (var service = new ServiceProviderNamedPipe<IBFSessionManager, BSSessionManager>())
{
// Récupération de la DALUsers
var dal = service.Channel.GetDALUsers(OperationContext.Current.ServiceSecurityContext.PrimaryIdentity.Name);
var user = dal.GetUserByLogin(login);
if (user == null) throw new FaultException(Errors.DALUsers_Err001);
return BMToolsEntitiesToTO.UserToTOUser(user);
}
}
错误全局管理器:
public class GlobalErrorHandler : IErrorHandler
{
public bool HandleError(Exception error)
{
// Empèche la propagation de l'erreur
return true;
}
public void ProvideFault(Exception error, MessageVersion version, ref Message fault)
{
var msg = error.Message;
// Création de l'exception de retour
var newEx = new FaultException(msg);
var msgFault = newEx.CreateMessageFault();
fault = Message.CreateMessage(version, msgFault, newEx.Action);
}
}
单元测试:
public void GetUserByLoginWithUnknownLoginTest()
{
TOUser user = null;
using (var service = new ServiceProviderHTTP<IBFUsers, BSUsers>(_user))
{
try
{
user = service.Channel.GetUserByLogin("1234");
}
catch (Exception e)
{
// e.message always provide "Internal server error instead of custom message (Errors.DALUsers_Err001)
Assert.AreEqual(Errors.DALUsers_Err001, e.Message);
}
Assert.IsNull(user);
}
}
自从我更改绑定以来,所有捕获异常的单元测试都失败了.
All unit tests that catch exception failed since I change binding.
谢谢您的帮助.
推荐答案
经过几次搜索,我发现很多人都遇到同样的问题.
After several search, I saw that a lot of people have same problem.
这是我的解决方法:
在服务器端,始终使用正确的HTTP状态代码抛出此类WebFaultException:
On server side, always throw a WebFaultException like this with correct HTTP Status code :
throw new WebFaultException<string>(myStringMessage, HttpStatusCode.NotFound);
在客户端(仅用于单元测试或MVC项目),强制转换异常以在Response对象上调用GetResponseStream以获取自定义消息:
On client side (only for unit tests or MVC project), cast exception to call GetResponseStream on Response object to get custom message :
var err = (WebException)e;
using (Stream respStream = err.Response.GetResponseStream())
{
using (var reader = new StreamReader(respStream))
{
var serializer = new XmlSerializer(typeof(string));
var response = reader.ReadToEnd();
return response.Substring(response.IndexOf('>') + 1).Replace("</string>", "");
}
}
在IErrorHandler的ProvideFault方法中,我只是添加代码将错误写入文件中,而没有使用Message.CreateMessage方法创建消息.
In ProvideFault method from IErrorHandler, I just add code to write errors in a file but not create a message with Message.CreateMessage method.
它可以正常工作,但会在ProvideFault之后生成EndPointNotFoundException,在其他一些帖子中,我看到可能会抛出ProtocolException.
It works correctly but generate an EndPointNotFoundException after ProvideFault, in some other posts I saw that a ProtocolException could be thrown.
谢谢您的发言.
这篇关于提供WCF Webhttp绑定的例外的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!