Why DisplayUsers(); doesn't work?
My base page is:
public class adminPage : System.Web.UI.Page
{
protected override void OnLoad(EventArgs e)
{
if (User.Identity.IsAuthenticated == false) { Response.Redirect("~/Account/login.aspx?ReturnUrl=/admin"); };
if (!(User.IsInRole("admin") || User.IsInRole("super user"))) { Response.Redirect("/"); };
}
}
my class is
public partial class users : adminPage
{
protected void Page_Load(object sender, EventArgs e)
{
string sName;
adminGeneralData.GetToolData(2, out sName);
pageH1.Text = sName;
DisplayUsers();
}
protected void DisplayUsers()
{
DataSet ds = userData.GetUsersData();
userList.DataSource = ds;
userList.DataBind();
}
}
but DisplayUsers() doesn't work,
If I recall correctly, you'll need to call the base class's OnLoad event to register the Page_Load event properly:
protected override void OnLoad(EventArgs e)
{
if (User.Identity.IsAuthenticated == false) { Response.Redirect("~/Account/login.aspx?ReturnUrl=/admin"); };
if (!(User.IsInRole("admin") || User.IsInRole("super user"))) { Response.Redirect("/"); };
base.OnLoad(e);
}
Here are a couple of good reads:
OnLoad vs. Page_Load vs. Load event
When creating a web control should you override OnLoad or implement Page_Load
According to Performance Tips and Tricks in .NET Applications:
Avoid the Autoeventwireup Feature
Instead of relying on autoeventwireup, override the events from Page. For example, instead of writing a Page_Load() method, try overloading the public void OnLoad() method. This allows the run time from having to do a CreateDelegate() for every page.
In the code executed, there is no difference, but
AutoEventWireup should be enabled (usually in markup) for each page
Page_Load (and other events like this) uses automatic events subscription mechanism, which uses Reflection, what slightly hits performance
I personally recommend to override OnLoad(), just don't forget to call base.
Related
I have a composite control like:
class MyControl : CompositeControl {
private Control _control1;
private Control _control2;
public bool RenderControl2 { get; set; }
/* Constructor to initialize controls*/
protected override void CreateChildControls(){
if(RenderControl2){
Controls.Add(_control2);
}else{
Controls.Add(_control1);
}
}
}
This works fine in scenarios where the value of RenderControl2 is set during Page_Init().
protected void Page_Init(object sender, EventArgs e){
if (!Page.IsPostBack){
myControl.RenderControl2 = MyMagicFucntion();
}
/* Works also when in Postback, but not required since the control keeps it state and only need to change state in the scenario below.*/
}
However, now we would like to set the value as a result of an event
protected void otherDropDow_SelectedIndexChanged(object sender, EventArgs e) {
myControl.RenderControl2 = otherDropDown.SelectedValue == "My Magic String";
}
This does not work since the control already executed CreateChildControls by the time the event fired. (Well, it does work during the next postback... :( )
I have tried to move the logic to the OnDataBinding event of the control. But this seems to have no impact on how the control actually show on the page.
/* DOES NOT RESOLVE THE ISSUE */
protected override void OnDataBinding(EventArgs e){
base.OnDataBinding(e);
/* _renderControl2HasChanged is set when RenderControl2 changes value
*/
if(_renderControl2HasChanged)
if(RenderControl2){
Controls.Remove(_control1);
Controls.Add(_control2);
}else{
Controls.Remove(_control2);
Controls.Add(_control1);
}
}
Instead of making the decision which control to display in CreateChildControls, you could evaluate the flag in OnPreRender and only change the visibility of the child controls, e.g.:
protected override void CreateChildControls()
{
Controls.Add(_control1);
Controls.Add(_control2);
}
protected override void OnPreRender(EventArgs e)
{
_control1.Visible = !RenderControl2;
_control2.Visible = RenderControl2;
}
In addition, you should save the value of RenderControl2 in the control state as described there. This way it will be persisted across postbacks.
I am pretty new to .NET - I am making a site that has an admin section that should only be visible to logged in users.
I have created the login code and once a user is authenticated, I then assign them a session variable.
My question is : is there a more efficient way to check the session variable rather than having the following function on each page?
protected void Page_Load(object sender, EventArgs e)
{
checkSession();
}
public void checkSession()
{
if (Session["LoggedIn"] != "true")
{
Response.Redirect("default.aspx");
}
}
thanks kindly!
if you are using a MasterPage you can put the checking code in the MasterPage's Page_Load event if not use either the Global.asax or a custom HttpModule and put the cheking code inside the the AcquireRequestState event handler for the first and the PostRequestHandlerExecute event handler for the second
Exmaple with Global.asax
public class Global : System.Web.HttpApplication
{ ...
void Application_AcquireRequestState(object sender, EventArgs e)
{
HttpContext context = HttpContext.Current;
// CheckSession() inlined
if (context.Session["LoggedIn"] != "true")
{
context.Response.Redirect("default.aspx");
}
}
...
}
You should probably consider using forms authentication:
http://www.asp.net/web-forms/videos/authentication/using-basic-forms-authentication-in-aspnet
You can configure a page, or folder to always require authorization, so the runtime will take care of that requirement rather than you having to check manually.
You could make your page a class that inherits from a base class that checks for logged in users.
Derive your pages from a custom class that derives from Page
override the Load method by adding your session check code
now all your pages have the validation
public class MyPage : System.Web.UI.Page
protected void Page_Load(object sender, EventArgs e)
{
if (Session["yoursession"] != "true")
{
//code
}
}
public class yourCustomPage1 : MyPage
{
protected void Page_Load(object sender, EventArgs e)
{
//you don't have to check or call any method..
}
}
public class yourCustomPage2 : MyPage
{
protected void Page_Load(object sender, EventArgs e)
{
//you don't have to check or call any method..
}
}
etc...
A good way to start to understand forms authentication in ASP.Net is creating a brand new website.
Go in Visual Studio and create New Project, select Web, then ASP.NET Web Application.
Check it out in Account folder to understand the process and ASP.Net methods.
You can create BasePage and inherit all your page from this base page , set the function in your basepage.
public class BasePage : Page
{
protected void checkSession()
{
if (Session["LoggedIn"] != "true")
{
Response.Redirect("default.aspx");
}
}
}
Your Page
public partial class YourPage : BasePage
{
....
}
Another solution :
In your Http Module, create Principal(Roles) and Identity in order to set authentification and authorization functionnalities, in your http module attach theses informations to current thread.
link : http://msdn.microsoft.com/en-us/library/system.security.principal.iidentity.isauthenticated.aspx
public class BasePage : Page
{
protected void checkSession()
{
if (Session["LoggedIn"] == null)
{
Response.Redirect("~/default.aspx/");
}
}
}
1st Way : Global.asax.cs ADD
void Application_AcquireRequestState(object sender, EventArgs e)
{
HttpContext context = HttpContext.Current;
Page page = context.Handler as Page;
if ((string)context.Session["LoggedIn"] != "true"
&& !(page.AppRelativeVirtualPath == "~/Default.aspx"))
context.Response.Redirect("default.aspx");
}
2nd Way : You can have the same session management in Master page. Page Load event.
Hope this helps.
You can add this code in the GLOBAL.asax.cs this will check if the session is empty and also it will not redirect if this the request is initialized from the Login page otherwise it will stuck in a loop.
void Application_AcquireRequestState(object sender, EventArgs e)
{
HttpContext context = HttpContext.Current;
// CheckSession() inlined
if (Context.Request.Url.LocalPath != "/UIComponents/User/Login.aspx")
{
if (context.Session["Name"] == null)
{
FormsAuthentication.RedirectToLoginPage();
}
}
}
I have a custom class creating a dropdownlist control as below:
public class IHGridView : System.Web.UI.WebControls.WebControl
{
private string _dataSource = "not set yet";
public string DataSource
{
get { return _dataSource; }
set { _dataSource = value; }
}
}
EDIT:
protected override void OnInit(EventArgs e)
{
// VIewState is alive. When I select an option and submit, after postback it's selected value is the one I selected.
this.Controls.Add(_dropDownList);
}
or
protected override void CreateChildControls()
{
// VIewState is dead. When I select an option and submit, after postback it's selected value is the default one.
this.Controls.Add(_dropDownList);
}
So, now I come up with the result that I have to add control in "OnInit" void.
But, this "OnInit" is the first void that this class writes.
If I want to use a property like "DataSource" before, "OnInit" void...
How would I do that?
EDIT:
protected void Button1_Click(object sender, EventArgs e)
{
IHGridViewTest2.DataSource = "fired";
}
DataSource is set when the button in aspx page is fired.
why would you want to add _dropDownList twice? once in the OnInit should be enough, and OnInit is where it should be added if you want it in the control collection - thus having viewstate persisted and restored.
to access and bind _dropDownList for example, override the DataBind method - at which point all the properties will be available to you.
protected override void DataBind(){
base.DataBind();
_dropDownList.DataSource = this.DataSource;
_dropDownList.DataBind();
}
this is pseudo code, and has not been tested or validated
EDIT:
Call overriden DataBind method
protected void Button1_Click(object sender, EventArgs e)
{
IHGridViewTest2.DataSource = "fired";
IHGridViewTest2.DataBind();
}
I have created a composite control with sample details as follows. Basically, the first time on page load the control sets a view state variable and the problem is that on post back (when the button is clicked), the ViewState variable is null. I have researched extensively and I am not able to find a solution. I checked all the Microsoft recommended articles and also from other developers. This approach seem to work for everyone and I can't figure out what I'm doing wrong. If anyone can help, I would really appreciate it.
PS: This code may not work as it is only for illustrative purposes. but this is exactly what i'm doing in my code.
Public class Test : CompositeControl
{
private Button btnTest = new Button();
public string TestViewState
{
get
{
string s = (string)ViewState["test"];
return (s == null) ? String.Empty : s;
}
set
{
ViewState["test"] = value;
}
}
private void set()
{
TestViewState = "test";
}
protected void Page_Load(object sender, EventArgs e)
{
if(!Page.IsPostBack)
set();
}
protected override void RecreateChildControls()
{
EnsureChildControls();
}
protected override void CreateChildControls()
{
base.Controls.Clear();
btnTest.ID = "btnTest";
btnTest.Click += new EventHandler(btnSubmitTest_Click);
if (!ChildControlsCreated)
Controls.Add(btnTest);
base.CreateChildControls();
}
protected override void Render(HtmlTextWriter writer)
{
btnSumbit.Render(writer);
}
protected void btnSubmitTest_Click(object sender, EventArgs e)
{
string test = TestViewState; // Viewstate value is null here!!!!!!
}
}
Are you sure that Page_Load is getting called? As far as I can remember that "notation" works only on pages and User Controls (didn't check that). Try overriding:
protected override void OnLoad(EventArgs e)
{
...
}
Test it with a Debugger.
Ok, the enableviewstate was disabled at the web.config level by another team member. Glad I found it. Thanks Arthur for confirming it worked for you.
I am creating a dynamic button in a custom class, outside of the .aspx codebehind. The custom class creates a Table object and generates a column of Buttons within that table. Once generated, the Table is loaded into a placeholder control. Everything is functioning well except for this problem:
How do I programmatically assign a Button Object a 'Click' event within the custom class?
MyButton.Click += new EventHandler(MyButtonClick);
This results in: 'The name 'MyButtonClick' does not exist in the current context' error.
I know it doesn't exist in the current context, but once the aspx page is rendered, the codebehind will include a method to handle 'MyButtonClick'. I don't know how store a Click event method name into a Button object from a custom class and pass it off to the aspx codebehind to be rendered.
You have to define an event in your custom control. Fire that event on button click so that your .aspx can handle it.
EDIT: Same principles apply to a custom class.
Control Code-Behind:
public delegate void ButtonEventHandler();
public event ButtonEventHandler ButtonEvent;
protected void Button1_Click(object sender, EventArgs e)
{
ButtonEvent();
}
.ASPX Code Behind:
protected override void OnInit(System.EventArgs e)
{
control1.ButtonEvent+=
new Control1.ButtonEventHandler (whatever_ButtonEvent);
}
protected void whatever_ButtonEvent()
{
//do something
}
Let's take this concept and apply it to a user control that has a textbox and two buttons. The user control is placed within a Gridview. When my code runs the method in my event handler method is always null. I think has to do w/the fact the a button is is in a user control which is in the gridview.
Here is my user control code.
public partial class User_Controls_GridViewFilter : System.Web.UI.UserControl
{
public event EventHandler UserControlButtonClicked;
protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
renderPage();
}
}
private void OnUserControlButtonClick()
{
if (UserControlButtonClicked != null)
{
UserControlButtonClicked();
}
}
protected void btnSearch_Click(object sender, EventArgs e)
{
OnUserControlButtonClick();
}
protected void btnReset_Click(object sender, EventArgs e)
{
OnUserControlButtonClick();
}
}
I register the control on the aspx page.
((User_Controls_GridViewFilter)gvMapLayer.HeaderRow.FindControl("FilterBox1")).UserControlButtonClicked
+= new ButtonEventHandler(User_Controls_GridViewFilter_UserControlButtonClicked);