Currently in the ASP.NET application I'm developing, basic validations (ie required fields) are being done in the Presentation Layer, using Validators and a ValidationSummary. This is working great for me specifically since the ValidationSummary will display multiple error messages (assuming multiple Validators are set to invalid).
I also have some validations being done in the business layer - due to their complexity (and data service layer reliance) I'd rather not keep them in the presentation layer. However, I'm not sure the best way to send these back to the presentation layer for display to the user. My initial consideration is to send back a List<string> with failed validation messages and then dynamically create a CustomValidator control (since apparently you can only bind one error message to one Validator control) for each error to show in the ValidationSummary when there are any.
I'm assuming I'm not the first one to come across this issue, so I'm wondering if anyone has any suggestions on this.
Thanks!
There are essentially two ways to do this: either by passing back an error code/object from your business layer, or throw out an exception. You can also combine both.
For an example, you can take a look SqlException class. When you send a SQL to SQL Server, it runs a query parser to parse your SQL first. If it sees syntax error, then it will throw out a SqlException and terminate the query. There may be multiple syntax errors in your query. So SqlExeption class has an Errors property that contains a list of errors. You can then enumerate through that list in your presentation layer to format your error message, probably with a CustomValidator.
You can also simply just return the error list without throwing an exception. For example, you can have your function to return a List in case at least one error occurred and return null in case the call was successful. Or you can pass List as an argument into your function. They are all fine, it all depends on which way you feel is more convenient. The advantage of throwing out an exception is it unwinds multiple call frames immediately, so you don’t have to check return value on every level. For example, if function A calls function B , B calls function C, C sees something wrong, then if let C to return an error object (or error code), then B has to have code to check whether C returned an error and pass that error code/value back, A have to check it as well ---- you need to check it on every level. On the other hand, if you just let C to throw an exception, then the code goes straight to the exception handler. You don’t have check return values on every level.
Related
Is it possible to get multiple error messages for missing required fields in a single error message to the user? For example, if I left all 5 of my required fields blank, the error message that is displayed when clicking Submit will show all 5 messages in the same window.
This is a fantastic idea and should be added to the PeopleSoft Idea Spaces in MyOracle Support. Unfortunately, this is not delivered. There are multiple ways a person might trigger an exception, including:
Choosing an invalid value
Leaving required fields blank
Failing FieldEdit or SaveEdit PeopleCode
Unfortunately, PeopleSoft fails on the first, not all. Regarding the last item: FieldEdit/SaveEdit, as soon as you trigger the PeopleCode Error function, PeopleCode halts, so it is impossible for us to use the Error function to queue multiple exceptions.
With all that said, nothing is impossible. One way to accomplish this would be to use our own JavaScript/CSS to mark all fields that fail validation. This would require us to write additional PeopleCode, etc., to work around Oracle's delivered validation.
One approach to do that is to perform the validations "manually", stack then and present to the user.
In order to do that, you need to have a custom "Save" or "Validate Button", and your peoplecode would stack the errors.
You can use the vanilla required fields validation + any conditional validation you need.
A good way to present this is just have a field(long) or an html area and nicely present the errors:
Emplid is required
Setid is required
Enter an end date less than start date
But otherwise, this is not part of Peopletools, although some modules do offer this (eSupplier Portal for instance has a similar feature).
We have a WebForms Control which requires that the ID of another Control implementing ITextControl is provided.
What exception should we throw if there is no control with that ID or a control is found but it's not implementing the interface?
var text = Page.FindControl(TextProviderId) as ITextControl;
if (text == null) {
throw new WhatEverException(...);
...
Should we split it into two cases and throw one exception if there is no control with that ID, and another one if said control does not implement ITextControl? If so, which exceptions should we use then?
If the control should really be there, I would say that your web form is in an invalid state if it is missing, so I would probably go for InvalidOperationException:
The exception that is thrown when a method call is invalid for the object's current state.
This would be applicable to both scenarios; regardless of whether the control is missing or if it does not implement the expected interface, the containing object is in an invalid state.
If this is a scenario that is expected to happen for various reasons (let's say that you are making some tool that others will program against, and this is a situation that they might very well produce), perhaps you should instead create two custom exceptions that make it very clear what is happening and how to correct it (such as ControlNotFoundException and InterfaceNotFoundException or something similar).
ArgumentOutOfRangeException?
Whether or not you should split them up into different exceptions probably depends most on whether or not you think it is likely that anyone will ever want to distinguish the two exceptions in different catch blocks.
Not knowing exactly how this will be used, this seems like the kind of error that should be brought to the developer's attention, where rewriting code to point to the correct file or implement the correct interface is the proper action, rather than implementing a try-catch and give the user friendly error messages. As such, I'd just throw an ArgumentException.
How can i pass the different types of errors from Data access layer to presentation layer?
suppose if we take the northwind database
scenario
I want to delete the customer, so i selected one customer in ui and clicked the "delete" button.It internally calls the "delete" in data access layer.
The prerequisite for deleting the customer is that the customer doesn't have any orders.So in data access layer we wil check whether that customer has any orders.If the customer has orders how can we pass the message from dal to presentation layer that the customer has orders and we don't delete.
Am i doing right?is there any other ways to deal with this type?
Thanks in advance
The other answers tell you how you should be implementing this particular scenario, however to answer your original question, the answer is to define your own exceptions.
You can have a core DataLayerException as the base for all of you data exceptions (inheriting from ApplicationException or similar) then have sub exceptions based on the scenario, e.g.:
ConnectionClosedException
TImeoutException
etc.
For me personally, it would be better to call a separate "ValidateDeletion" method prior to attempting a delete. This would first check to see if that customer has orders before removing them from the database.
Particulary, if you want to raise different kinds of exception from database... I use to raise an error from SP like this.
if (#invalidCount <> 1)
Begin
Raiserror('[Duplicate] Record Already Posted In System ', 20, 1)
End
Catch the error in the DAL, and analyse the exception type through the exception message (here the keyword for me is the "[Duplicate]") and throw the different kind of exception appropriately.
Of course this will be very cumboresum if you have more than 2/3 types of exceptions.
For me the best way is to raise an event TryToDeleteCustomerWithOrders.
The validation part is also fine, but it's about data, so the data layer should do the whole work. If you put the validation outside, there is chance that you call the deletion function without validation ....
Suppose I have a button in an aspx page that performs a save of the form data to the database. In the associated event handler, before sending the updates, I read something from a webservice, operation that might result in an exception. In case of an error I want to have an adequate message displayed on the page, and all the data in the form preserved. How can I achieve this? Also, all my pages inherit from a basepage, so I would like, if possible to have all the error handling code in the base class. I do not want, if possible, to surround any web service call with try-catch blocks, I would in case of any unhandled exception to call some method automatically, something like Page_error, but still preserve the data in my forms.
You can easily put a method that manages the display message (maybe setting the text of some errorMessageLabel) in a superclass called from any derived class (if you wanna use inheritance to setup a template for your pages) if an exception is thrown (you can put the call to the superclas method in a catch block if there's actually an exception being thrown or you can manage this manually if the webservice is unavailable depending on your programming style).
As far as preserving the data presented, if viewstate is on and you are not populating your page dynamically then you're ok - if not, you need to explicitly save state information in viewState or session entries and retrieve them back if something goes wrong.
This bit really depends on how your page is actually implemented.
I am using methods with the Attribute [WebMethod] in my aspx pages. I don't use any asp.net ajax but jQuery to call these methods and return objects in JSON. This all works fine.
Next I added an authorization check inside the webMethod, if the current user doesn't have access to the feature I need to let the calling JavaScript know.
So I am throwing an AccessViolationException exception which can then be parsed by the OnError callback function in JavaScript. This works too but the exception includes the full StackTrace and I don't want to make this available to the calling client.
What other ways I could use to return an "Access Denied" to the client when the WebMethod returns a business object?
I'm using ASP.Net 3.5SP1 and jQuery 1.32
You can also add a:
customErrors mode="On"/
in your web.config, this will cut away the stack trace and leave you only the exception message
Why propagate errors through the wire? why not use an error response ?
Just wrap your object in a response object wich can contain an error code for status and an error message to present to users.
As suggested by NunFur I changed my approach and rather than throwing an error, I return a 'richer' object.
There are at least two options, the first one would be to encapsulate my business object into a response object with some status properties. I tried this but it makes the JSON more complicated.
So rather than adding a new object I added two properties to my business object, something like ServiceStatus and ServiceMessage. By default these are 200 and '', but can be set by the WebMethod code if anything goes wrong (no access, proper error). In this case they business object will be 'empty' (no data). The JavaScript code then first checks for the ServiceStatus and reacts appropriately.
I add the two fields to all my objects that are returned by WebMethods, even a simple string. They have to implement an Interface with those two properties.
Now I have complete control over that goes over the wire in case something unexpected is happening.
Thanks for the input
I save exceptions for when things go really wrong. (e.g. can't connect to the database)
Either return nothing (null/nill/whatever), or return a false bool value.
Sorry that I don't have a better answer than that...I'll have to keep looking myself.
You could look at SoapException: http://msdn.microsoft.com/en-us/library/system.web.services.protocols.soapexception(VS.71).aspx
I'm just not sure, if it will work when it is called from JavaScript. Espeially if it's called with a get-request.
BTW AccessViolationException is to my best knowlegde ment to be thrown when the application is accessing memory it has no access to.
/Asger