📜 ⬆️ ⬇️

Exceptions through WCF

Let's talk about passing exceptions through the WCF service.

To begin with, let's imagine a situation - we have a RegisterUser method , which respectively performs user registration. And in case of an error in entering any data, it throws a CustomException.
The registration code looks like this:
/// <summary>
/// Registers the user.
/// </summary>
/// <param name="username">The username.</param>
/// <param name="password">The password.</param>
/// <param name="email">The email.</param>
public void RegisterUser( string username, string password, string email)
{
if ( /* username*/ )
throw new InvalidUsernameException();
if ( /* password*/ )
throw new InvalidPasswordException();
if ( /* email*/ )
throw new InvalidEmailException();
...
}
* This source code was highlighted with Source Code Highlighter .

And so its use:
/// <summary>
/// Handles the Click event of the btnRegister control.
/// </summary>
/// <param name="sender">The source of the event.</param>
/// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
protected void btnRegister_Click( object sender, EventArgs e)
{
try
{
RegisterUser(txtUsernamt.Text, txtPassword.Text, txtEmail.Text);
}
catch (InvalidUsernameException usernameException)
{
// Username
}
catch (InvalidPasswordException passwordException)
{
// Password
}
catch (InvalidEmailException emailException)
{
// Email
}
...
* This source code was highlighted with Source Code Highlighter .

Everything works fine, the programmer knows how to handle the error, the user knows where the error is.
And now let's imagine that the RegisterUser method is in WCF service.
This is what MSDN says about WCF exceptions:

In all managed objects, processing. In SOAP-based applications such as WCF applications. It’s not a problem. In addition, because of the XML form, it is a very interoperable approach.

This means that the SOAP fault message is used to send the exception and you need to work with them a little differently.
Those. we can throw only FaultException .
But not everything is so boring, FaultException has a generic overload FaultException <T>. We will take advantage of it.

Let's create special classes for our errors:
/// <summary>
/// Username
/// </summary>
[DataContract]
class InvalidUsernameFault
{
[DataMember]
public string CustomError;
public InvalidUsernameFault()
{
}
public InvalidUsernameFault( string error)
{
CustomError = error;
}
}
/// <summary>
/// Password
/// </summary> [DataContract]
class InvalidPasswordFault
{
[DataMember]
public string CustomError;
public InvalidPasswordFault()
{
}
public InvalidPasswordFault( string error)
{
CustomError = error;
}
}

/// <summary>
/// Email
/// </summary>
[DataContract]
class InvalidEmailFault
{
[DataMember]
public string CustomError;
public InvalidEmailFault()
{
}
public InvalidEmailFault( string error)
{
CustomError = error;
}
}
* This source code was highlighted with Source Code Highlighter .

Now back to our WCF service.
In the interface, we must specify the FaultContract for our method:
[OperationContract]
[FaultContract( typeof (InvalidUsernameFault))]
[FaultContract( typeof (InvalidPasswordFault))]
[FaultContract( typeof (InvalidEmailFault))]
void RegisterUser( string username, string password, string email);


* This source code was highlighted with Source Code Highlighter .

Well, now we can be sure that our exceptions will reach the client:
/// <summary>
/// Registers the user.
/// </summary>
/// <param name="username">The username.</param>
/// <param name="password">The password.</param>
/// <param name="email">The email.</param>
public void RegisterUser( string username, string password, string email)
{
if ( /* username*/ )
throw new FaultException<InvalidUsernameFault>( new InvalidUsernameFault());
if ( /* password*/ )
throw new FaultException<InvalidPasswordFault>( new InvalidPasswordFault());
if ( /* email*/ )
throw new FaultException<InvalidEmailFault>( new InvalidEmailFault());
...
} FaultException . , : /// <summary>
/// Registers the user.
/// </summary>
/// <param name="username">The username.</param>
/// <param name="password">The password.</param>
/// <param name="email">The email.</param>
public void RegisterUser( string username, string password, string email)
{
if ( /* username*/ )
throw new FaultException<InvalidUsernameFault>( new InvalidUsernameFault(“ Medved ”));
if ( /* password*/ )
throw new FaultException<InvalidPasswordFault>( new InvalidPasswordFault(“ '12345' ”));
if ( /* email*/ )
throw new FaultException<InvalidEmailFault>( new InvalidEmailFault(“ ya@krasafcheg.ru”));
...
}
* This source code was highlighted with Source Code Highlighter .

')
Handling such exceptions is also easy:
/// <summary>
/// Handles the Click event of the btnRegister control.
/// </summary>
/// <param name="sender">The source of the event.</param>
/// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
protected void btnRegister_Click( object sender, EventArgs e)
{
try
{

wcfclient.RegisterUser(txtUsernamt.Text, txtPassword.Text, txtEmail.Text);
}
catch (FaultException<InvalidUsernameFault> usernameException)
{
// Username
}
catch (FaultException<InvalidPasswordFault> passwordException)
{
// Password
}
catch (FaultException<InvalidEmailFault> emailException)
{
// Email
}
catch (FaultException faultEx)
{
// ,
// WCF
} ...
}

* This source code was highlighted with Source Code Highlighter .

As you can see, there is nothing complicated! Have questions? write , be sure to figure it out ;-)
Hope this helps!
Crosspost

Source: https://habr.com/ru/post/41638/


All Articles