We are using asp .Net with C#. I have page(.aspx) consist of multiple Web User Controls(.ascx)
I would like to have an error handling machanism in such a way that if there is any exception in one of the user control, asp .net should show some friendly error message on a control. All other control should render as expected.
Is there any way this can be done without putting place holder on each control which you show/hide in case of exception?
You could do something like this.
An abstract base class with an abstract OnLoad() that each UserControl has to implement. You can use this same model for any event that you want to have shared error handling.
public abstract class BaseUserControl : UserControl
{
protected void Page_Load(object sender, EventArgs e)
{
try
{
OnLoad();
}
catch (Exception)
{
//Custom error handling here
}
}
protected abstract void OnLoad();
}
public class MyUserControl: BaseUserControl
{
protected override void OnLoad()
{
//My normal load event handling here
}
}
1) In app_code, create a class MyPage.cs that inherits Page
class MyPage : Page { }
2) Change the inherits of your pages to MyPage.
public partial class _Default : MyPage { ...
There's an attribute in the web.config you can use to change it if you want
3) Back to MyPage.cs, add the generic error handler of all pages
protected override void OnError(EventArgs e)
{
/* here you can intercept the error and show the controls that you want */
base.OnError(e);
}
First create a base user controlclass which overrides default onerror event.
public class MyControlClass:UserControl
{
protected override void OnError(EventArgs e)
{
//here you sould add your friendly msg implementation
//base.OnError(e); here should remain commented
}
}
Then you can create your user controls:
public class Control1:MyControlClass
{
// ....
// ....
}
So, if any control creates an exception , the rest will keep on working.
Related
i need to prevent UserControl Page_Load event in case the control placed inside PlaceHolder that Visible property set to false.
I have some base class that all my user control derived from, and this class derived from UserControl class.
I found this : How to stop the execution of UC at page load on Visible false
The answer was to use "this.Visible" inside the Page_Load event handler
Or to override OnPreRender method and use it instead of the Page_Load.
I need some way to solve this problem inside my BaseControl,
in order to avoid multiple code changes.
Is it possible?
Thanks in advance!
Finally i found a solution:
public abstract class BaseClass : UserControl
{
protected override void OnLoad(EventArgs e)
{
if (this.Visible)
{
base.OnLoad(e);
}
}
}
public partial class WebUserControl1 : BaseClass
{
protected void Page_Load(object sender, EventArgs e)
{
// running only if this.Visible = true
}
}
There is nothing you can do to circumvent the execution of Page_Load. This event will be raised regardless because it is part of the page life cycle. What you can do however, is to conditionally execute any heavy logic based on this.Visible.
If you want to check visibility of a child control from a base class, and then conditionally handle additional shared logic there (whatever that may be), you can do something like this:
// DerivedChildControlA.ascx
<uc1:ChildControl runat="server" ID="someChildControlID" />
public abstract class BaseControl : UserControl
{
protected abstract ChildControl DerivedChild { get; }
}
public class DerivedChildControlA : BaseControl
{
protected override ChildControl DerivedChild
{
get { return this.someChildControlID; }
}
}
Once you obtain the reference to that child, you can check its visibility and perform desired actions in the base class.
For example, what I normally do for all my UserControls is put the main loading logic in a separate method called Load(). Then I call this method from the parent. The thing is, you can conditionally call Load() which gives you more control. In your instance, you can call Load() from the parent base class depending on the child control's visibility.
EDIT:
There may be a way by removing the child control from the page's child control collection, but this feels like a hack. For additional info check out the comment by Aterra on ASP.NET Forums.
You could load the User Controls dynamically. Then you won't have the problem of them being loaded even though they are not visible. So on the aspx page you can do this:
if (showControl == true)
{
//create an instance of the user control
WebUserControl1 control1 = (WebUserControl1)LoadControl("~/WebUserControl1.ascx");
//add it to the page when needed
PlaceHolder1.Controls.Add(control1);
}
The only downside is that the Control will be gone after each PostBack, so you will have to keep track if the Control was shown somewhere and recreate it if needed.
Another thing you can do is leave the Page_Load of the User Control empty and create a Method that you call from the parent page.
User Control
protected void Page_Load(object sender, EventArgs e)
{
//empty
}
public void doStuffInUserControl()
{
Label1.Text = "Called from parent!";
}
Parent aspx page
protected void Page_Load(object sender, EventArgs e)
{
someChildControlID.doStuffInUserControl();
}
I have an issue with overriding a method. I have created a base class with custom code that I want to run during the OnLoad event. The code in this overridden method applies to 90% of the pages that inherit from it, but on a few pages I need to override the override. My issue is that I still need to run the System.Web.UI.Page's OnLoad implementation. If I include the base.OnLoad(e) line in the second class (see below), it calls the BasePageEdit's logic, but if I remove it, the Page_Load event is never called. How can I skip over the logic in BaseEditPage's, and still get the functionality from System.Web.UI.Page?
public class BasePageEdit : System.Web.UI.Page
{
protected override void OnLoad(EventArgs e)
{
// I need this to raise the Page_Load Event!
base.OnLoad(e); // Calls System.Web.UI.Page OnLoad Event which I want.
// Logic that I want to run in ADDITION to base Implementation;
}
// Other classes and methods;
}
public class WebPageThatNeedsSpecialOnLoadImplementation : BasePageEdit
{
protected override void OnLoad(EventArgs e)
{
// I need this to raise the Page_Load Event!
base.OnLoad(e); // If I include this, it runs the BasePageEdit, I don't want that...
// But I still need to run the System.Web.UI.Page onLoad event or Page_Load will not be called.
// Logic that I want to run INSTEAD of the logic from the override from BasePageEdit.
}
}
Thank you very much Slaks! I am editing my question to show how I implemented so that others viewing this post can implement the same way if they choose!
public class BasePageEdit : System.Web.UI.Page
{
protected override void OnLoad(EventArgs e)
{
BasePage_OnLoad(e);
// Logic that I want to run in ADDITION to base Implementation;
}
protected virtual void BasePage_OnLoad(EventArgs e)
{
base.OnLoad(e);
}
// Other classes and methods;
}
public class WebPageThatNeedsSpecialOnLoadImplementation : BasePageEdit
{
protected override void OnLoad(EventArgs e)
{
BasePage_OnLoad(e);
// Logic that I want to run INSTEAD of the logic from the override from BasePageEdit.
}
}
You can't do that.
However, you can make a new method in BasePageEdit which just calls its base.OnLoad, and call that directly from the derived class instead.
I have a problem validating the user of the page in ASP.Net my plan is using Attribute per page but it seams the constructor of the class is called first before the attribute. Is there a way to do this using Attribute?
i tried something like this
public class BaseAuthenticate : Attribute
{
public BaseAuthenticate(string pageID)
{
// condition if current user is allowed in pageID,
// throws exception if not allowed
}
}
[BaseAuthenticate("03902020-BC73-4DC0-A000-D4E20409FA2C")]
public partial class Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
// will not reach here if not validated in BaseAuthenticate
}
}
any help would be appreciated.
TIA
Change your constructor such that it calls the superconstructor -
public BaseAuthenticate(string pageID) : base() {
//blah blah blah
// Egyptian braces >>>
}
That should execute the base constructor. Obviously, whatever the superclass needs as an argument will have to be put in base().
I have been battling this for some time and I need some guidance.
I'm coding in ASP.NET 4.0 WEBFORMS.
Question is: How to expose a textbox, Label or any other control to another class.
I have a webform (see below).
public partial class WebForm1 : System.Web.UI.Page
{
}
This is then referenced and sent to another class.
public class SearchInitializer
{
private WebForm1 _webform1;
public SearchInitializer(WebForm1 Webform1)
{
_webform1 = Webform1;
}
public void ChewSettings()
{
_webform1 //can't find any control in here?!
}
}
First I thought of creating a public property which I thought I could access from the reference I sent to the new class.. But nooo!
public partial class WebForm1 : System.Web.UI.Page
{
public string KeywordBox1
{
get {return txt_keyword.Text;}
set {txt_keyword.Text = value;}
}
}
The I tried to inherit the Webform into the other class. Making the the property available but no luck there.
public class SearchInitializer : Webform1
{
private WebForm1 _webform1;
public SearchInitializer(WebForm1 Webform1)
{
_webform1 = Webform1;
}
public void ChewSettings()
{
_webform1 //can't find any control in here?!
}
}
Okay an abstract class migth be of use here, inheriting everything. But I think I got that wrong to. I have events and static classes, so they can talk with the page. But I really would like not to use a static class as a container to save all the info in my controls.
So these are the examples I have tried and they all failed. So this is me basicly trying to expand what I know ;) Thanks for reading!!
Why have they failed and how should I do it?
EDIT AS REQUESTED!
public partial class WebForm1 : System.Web.UI.Page
{
protected void btn_click(object sender, EventArgs e)
{
SearchInitializer searchIni = new SearchInitializer(this);
}
}
To expose the controls there are two methods I can think of that you can employ.
You can remove the following statement from the myPage.designer.cs file and place it in your code behind as a public declaration:
protected global::System.Web.UI.WebControls.TextBox myTextBox;
becomes
public System.Web.UI.WebControls.TextBox myTextBox;
This should make it immediately accessible. My preferred method is to add a property for each specific control that you want to provide access to.
public System.Web.UI.WebControls.TextBox MyTextBoxElement
{
get
{
return myTextBox;
}
}
This allows to provide supplementary access controls if you need them or other conditionals. In any case, to access either the field or the property, the consuming object must reference this by your specific page type.
Not sure what you are trying to do, but to access a base class within an inherited calss you need to use the base keyword, not declare an instance there of.
public partial class WebForm1 : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
}
public string KeywordBox1
{
get { return txt_keyword.Text; }
set { txt_keyword.Text = value; }
}
}
public class SearchInitializer : WebForm1
{
public SearchInitializer()
{
}
public void ChewSettings()
{
// Works
base.KeywordBox1 = "Red";
}
}
If intellisense is not showing the property, try rebuilding the solution. It will then refresh the list of available properties and it should show.
Your original approach must work. I suggest you create a small test project with a form with text box and SearchInitializer class and see that it works, after that figure out what is different in your current project.
I have added an EventHandler for the Click-event to a picturebox but on runtime this handler is never called (the debugger shows me that it is added to the control directly but when I click on the picturebox nothing happens).
I assume it has something to do with my inheritance. I have a usercontrol called AbstractPage (its not really abstract since the designer doesnt like that) which only consists of a heading and this picturebox but it provides quite some functions the actual pages rely on.
#region Constructor
public AbstractPage()
{
InitializeComponent();
lblHeading.Text = PageName;
picLock.Click += new EventHandler(picLock_Click);
}
#endregion
#region Events
void picLock_Click(object sender, EventArgs e)
{
...do some stuff
}
#endregion
The page implementations just inherit this class and add their controls and behavior. We recently figured out that subclassing UserControl is not performant and we lose some performance there, but its the best way to do it (I dont want to c&p function for 25 pages and maintain them).
My pageA looks like this
public partial class PageA : AbstractPage
{
#region Constructor
public PageA()
{
// I dont call the base explicitely since it is the
// standard constructor and this always calls the base
InitializeComponent();
}
#endregion
public override string PageName
{
get { return "A"; }
}
public override void BindData(BindingSource dataToBind)
{
...
}
Anyway, the picLock_Click is never called and I dont know why?
The pages are all put into a PageControl which consists of a TreeView and a TabContainer where the pages are put once I call addPage(IPage)
public partial class PageControl {
...
protected virtual void AddPages()
{
AddPage(new PageA());
AddPage(new PageD());
AddPage(new PageC());
...
}
protected void AddPage(IPage page)
{
put pagename to treeview and enable selection handling
add page to the tabcontainer
}
Thanks in advance
If I understand your problem correctly, this worked for me out of the box (using VS2k8). My code:
public partial class BaseUserControl : UserControl
{
public BaseUserControl()
{
InitializeComponent(); //event hooked here
}
private void showMsgBox_Click(object sender, EventArgs e)
{
MessageBox.Show("Button clicked");
}
}
public partial class TestUserControl : BaseUserControl
{
public TestUserControl()
{
InitializeComponent();
}
}
I moved the TestUserControl to a form, clicked the button and got the message box as expected. Can you paste some more code, e.g. how do you use your AbstractPage?
I found the problem. We are using the Infragistics WinForms but in that case I used the standard picturebox. I replaced it with the UltraPictureBox and now it works.