I came across a pretty weird issue. Some of my Web User Controls are causing the parent page which references it to get 404 page not found error.
Here is how I register it on the .aspx page:
<%# Register TagPrefix="uc" TagName="DonationList"
Src="~/Controls/Donation/DonationList.ascx" %>
And the line where the user control is declared on the same aspx page:
<uc:DonationList ID="seenDonationListUC" runat="server" SeenInformation="Seen" />
If I remove the above line, I don't get a 404 error page anymore.
This is a small snippet of the user control class:
public partial class DonationList : System.Web.UI.UserControl
{
public enum Seen
{
Unspecified = 0,
Seen = 1,
NotSeen = 2
}
public Seen SeenInformation
{
get
{
int temp = seenInformationHF.Value == "" ? 0 : Convert.ToInt32(seenInformationHF.Value);
result = (Seen) temp;
return result;
}
.....
Any idea on the possible causes of this?
Name of your enum and subsequent enum value both are same "Seen". Try changing the enum name to something like SeenOptions. For example,
public enum SeenOptions
{
Unspecified = 0,
Seen = 1,
NotSeen = 2
}
In this case your SeenInformation class will look like,
public SeenOptions SeenInformation
{
get
{
int temp = seenInformationHF.Value == "" ? 0 : Convert.ToInt32(seenInformationHF.Value);
result = (Seen) temp;
}
.....
And finally, your user control line on aspx page will be same as before.
<uc:DonationList ID="seenDonationListUC" runat="server" SeenInformation="Seen" />
I hope this will fix your problem.
Related
i have the next question:
I've got an .aspx which contains a lot of web controls, this is the one i care:
//line 5
<%# Register src="Controls/UCAttachments.ascx" tagname="UCAttachments" tagprefix="uc1" %>
//line 430
<uc1:UCAttachments ID="UCAttachments" runat="server" Visible="false" />
On the selected index changed event of a combo box, i need to call a function of the web control, this is the code of the .aspx.cs.
private void cbo_SelectedIndexChanged( object sender, EventArgs e )
{
if(this.op == 1){
UCAttachments.visible=true;
UCAttachments.loadById(this.id); <-this doesnt work.
//Even tho, i can access all the other functions of UCAttachments.
//More infor abkout the error:
//'CONTROL' does not contain a definition for 'loadById'and no accessible //method accepting first argument...
}
}
public partial class Controls_UCAttachments: System.Web.UI.UserControl
{
//lots of functions
public void loadById( string id )
{
string query = "SELECT * FROM table WHERE ID = " +id;
//more code
return ;
}
}
you have to make this method static
public partial class Controls_UCAttachments
{
//lots of functions
static public void loadById(string id)
{
string query = "SELECT * FROM table WHERE ID = " + id;
//more code
return;
}
}
and you can call using this syntax
Controls_UCAttachments.loadById(this.id);
so.. very curious thing.
when you have a form which contains a lot of user controls, you need to wait for the metadata file to reload the new methods you've created.
So i closed my visual studio and re opeened a minutes later and the bug desapeared.
in my web site i need to check permission on every page,
i found my self repeating the same code every page.
this is one of my pages
public partial class KitView : AmsBasePage
{
protected void Page_Load(object sender, EventArgs e)
{
IddUser user = new IddUser();
user = (IddUser)Session["user"];
bool isAdmin = user.roles.Where(IddRole => IddRole.R_ID.Equals(3)).First().IsInRole;
bool isIddTeam = user.roles.Where(IddRole => IddRole.R_ID.Equals(2)).First().IsInRole;
bool isProductionTeam = user.roles.Where(IddRole => IddRole.R_ID.Equals(1)).First().IsInRole;
if (isAdmin)
{
hypAddComponent.Visible = true;
hypAddComponent.NavigateUrl = "AddComponent.aspx?CKID=" + Request.QueryString["CKID"];
}
}
}
how is the best practice to have the roles: isAdmin,isIddTeam,isProductionTeam
in every page but not repeating the code below in every page code
IddUser user = new IddUser();
user = (IddUser)Session["user"];
bool isAdmin = user.roles.Where(IddRole => IddRole.R_ID.Equals(3)).First().IsInRole;
bool isIddTeam = user.roles.Where(IddRole => IddRole.R_ID.Equals(2)).First().IsInRole;
bool isProductionTeam = user.roles.Where(IddRole => IddRole.R_ID.Equals(1)).First().IsInRole;
You should put your authorization code in your Master Page (ASP.NET Web Form) or Layout Page (ASP.NET MVC). That way, your authorization logic will only be placed in one location and runs on every page.
If you want to avoid redundant codes, i would suggest to write your authorization logic in a sepearte class or you can even write the aurthorization logic in a MasterPage if you have any. Then inherit them in your webforms.
Note: in your webforms you will have to override your page_load event so that the authorization from your inherited base class runs first.
if you want to avoid repeating authorization code, you should do it at a central location.
there can be many ways for that, but I can suggest you few
Use Master Page - and write the authorization code in Master Page's OnLoad
Create a HttpModule - Insert your own Module in the ASP.NET Page Events PipeLine and handle all the authorization and authentication logic
Now this is what I did in a multi-million $ Project
Create a PageBase.cs being inherited from System.Web.UI.Page - which you are already doing
Create a constructor of the PageBase, in which you can pass current Page permissions i.e.
public void PageBase(AppActivityEnum PageView, AppActivityEnum PageEdit, AppActivityEnum PageDelete)
{
this.pageView = PageView;
this.pageEdit=PageEdit;
this.PageDelete=PageDelete;
VerifyPermission();
}
where VerifyPermission() is:
public void VerifyPermission()
{
var currentUser= SessionHelper.GetCurrentUser();
var permissions = Utility.GetUserPermissions(currentUser.RoleId);
this.CanView=permissions.Contains((int)this.pageView);
this.CanEdit=permissions.Contains((int)this.pageEdit);
this.CanDelete=permissions.Contains((int)this.pageDelete);
}
now these three variables i.e. CanView, CanEdit, CanDelete are public properties in PageBase, hence available to all your pages(wherever you have inherited).
and you can set your controls(add button, delete button), page visibility based on these variables.
so basically, you create an Activity Table for storing ref of each of the Pages. where Activity table looks like
Id
Name
Value
Parent
a typical entry in this table is like:
1 Module-Master MMaster NULL
2 Module-Master-View MMasterView 1
3 Module-Master-Edit MMasterEdit 1
4 Module-Master-Delete MMasterDelete 1
and you maintain RoleAppActivtyMapping (obviously):
Id RoleId AppActivityId
1 1 2
1 1 3
1 1 4
so RoleId one has all the three permissions.
so GetUserPermissions(RoleId) basically gets all the RoleAppActivityMapping entries corresponding to passed Role.
so on every page you call the PageBase' constructor to verify the view permissions. You pass the current Page's AppActivity Id in the constructor.
and if CanView is false: you redirect to "UnAuthorized" page upon hitting the url.
I added in my AmsBasePage class that all pages inherit from .
this code
private bool _isAdmin;
private bool _isIddTeam;
private bool _isProductionTeam;
protected bool isAdmin
{
get { return _isAdmin; }
set { _isAdmin = value; }
}
protected bool isIddTeam
{
get { return _isIddTeam; }
set { _isIddTeam = value; }
}
protected bool isProductionTeam
{
get { return _isProductionTeam; }
set { _isProductionTeam = value; }
}
check your authorization in the master page. That way, I will be checked once and repeatation can be avoided.
I have a search textbox situated on a masterpage like so:
<asp:TextBox ID="frmSearch" runat="server" CssClass="searchbox"></asp:TextBox>
<asp:LinkButton ID="searchGo" PostBackUrl="search.aspx" runat="server">GO</asp:LinkButton>
The code behind for the search page has the following to pick up the textbox value (snippet):
if (PreviousPage != null && PreviousPage.IsCrossPagePostBack)
{
Page previousPage = PreviousPage;
TextBox tbSearch = (TextBox)PreviousPage.Master.FindControl("frmSearch");
searchValue.Text = tbSearch.Text;
//more code here...
}
All works great. BUT not if you enter a value whilst actually on search.aspx, which obviously isn't a previous page. How can I get round this dead end I've put myself in?
If you use the #MasterType in the page directive, then you will have a strongly-typed master page, meaning you can access exposed properties, controls, et cetera, without the need the do lookups:
<%# MasterType VirtualPath="MasterSourceType.master" %>
searchValue.Text = PreviousPage.Master.frmSearch.Text;
EDIT: In order to help stretch your imagination a little, consider an extremely simple property exposed by the master page:
public string SearchQuery
{
get { return frmSearch.Text; }
set { frmSearch.Text = value; }
}
Then, through no stroke of ingenuity whatsoever, it can be seen that we can access it like so:
searchValue.Text = PreviousPage.Master.SearchQuery;
Or,
PreviousPage.Master.SearchQuery = "a query";
Here is a solution (but I guess its old now):
{
if (PreviousPage == null)
{
TextBox tbSearch = (TextBox)Master.FindControl("txtSearch");
searchValue.Value = tbSearch.Text;
}
else
{
TextBox tbSearch = (TextBox)PreviousPage.Master.FindControl("txtSearch");
searchValue.Value = tbSearch.Text;
}
}
I have in many places in my ASP.NET project used the Session variable for storing data. I usually write something like this:
public uint MyPropery
{
get
{
object o = Session["MyProperty"];
if (o != null)
return (uint)o;
else
return 0;
}
set
{
Session["MyProperty"] = value;
}
}
However, this time I get a NullReferenceException in the setter. As far as I know, it is valid to assign the Session variable in the manner above. Also, Session is not null and neither is value.
Any ideas on this?
Edit:
Adding the code for the UserControl in which the property exists. I am using ext.net but that shouldn't have anything to do with this. One thought that crossed my mind:
The UserControl (seen below) is added dynamically in code-behind of a page. Can that have anything to do with it?
I am adding UserControls like this (on a Page):
foreach(CoreCommons.System.Comment c in cg.Reply_Comments)
{
WebApplicationExtNetTest.Secure.UserControls.CoreComment cc = new UserControls.CoreComment();
cc._Comment = c; // here is where i get the NullRef
this.Panel1.ContentControls.Add(cc);
}
Markup:
<%# Control Language="C#" AutoEventWireup="true" CodeBehind="CoreComment.ascx.cs" Inherits="WebApplicationExtNetTest.Secure.UserControls.CoreComment" %>
<%# Register Assembly="Ext.Net" Namespace="Ext.Net" TagPrefix="ext" %>
<ext:Panel runat="server" ID="CoreCommentOuterPanel" BodyStyle="background: #FFFDDE">
<Items>
<ext:ColumnLayout runat="server">
<Columns>
<ext:LayoutColumn ColumnWidth="0.8">
<ext:Image runat="server" ImageUrl="/Resources/bullet_triangle_green_16x16.png" Align="AbsMiddle"></ext:Image>
<ext:Label runat="server" ID="lblCommentInfo"></ext:Label>
</ext:LayoutColumn>
<ext:LayoutColumn ColumnWidth="0.2"><ext:Button runat="server" ID="btnDelete" Icon="Delete"></ext:Button></ext:LayoutColumn>
</Columns>
</ext:ColumnLayout>
<ext:Label runat="server" ID="lblComment"></ext:Label>
</Items>
</ext:Panel>
Code-behind:
namespace WebApplicationExtNetTest.Secure.UserControls
{
public partial class CoreComment : System.Web.UI.UserControl
{
public CoreCommons.System.Comment _Comment
{
get
{
object o = Session["CoreComment_ObjectId"];
if (o != null)
return (tWorks.Core.CoreCommons.System.Comment)o;
else
return null;
}
set
{
Session["CoreComment_ObjectId"] = value;
SetComment();
}
}
protected void Page_Load(object sender, EventArgs e)
{
}
private void SetComment()
{
if (_Comment == null)
{
lblCommentInfo.Text = "";
lblComment.Text = "";
}
else
{
lblCommentInfo.Text = _Comment.Author + ", " + _Comment.TimeStamp.ToString("g");
lblComment.Text = _Comment.Text;
}
}
}
}
I'm almost completely sure the NullReferenceException is thrown in SetComment() because none of the CoreComment's child controls (lblComment, lblCommentInfo) are properly instantiated at the point you set the _Comment property.
The reason these child controls are not instantiated is indeed the way you currently add the CoreComment controls. For dynamically adding UserControls, you must use Page.LoadControl() (see: here) to create a new instance of the control, as it does some behind-the-scenes magic to ensure it is properly initialized, which includes the instantiation of the child controls.
On a sidenote, personally I'd change SetComment() to SetComment(CoreCommons.System.Comment comment) and use the parameter instead of repeatedly calling the getter, or, if staying with the original, at least call the getter only once and store the result in a local variable. With what I assume is probably InProc session storage it won't make much of a difference, but in any other storage mode you'd repeatedly deserialize the Comment object for no reason.
You need to use the Page.LoadControl() method instead , please look here
BTW:the problem is in adding the control programatically with that way.
Use:
return Session["MyProperty"] as uint? ?? 0;
and post somewhere full exception stack trace with inner exception(s)
I have a simple ASP.NET Web User Control. It looks like this:
<%# Control Language="C#" AutoEventWireup="true"
CodeBehind="NewsArticle.ascx.cs"
Inherits="Website.Controls.NewsArticle" %>
<div>
<asp:Literal ID="ltlBody" runat="server" />
</div>
My code behind looks like this:
namespace Website.Controls
{
public partial class NewsArticle : System.Web.UI.UserControl
{
public String bodyText
{
//get { return ltlBody.Text; }
set { ltlBody.Text = value; }
}
}
}
On a .aspx page I have <asp:Panel ID="pNews" runat="server" />
In the code behind I have:
foreach (vwNews news in newsQuery)
{
NewsArticle article = new NewsArticle();
article.bodyText = news.Body;
pNews.Controls.Add(article);
}
Every time I run this code the newsQuery is populated correctly and I get to the line
aticle.bodyText = news.Body; and then I received the error article.bodyText threw an exception of type 'System.NullReferenceException'
I am not sure what is causing this error message or how to fix it. I would think that there should not be an issue. I tried creating a constructor for my Web User Control so that it would give default values to my properties but that didn't work. Any idea how to make this work? It doesn't seem like it should be that
To load a control programatically you need to use the Page.LoadControl() method. See this MSDN article
You have a typo within the code you've written. 'aticle' instead of 'article'.