Я разрабатываю распределенное приложение. В нем есть роли и наборы разрешений, которые я должен проверить.
Является хорошей оценкой, чтобы бросить исключение, например, несанкционированный доступ?
Или мне нужно отправить сообщение обратно клиенту?
Хорошая практика обслуживания служб Wcf
Ответ 1
В вашей служебной операции вы можете указать FaultContract, который будет служить для обеих целей следующим образом:
[OperationContract]
[FaultContract(typeof(MyServiceFault))]
void MyServiceOperation();
Обратите внимание, что MyServiceFault должен быть отмечен атрибутами DataContract и DataMember, так же, как и сложный тип:
[DataContract]
public class MyServiceFault
{
private string _message;
public MyServiceFault(string message)
{
_message = message;
}
[DataMember]
public string Message { get { return _message; } set { _message = value; } }
}
На стороне обслуживания вы сможете:
throw new FaultException<MyServiceFault>(new MyServiceFault("Unauthorized Access"));
И на стороне клиента:
try
{
...
}
catch (FaultException<MyServiceFault> fault)
{
// fault.Detail.Message contains "Unauthorized Access"
}
Ответ 2
Ну, вы можете поймать все исключения в методах реализации службы WCF и перебросить их как FaultExceptions. Делая это таким образом, исключение будет отвергнуто на клиенте с сообщением по вашему выбору:
[OperationContract]
public List<Customer> GetAllCustomers()
{
try
{
... code to retrieve customers from datastore
}
catch (Exception ex)
{
// Log the exception including stacktrace
_log.Error(ex.ToString());
// No stacktrace to client, just message...
throw new FaultException(ex.Message);
}
}
Чтобы избежать непредвиденных ошибок, переданных обратно клиенту, также хорошей практикой никогда не бросать экземпляры Exception в код на стороне сервера. Вместо этого создайте один или несколько ваших собственных типов исключений и выбросите их. Таким образом, вы можете различать неожиданные ошибки обработки сервера и ошибки, которые возникают из-за неверных запросов и т.д.:
public List<Customer> GetAllCustomers()
{
try
{
... code to retrieve customers from datastore
}
catch (MyBaseException ex)
{
// This is an error thrown in code, don't bother logging it but relay
// the message to the client.
throw new FaultException(ex.Message);
}
catch (Exception ex)
{
// This is an unexpected error, we need log details for debugging
_log.Error(ex.ToString());
// and we don't want to reveal any details to the client
throw new FaultException("Server processing error!");
}
}
Ответ 3
Выбрасывание общих исключений Dot Net приведет к тому, что прокси-серверы служб и серверный канал будут работать в неисправном состоянии, если вы не используете basicHTTPBinding... Чтобы избежать этого, вы всегда должны бросать FaultException из сервиса... от вас поймать блок просто используйте:
throw new FaultException("Your message to the clients");