Execute attribute before class constructor - c#

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().

Related

Using local variable in aspx page

I am new to c#.
Is it possible to use a local variable (declared in Page_Load method inside System.Web.UI.Page class) in the .aspx page. or do i have to declare an accessor variable inside "UI.Page" class and use it as reference?
public partial class consoleTours : System.Web.UI.Page
{
public string AStr{ get; set; }// i could use this
}
protected void Page_Load(object sender, EventArgs e)
{
string LStr=""; <i>// i couldn't use this
}
Thank you for edit. as to c# i am also new to stackoverflow as you could see.
Point of my question is.I couldn't use public property (AStr) for tryParse.i first use local variable for parsing then assign LStr to AStr and use it in the page. so it makes me use 2 variables instead one. I thought there should be another way.
You have 2 valid options 1:
Use a public property on the page:
This is what you have done already:
public class MyPage : System.Web.UI.Page
{
public string MyPageTitle { get; set; }
}
Now, the property MyPageTitle can be accessed anywhere in your cs file, and can be used in your ASPX file aswell.
If you want to have a property which is accessible on multiple pages, you must play with inheritance:
Use inheritance to create a new Page object:
First, you create class that acts as a Page:
public class ParentPage : System.Web.UI.Page
{
public string MyPageTitle { get; set; }
}
Now, when you create a new page, your code will look by default like this:
public class MyPage : System.Web.UI.Page
{
}
Change the System.Web.UI.Page to your created ParentPage, so it will looks like the following:
public class MyPage : ParentPage
{
}
Now, in the 'MyPage' class, you will have access to the MyPageTitle property as well as on the aspx file.
Thus, your are exposing a variable to another control by using inheritance.
Declare the variable just inside the class and outside of a method
public string LStr="";
protected void Page_Load(object sender, EventArgs e)
{
LStr= "this new value";
}

AuthorizationAttribute IsAuthorized not called

I've created a custom attribute that derives from System.ComponentModel.DataAnnotations.AuthorizationAttribute and overrides the IsAuthorized method.
I've decorated my methods with the new attribute but the IsAuthorized method is never called. Can anyone explain why?
Here's my attribute declaration :
[AttributeUsage(AttributeTargets.All)]
public class AuthorisationAttribute : System.ComponentModel.DataAnnotations.AuthorizationAttribute
{
private bool IsAuthorised { get; set; }
public AuthorisationAttribute(bool isAuthorised)
{
IsAuthorised = isAuthorised;
}
protected override AuthorizationResult IsAuthorized(IPrincipal principal, AuthorizationContext authorizationContext)
{
return IsAuthorised ? AuthorizationResult.Allowed : new AuthorizationResult("You are not authorised for this activity");
}
}
and here is my usage :
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
[Authorisation(true)]
private void button1_Click(object sender, EventArgs e)
{
MessageBox.Show("Pass");
}
[Authorisation(false)]
private void button2_Click(object sender, EventArgs e)
{
MessageBox.Show("Shouldn't see this");
}
}
Thanks in advance.
With very few exceptions, attributes aren't injection points. They don't do anything at all by themself. They are just metadata (information about types / members). For them to be active, you need the calling framework to explicitly check for them (via reflection), and invoke any methods.
This is the case in some places; MVC uses attributes extensively, for example. But this is not the case for winform event-handlers and other arbitrary methods. So nothing happens.
Basically, you've done the equivalent of putting a sticky label with "do not enter" onto the door, but in a place that nobody can see by default (the top edge of the door, for example). It only does something if (both):
somebody looks for the label
people either electively obey the label, or you have an explicit door-person who checks the label against the people going in/out

ASP.NET expose controls to other class

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.

ASP .Net User control error handling

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.

Multiple inheritance in C# - again

I know that C# does not offer multiple inheritance. And I know there' are workarounds like this one for instance.
But here's a problem that I faced today, can't figure any ELEGANT workaround. I'll add some abstract code-sample so you get it quicker...
(let it be a real-life ASP.NET code - cause those "class A, class B" code-samples are really confusing):
public class AdminPage : System.Web.UI.Page
{
protected override void OnInit(EventArgs e)
{
//if not an admin - get out
if(!CurrentUserIsAdmin()) Response.End();
base.OnInit (e);
}
}
public class JQueryPage : System.Web.UI.Page
{
protected override void OnInit(EventArgs e)
{
RegisterJQueryScript();
base.OnLoad (e);
}
}
//now here's what I REALLY miss in C#
public class AdminJQueryPage : AdminPage, JQueryPage;
Compose out the functionality? This is better for Single Responsibility. You'd have to think carefully about your constructors.
interface IAdminPage {
public string AdminPageMethod();
}
interface IJQueryPage {
public string JQueryPageMethod();
}
internal class AdminPage : IAdminpage {
private string someString;
internal AdminPage(string value) {
this.someString = value;
}
public string AdminPageMethod() {
return "AdminPage result with some string: " + this.someString;
}
}
internal JQueryPage : IJQueryPage {
private int someNumber;
internal JQueryPage(int value) {
this.someNumber = value;
}
public string JQueryPageMethod() {
return "JQueryPage result with number: " + this.someNumber;
}
}
class AdminJQueryPage : IQueryPage, IAdminpage {
private readonly IAdminPage adminPage;
private readonly IJQueryPage jqueryPage;
public AdminJQueryPage(string someString, int someNumber) {
this.adminPage = new AdminPage(someString);
this.jqueryPage = new JQueryPage(someNumber);
}
public string AdminPageMethod() {
return this.adminPage.AdminPageMethod();
}
public string JQueryPageMethod() {
return this.adminPage.JQueryPageMethod();
}
}
If you really want multiple inheritance, look at Scala's traits
Edit: added passing of constructor values to composed out classes. Also made the classes internal (cannot be accessed or constructed outside the assembly) because they are only ever constructed by the AdminJQueryPage class, which is the 'public-facing' class.
I came from C++ too and dont miss it, especially since reading Refactoring [and using a non-OOTB tool for that].
You can use PostSharp to post process based on placing attributes on your AdminJQueryPage which would achieve the exact same effect.
Or you can Extract Method code into helper classes and call that (i.e., Joe's example)
Or you can put the helpers in a single base class and call from that.
Either way your code will be clearer.
It's only a matter of time before your mixins start overlapping, and then your general suite of techniques for managing that complexity needs to kick in - in C++, MI should only have been one tool in a suite - rather than a very sexy hammer.
its possible to fake a mixin by specifying a interface and creating extension methods for that interface. however I'm not use this will help overriding methods, only adding new ones. you are of course able to then call an extension method when overriding, but that is basically the same as extracting the methods to a helper class, but with a little more sugar
Even if it was possible, one problem with the semantics of an MI-based solution to the specific problem you raised is what happens on the markup side? The Render() method that generates the markup would run first in one class, and then in the other? That's probably not the behavior you want when both classes generate entire pages.
If you're open to solutions that are outside of the language itself, there are several elegant options in ASP.NET that will address the type of issue you raised (changing the actions taken during an event in the page life cycle). For example:
Page Adapters
Control Adapters
Custom user controls
HttpModules
Master Pages
Tag mapping
The best choice will of course depend on the details of your application. In case it's helpful, I cover those options in my book, including sample code: Ultra-Fast ASP.NET.
The simplest approach is to build a hierarchy - allow AdminPage to inherit from JQueryPage like so:
public class AdminPage : JQueryPage
{
protected override void OnInit(EventArgs e)
{
//if not an admin - get out
if(!CurrentUserIsAdmin()) Response.End();
base.OnInit (e);
}
}
public class JQueryPage : System.Web.UI.Page
{
protected override void OnLoad(EventArgs e)
{
RegisterJQueryScript();
base.OnLoad (e);
}
}
//now here's what I REALLY miss in C#
public class AdminJQueryPage : AdminPage
My guess is some of this awkwardness comes from the ASP.NET page model, which uses overridden base class methods.
You can to do this with Interfaces
public interface IJQueryPage
{
}
public abstract class AdminPage : System.Web.UI.Page
{
protected override void OnInit(EventArgs e)
{
//if not an admin - get out
if(!CurrentUserIsAdmin()) Response.End();
base.OnInit (e);
}
protected override void OnLoad(EventArgs e)
{
if (this is IJQueryPage)
{
RegisterJQueryScript();
}
base.OnLoad (e);
}
}
public class AdminJQueryPage : AdminPage, IJQueryPage
{
}

Categories