From: Scott Rymer on 5 Mar 2010 09:30 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
From: Mr. Arnold on 5 Mar 2010 13:04 "Scott Rymer" wrote: > 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.
From: sloan on 5 Mar 2010 14:44 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. "Mr. Arnold" <No(a)No.com> wrote in message news:753FCBE7-BF56-4C90-AA95-151B79C1696F(a)microsoft.com... > > > "Scott Rymer" wrote: > > >> 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.
From: Scott Rymer on 5 Mar 2010 15:45 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 "Mr. Arnold" <No(a)No.com> wrote in message news:753FCBE7-BF56-4C90-AA95-151B79C1696F(a)microsoft.com... > > > "Scott Rymer" wrote: > > >> 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.
From: Mr. Arnold on 6 Mar 2010 00:09
Scott Rymer wrote: > 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. |