Handling exceptions in WCF

  • Thread starter Thread starter Scott Rymer
  • Start date Start date
S

Scott Rymer

I'm working on a WCF service with a LINQ to SQL back end. I'm trying to
figure out how to handle exceptions in the UI that are thrown by the
OnPropertyChanging event in the dbml.

In my dbml, I have some validation logic:

Namespace MyProject.Data
Partial Public Class User

Private Sub OnBusinessPhoneChanging(ByVal value As String)
If Not Utilities.ValidatePhone(value) Then
Throw New Exception("Invalid Phone number")
End If
End Sub

Private Sub OnEmailChanging(ByVal value As String)
If Not Utilities.ValidateEmail(value) Then
Throw New Exception("Invalid Email Address")
End If
End Sub

Private Sub OnValidate(ByVal action As
System.Data.Linq.ChangeAction)

Using db As New MyProjectDataContext
Dim usr = (From u In db.Users _
Where u.Username = _Username Or u.Email = _Email
_
Select u).FirstOrDefault
If Not usr Is Nothing Then
If usr.Username = _Username Then
Throw New Exception("A user already exists with that
username")
ElseIf usr.Email = _Email Then
Throw New Exception("A user already exists with that
email address")
End If
End If
End Using

End Sub

End Class
End Namespace

In my UI (ASP.NET website), I have:

Protected Sub Button1_Click(ByVal sender As Object, ByVal e As EventArgs)
Handles Button1.Click

Using mbr As New MembershipServiceClient

Dim u As New MembershipService.User
u.Email = txtEmail.Text

Try
u = mbr.SaveUser(u)
GridView2.DataSource = mbr.GetUsers
GridView2.DataBind()
Catch ex As FaultException(Of MyProjectFault)
Label1.Text = ex.Detail.Message
Catch ex As Exception
Label1.Text = ex.Source & "::" & ex.Message
End Try

End Using
End Sub

And SaveUser:

Public Function SaveUser(ByVal user As MyProject.Data.User) As
MyProject.Data.User

If user.Timestamp Is Nothing Then
db.Users.InsertOnSubmit(user)
Else
db.Users.Attach(user, True)
End If

Try
db.SubmitChanges()
Catch ex As Exception
Dim err As New MyProjectFault()
err.FaultCode = FaultType.UNKNOWN_ERROR
err.Message = ex.Message
If Not ex.InnerException Is Nothing Then err.Details =
ex.InnerException.ToString
Throw New FaultException(Of MyProjectFault)(err)
End Try

Return user

End Function

When I call mbr.SaveUser(u) in the UI with an email address that exists
(hitting OnValidate), I get a proper FaultException returned to the UI which
shows the proper error message. However, if I submit an invalid email
address (hitting OnEmailAddressChanging), I get an "server unable to process
request" message instead of my "Invalid email address" message at the UI.
If I turn on includeExceptionDetailInFaults, then I get the proper message
but I will eventually need to turn this off. Where can I catch the
exception in the dbml for the OnPropertyChanging events so I can convert it
to a fault?

Should I be validating in the dbml (Data Classes) in the first place? Or
should I be checking everything in the SaveUser method in the business
layer?

Thanks!
-Scott
 
:

Should I be validating in the dbml (Data Classes) in the first place? Or
should I be checking everything in the SaveUser method in the business
layer?
Vlaidation rules are business rules and validation of data should be done in
the BLL and not the DAL.

If an exception is thrown across a WCF service, then it should be due to
some fatal exception like a SQL exception and not some validation exception
thrown. Validation should be done before the call to WCF is made to reduce
the traffic over the wire between client and service.
 
I would agree with that..............but add this thought.
"As much as possible" client side validation should be done before sending
across the wire.

I guess a few scenarios, you can only validate on the server side........
perhaps your service has to call another (and totally different service) to
validate something.
Just a thought.

But rules validations should be done in the business layer. (as previously
stated).


You can check out:
http://www.idesign.net/idesign/DesktopDefault.aspx?tabindex=5&tabid=11#WCFEssentials

and these 3 examples:
ErrorHandlerBehavior Attribute
Fault Contract
IErrorHandler


Or better yet, buy Juval Lowy's book on WCF.
 
Thanks... so basically do validation as close to the client UI as possible
to avoid traffic?
In that case, all my string format validators could be moved to
<asp:RegularExpressionValidator> or better yet, some sort of client side
validator script? What if I want to reuse my service for another project?
I will then need to implement another set of validators in that
application... I suspect this is why it's done in the reusable BLL. What
traffic are we reducing then?

I'm finding with LINQ to SQL and the ability to implement/extend partial
classes in the DAL, the line between BLL and DAL is getting faint...

-Scott
 
Scott said:
Thanks... so basically do validation as close to the client UI as
possible to avoid traffic?

Why send the object across the wire to be validated. If you're working
with N-tier applications, then the BLL, MVP or MVC is setting on the
client side where validation is more than what the UI can stop using
Validators.
In that case, all my string format validators could be moved to
<asp:RegularExpressionValidator> or better yet, some sort of client side
validator script?

You can do that.
What if I want to reuse my service for another
project? I will then need to implement another set of validators in that
application... I suspect this is why it's done in the reusable BLL.
What traffic are we reducing then?

The transmission of an object or object graph over the wire from the
client to the service should be reduced in a multi user application
using a Web service as others are using the Web server too front-end and
back-end Web servers, which is a best practice.

The time for the object or object graphic to be sent over the wire to a
Web service or WCF Web service is for CRUD operations. You get in and
you get out.
I'm finding with LINQ to SQL and the ability to implement/extend partial
classes in the DAL, the line between BLL and DAL is getting faint...

It shouldn't if one is creating proper N-Tier and SOA applications. The
DAL is the Data Access Layer for CRUD operations, and the BLL is the
Business Logic Layer for business rules.

Now, all the layers can be working with the same object, because it is
using Linq-2-SQL or ADO.NET Entity Framework with a model based on OOPs,
meaning you can validate the object's properties at the BLL and send
messages about the object state to the UI without the use of Validator
controls.
 
sloan said:
I guess a few scenarios, you can only validate on the server side........
perhaps your service has to call another (and totally different service) to
validate something.
Just a thought.

Yes, there are some exceptions like a business object has many child
graphs/collection with must be validated. In this case, the validation
of the object was done on the WCF service side injecting the object into
a Windows Workflow validation (about 30 steps) with some steps hitting
the DAL for validation with other tables on the ADO.NET EF model.

The object held its error collection messages in the object. The object
was sent back if not valid with error collection messages displayed to
the user.
 
Back
Top