How to handle Object Data Source Exception handling in DotNetNuke - asp.net

I've created several DNN (5.2.3) modules and I'm finding that if an error happens on the object data source (ODS) DNN will then show that error to everyone. A sample (though not a ODS specific error in this case) is shown below. This has no meaning to user. The exception should really be "Thing not found" or something like that to the user. The problem is that this DropDownList is bound to an ODS. So my questions are:
How in DNN can I override this behavior to show a helpful message using ODS binding?
How in DNN can I override this behavior to show a generalized exception for all errors for the current module, if a specific exception cannot be caught to give a helpful message to the user?
Sample:
'SelectedThingDropDown' has a SelectedValue which is invalid because it does not exist in the list of items. Parameter name: value
PS> I know about try/catch Exceptions.ProcessModuleException(e,ex). The problem is this does not work for ODS binding, unless I'm doing something wrong.

There are number of places you can inspect while dealing with ODS and DropDownList. Here is list of some of them.
ODS_Selected event, check e.Exception: This object is having errors when calling Select method provided. It's null if there is no error. If you find error, you can disable the ddl and place a user friendly message in label for notification.
DDL_DataBound event: Don't directly bind the selected value, try to find the the dll items by value like :
ListItem item = ddl.Items.FindByValue('');
if(item != null) item.selected = true;
Keep in mind that module load exception will be there only if you are not handling the exceptions, if you feel they are not helpfull to user, you can override them by your own user notification method with the help of try catch as you said. but don't forget to create entries in the event log for the error so that you can track your errors and optimize them.
Good luck.

Related

ASP.NET Exception Handling presentation to user

I have added try catches in my site which work great. The next part in development is to set up some exception handling output. Obviously I don't want the site to crumble when an error occurs and I don't want a horrible error screen. So, somewhere in the middle would be nice.
I was thinking to have an exception handler user control in the main master page which wil output a nice little message when something goes wrong.
What would be the best way to pass the exception to this user control? I was thinking of using a session variable.
Does anyone have a solution to this problem?
Thanks
This is easier than you're making it. Create a page called error.aspx (or whatever you want to call it), and turn the CustomErrors on in the web.config.
<configuration>
<system.web>
<customErrors defaultRedirect="errors.aspx"
mode="On">
</customErrors>
</system.web>
</configuration>
There is a lot of configurability to handle different http errors or random exceptions. If you want, you can dump the exception message (or the exception itself) into the session or use the HttpServerUtility.GetLastError (documentation)and then output any number of different messages on the error page. This will even catch exceptions that you DON'T catch.
CustomErrors Documentation
Edit:
#Icarus indicates that OP is looking for a solution by which the page continues to render and output while only showing an error message within the page, so I'll provide an answer to that as well.
There are a few ways I've handled this in the past. For very complex pages where the behavior requested is fatal (the page result can't be known), I've always deferred to an error page as I mentioned above that includes major master elements. So the menu, header, etc are all still there, but the notification of cataclysm is evident.
The behavior you seem to be looking for is something I would use less out of a need to report exceptions than to report general messages. My preference is to have a user control that has a public bindable property that a message can be injected into. Such as (forgive the VB, I can't seem to find my C# version):
<BrowsableAttribute(True), Bindable(False), Category("Misc"), _
Description("Gets or sets the NavigateUrl property for the link to start a new request.")> _
Public Property MyImportantMessage() As String
Get
Return _myImportantMessage
End Get
Set(ByVal value As String)
_myImportantMessage= value
End Set
End Property
Then the output could be any string message you like or you could program in a number of presets, fetch from resources, whatever. As to how to get it in there, we have taken the MasterPage route. We have a method in our master pages which assigns such a property in the user control directly. In order for this method to be callable, each page that uses the master page has to include the VirtualPath property, otherwise the method will not be available at compile time.
<%# MasterType
VirtualPath="~/MasterPage.master" %>
This then allows the Master property to be called from within the page itself to call this property:
'Keeping the VB theme
Me.Master.SetImportantMessage(message)
Keep in mind that Me.Master from within the page is not the same as Page.Master. So your exception will either need to bubble up to the actual page or the page reference itself will have to be sent down to your usercontrols as a property.
If you're wanting to provide an error for a handled exception, it's really as simple as populating a label with some sort of a notice that the application had a problem processing a request. You would do this within the "catch" part of the statement. I've even gone as far as presenting different messages depending on the role of the user. For instance if an admin generates an error you could actually output the actual exception message, but if someone in a lesser role generates it it would show them a more generic error and send the admin group a message/email.
try
{
//your code here
}
catch (Exception ex)
{
if (Role!="Admin")
{
Label1.Text = "There was an error, the administrator has been notified."
}
else
{
Label1.Text = "Error: " + ex.Message + ": " + ex.StackTrace; //you could add further here if you want to look for an inner exception.
}
}

Help with updating vb.net formview using storedprocedure

I have followed this tutorial for the most part to explain what I am doing. http://www.asp.net/data-access/tutorials/creating-a-business-logic-layer-vb
What i need to do is figure out the best way to approach to be able to update my formview. I do not understand what the tutorial is trying to explain to me so i tried it the way i have updated a gridview before. But I am receiving "No parameterless constructor defined for this object." I tried to debug and view the callstack but it does not really tell me much.
I have my sql stored procedure to update which when executed works fine.
I also have another class in which i reference the application details class
applicant.vb
This is the code in order for when you click the view details link on the gridview it passes you off to another page that shows that applicants details it is within the same applicant.vb class
I am trying to update using the following method on the .aspx page but i receive the following error "No parameterless constructor defined for this object."
Memberdetails.aspx
Without knowing which line of code is causing that error, I can't say for sure, however, my guess is that your error is on this line of code.
_applicantadapter = New applicantTableAdapter
Put an open parentheses after applicantTableAdapter to see the different constructor signatures available to you for that type. I bet you'll see none of the options allow no parameters.
That error means that the object type you are trying to instantiate requires that you include parameter(s) (and you are not).

Cannot bind to list<T>.property or list<T>.item.property in details section of Telerik report

I have created a Telerik report and I am setting the datasource on runtime to an object with some properties and a List. I am using the properties in the page and report header sections and i want to use the list as the details. Now the problem is binding to the List's item properties in the details section. I have played around with the expression builder and it seems that i should access the properties like this :
[=Fields.myList.Item.myProperty]
when i run the program i get a nice big red rectangle with the following error :
An error has occured while processing TextBox 'textBox28':Common Language Runtime detected an invalid program.
I have tried to change different variants of expression which also gives me other errors
[=Fields.myList.myPropery]
An error has occured while processing TextBox 'textBox28': The expression contains object 'myProperty' that is not defined in the current context.
The closest i have gotton was with the object it self, which outputs the object.toString()
[=Fields.myList]
I found a working solution although not what i was looking for, I created my own class with properties and made a List. I then retrieved the data from the db did the changes i wanted to do in the class and set the datasource of the report to the list. This is working quite well.
I struggled with this error:
An error has occured while processing TextBox 'textBox28': The expression contains object 'myProperty' that is not defined in the current context.
The solution I came up with was to make my model object inherit from List. For example:
public class MyReportModel : List<MyEntityDto> {
}
The look of the report wizard makes it seem like this isn't necessary, but I found no other way around this error.
This is for Telerik Reporting Q3 2013.

ServerControl randomly null

I got a master page with a server control in it. Randomly the server control is inaccessible from codebehind. This doesn't happen on a specific action (eg a Button click or so). Currently I have no clue what this could be. I don't think it's output caching since this is not explcitly activated and the error happens far to seldom for that. But I'm going to disable caching in the master page explicitly with next deployment.
Anyone an idea how to find more info to find what's happening? Or has someone had a similar error?
The control is defined in markup. The accompaning codebehind is:
PGFMainNavi.HasAccessToFunction = HasAccessToNaviItem;
// HasAccessToNavi is a local function
Exception is:
System.NullReferenceException: Object reference not set to an instance
of an object
Thanks.
sa
I have similar errors when I cache my controls - and I always check if their null, or if they are the correct types.
I think that your control is cached somewhere.
Use this code, to check that is not cached.
if(PGFMainNavi != null)
{
PGFMainNavi.HasAccessToFunction = HasAccessToNaviItem;
}
or find where you set the case on this control and remove it.
Second Solution
Some times after an online update I get this error, because compiler did fail to read correct all involving files - probably some user read the page the same time I copy the files or something.
To avoid that I always use the app_offline.htm before make my updates.

Good error handling practice

What is a good error handling practice for an asp.net site? Examples? Thanks!
As with any .net project I find the best way is to only catch specific error types if they are may to happen on the given page.
For example you could catch Format Exceptions for a users given input (just incase JavaScript validation fails and you have not use tryparse) but always leave the catching of the top level Exception to the global error handler.
try
{
//Code that could error here
}
catch (FormatException ex)
{
//Code to tell user of their error
//all other errors will be handled
//by the global error handler
}
You can use the open source elmah (Error Logging Modules and Handlers) for ASP.Net to do this top level/global error catching for you if you want.
Using elmah it can create a log of errors that is viewable though a simple to configure web interface. You can also filter different types of errors and have custom error pages of your own for different error types.
One practice that I find to be especially useful is to create a generic error page, and then set your defaultRedirect on the customErrors node of the web.config to that error page.
Then setup your global.asax for logging all unhandled exceptions and then put them (the unhandled exceptions) in a static property on some class (I have a class called ErrorUtil with a static LastError property). Your error page can then look at this property to determine what to display to the user.
More details here: http://www.codeproject.com/KB/aspnet/JcGlobalErrorHandling.aspx
Well, that's pretty wide open, which is completely cool. I'll refer you to a word .doc you can download from Dot Net Spider, which is actually the basis for my small company's code standard. The standard includes some very useful error handling tips.
One such example for exceptions (I don't recall if this is original to the document or if we added it to the doc):
Never do a “catch exception and do nothing.” If you hide an exception, you will never know if the exception happened. You should always try to avoid exceptions by checking all the error conditions programmatically.
Example of what not to do:
try
{
...
}
catch{}
Very naughty unless you have a good reason for it.
You should make sure that you can catch most of the errors that are generated by your application and display a friendly message to the users. But of course you cannot catch all the errors for that you can use web.config and defaultRedirect by another user. Another very handy tool to log the errors is ELMAH. ELMAH will log all the errors generated by your application and show it to you in a very readable way. Plugging ELMAH in your application is as simple as adding few lines of code in web.config file and attaching the assembly. You should definitely give ELMAH a try it will literally save you hours and hours of pain.
http://code.google.com/p/elmah/
Code defensively within each page for exceptions that you expect could happen and deal with them appropriately, so not to disrupt the user every time an exception occurs.
Log all exceptions, with a reference.
Provide a generic error page, for any unhandled exceptions, which provides a reference to use for support (support can identify details from logs). Don't display the actual exception, as most users will not understand it but is a potential security risk as it exposes information about your system (potentially passwords etc).
Don't catch all exceptions and do nothing with them (as in the above answer). There is almost never a good reason to do this, occasionally you may want to catch a specific exception and not do any deliberately but this should be used wisely.
It is not always a good idea to redirect the user to a standard error page. If a user is working on a form, they may not want to be redirected away from the form they are working on. I put all code that could cause an exception inside a try/catch block, and inside the catch block I spit out an alert message alerting the user that an error has occurred as well as log the exception in a database including form input, query string, etc. I am developing an internal site, however, so most users just call me if they are having a problem. For a public site, you may wish to use something like elmah.
public string BookLesson(Customer_Info oCustomerInfo, CustLessonBook_Info oCustLessonBookInfo)
{
string authenticationID = string.Empty;
int customerID = 0;
string message = string.Empty;
DA_Customer oDACustomer = new DA_Customer();
using (TransactionScope scope = new TransactionScope())
{
if (oDACustomer.ValidateCustomerLoginName(oCustomerInfo.CustId, oCustomerInfo.CustLoginName) == "Y")
{
// if a new student
if (oCustomerInfo.CustId == 0)
{
oCustomerInfo.CustPassword = General.GeneratePassword(6, 8);
oCustomerInfo.CustPassword = new DA_InternalUser().GetPassword(oCustomerInfo.CustPassword, false);
authenticationID = oDACustomer.Register(oCustomerInfo, ref customerID);
oCustLessonBookInfo.CustId = customerID;
}
else // if existing student
{
oCustomerInfo.UpdatedByCustomer = "Y";
authenticationID = oDACustomer.CustomerUpdateProfile(oCustomerInfo);
}
message = authenticationID;
// insert lesson booking details
new DA_Lesson().BookLesson(oCustLessonBookInfo);
}
else
{
message = "login exists";
}
scope.Complete();
return message;
}
}

Resources