Не могу отправить исключения из моего приложения WCF - PullRequest
0 голосов
/ 28 марта 2012

Следуя инструкциям здесь

http://beyondrelational.com/modules/2/blogs/79/posts/11543/throwing-exceptions-from-wcf-service-faultexception.aspx

Я получил следующий код:

Интерфейс:

[ServiceContract]
public interface IAuthenticator
{
    [OperationContract]
    [FaultContract(typeof(AuthenticationException))]
    Account authenticateApplication(string userName, string Password);
}

Исключение:

[DataContract]
public class AuthenticationException
{
    private string validationError;

    [DataMember]
    public string ValidationError
    {
        set { validationError = value; }
        get { return validationError; }
    }

    public AuthenticationException(string valError)
    {
        validationError = valError;
    }
}

И, наконец, вот как я выкидываю ошибки в моей реализации authenticateApplication:

catch (InvalidUsernameException)
{
    throw new FaultException<AuthenticationException>(new AuthenticationException("The username you entered could not be found in our database."), new FaultReason("Error"));
}

Проблема в том, что вместо отправки ошибки клиенту приложение WCF приложения завершает работу, говоря, что я не обработал исключение.

Если это имеет значение, вот как я звоню своему клиенту:

try
{
    myAcc = httpProxy.authenticateApplication("some text", "some other text");
}
catch (FaultException<AuthenticationException> ex)
{
    MessageBox.Show(ex.Detail.ValidationError);
    return;
}

Редактировать: Вот мой след стека:

   at AuthenticatorService.Authenticator.authenticateApplication(String userName, String Password) in E:\Miscellaneous\Applications\Web 2.0 Creator\AuthenticatorService\AuthenticatorService\AuthenticatorService\Authenticator.cs:line 109
   at SyncInvokeauthenticateApplication(Object , Object[] , Object[] )
   at System.ServiceModel.Dispatcher.SyncMethodInvoker.Invoke(Object instance, Object[] inputs, Object[]& outputs)

Редактировать Редактировать:

Вот полный блок try try:

try
{
    using (myConnection)
    {
        using (myCommand)
        {
            //Tell it to execute the stored procedure on the database
            myCommand.CommandText = "findUsername";
            myCommand.CommandType = CommandType.StoredProcedure;
            myCommand.Parameters.Add("@userName", SqlDbType.NVarChar, 20);
            myCommand.Parameters["@userName"].Value = userName;

            //If the reader returns 0 rows, that means the username doesn't exist in the database, so step there and return an exception
            using (myReader)
            {
                myReader = myCommand.ExecuteReader();
                if (myReader.HasRows == false)
                {
                    InvalidUsernameException iue = new InvalidUsernameException();
                    throw iue;
                }
                else //Else we store the fields
                {
                    myAcc.Password = myReader[1].ToString();
                    isActive = Convert.ToBoolean(myReader[2]);
                    myAcc.Key = myReader[3].ToString();
                    myAcc.ExpiryDate = myReader[4].ToString();
                }
            }
        }
    }
}
catch (SqlException)
{
    throw new FaultException<AuthenticationException>(new AuthenticationException("There was an error while connecting the database, please contact support."), new FaultReason("Error"));
}
catch (InvalidOperationException)
{
    throw new FaultException<AuthenticationException>(new AuthenticationException("An error in the program while connecting to the database."), new FaultReason("Error"));
}
catch (InvalidUsernameException)
{
    throw new FaultException<AuthenticationException>(new AuthenticationException("The username you entered could not be found in our database."), new FaultReason("Error"));
}
catch (Exception)
{
    throw new FaultException<AuthenticationException>(new AuthenticationException("There was a general error during the process."), new FaultReason("Error"));
}

Ответы [ 3 ]

2 голосов
/ 28 марта 2012

Попробуйте добавить конструктор без параметров в класс AuthenticationException. Или:

[DataContract]
public class AuthenticationException
{
    [DataMember]
    public string ValidationError { get; set; }
}

и к вашим услугам:

throw new FaultException<AuthenticationException>(
    new AuthenticationException 
    { 
        ValidationError = "The username you entered could not be found in our database."
    }, 
    new FaultReason("Error")
);

Также помните, что это работает только для исключений, которые происходят внутри блока try / catch. Если есть какое-то другое исключение, возникающее в какой-либо другой части службы, которая не переведена в FaultContract, вы не поймаете его как FaultException<T> на клиенте.

Также рекомендуется централизовать обработку исключений вашей службы WCF в одном месте с помощью пользовательского IErrorHandler , который будет распространять ошибки вместо размещения блоков try / catch по всему коду.

1 голос
/ 28 марта 2012

Похоже, вам нужно вызвать myReader.Read, прежде чем получить доступ к его полям.

0 голосов
/ 28 марта 2012

Я нашел ответ на мою проблему на этой странице:

http://sergecalderara.wordpress.com/2008/11/25/systemservicemodelfaultexception1-was-unhandled-by-user-code/

Вам необходимо отключить следующие параметры Visual Studio:

enter image description here

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...