How to run a custom System.Attribute over an ashx file - c#

Normally, on a usual aspx file, I can use System.Attribute at the begining of the page, like:
[AuthorizePage()]
public partial class _Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
}
}
public class AuthorizePage : System.Attribute
{
public AuthorizePage()
{
//do some stuff to authorize
}
}
And before the page initializes the Attribute's constructor runs and do some stuff to ensure a person is currently logged in, otherwise the attribute constructor Redirects user to a login page.
I wanted to do the same on a HttpHandler (ashx file), but the attribute never initializes when on a ashx page.
[AuthorizePage()]
public class AjaxHandler : MuCustomClassBase, IHttpHandler, IReadOnlySessionState
{
//The interface implementations and some other custom private methods
}
I do an AJAX Call to this ashx page. Could this be the reason why the Attribute doesn't run? Or any other things I must know?
Eventually, I would be extremely happy to know How to run a Custom System.Attribute over an ashx file?

Assuming you are using ASP.Net authentication, you can just add the .ashx to the list of protected pages in web.config and IIS/ASP.Net will take care of the rest:
<location path="AjaxRequests.ashx">
<system.web>
<authorization>
<allow users="?" />
</authorization>
</system.web>
</location>
If you are using a self-built authentication scheme, you could override OnProcessRequest and perform the necessary authentication in that method, redirecting as needed.

Attributes don't do anything by themselves. You can pile 10 random attributes on a class and nothing will really happen. Attributes just provide metadata about the class/method/property.
There should be a piece of code that looks at the metadata and act on it. Since you seem to be using custom AuthorizePageAttribute such piece of code either don't run for handlers or does not expect class that is not derived from Page to have such attribute.
To fix an issue you need to find what handles you custom attribute and fix it. You may need to add similar code to your handlers directly.
The fact that your code in constructor of attribute does something useful for a page class on every request to that page sounds suspicious - I'd expect such attributes to be created once per type instance. Relying on non-trivial code in constructor of an attribute to run per-instance of the class seems dangerous to my.

Well first of all yes you are reinventing the ActionFilterAttribute in Asp.Net MVC. But, I have to ask if you really need to use attribute? I suggest you to use inheritance model. Let me simply explain; you might have a SecurePage : Page class that implements the security operations. You may then pass the security code that is related to the derived page.
And if you insist on using attributes, you should intersect the handler mechanism by writing a base factory handler that routes to the needed handler. This handler should behave like a mediator object.

Related

Asp.net 4.5 Custom Attribute Webform

Using a Asp.Net old project, to access webforms I need to create a custom class Attribute that reads users rights like 'Rights.ViewDashboard' or 'Rights.CanEdit' an so. The class code is:
[AttributeUsage(AttributeTargets.Class, AllowMultiple = true)]
public class AuthorizationAttribute : Attribute
{
public AuthorizationAttribute(Rights permission)
{
if (Security.IsAuthorizedTo(permission))
return;
HttpContext.Current.Server.TransferRequest("~", false);
}
}
In the aspx webform I have:
[Authorization(Rights.ViewDashboard)]
public partial class DashboardRisorse : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
}
}
When the user calls the webform if he haven't specific right the page is not loaded and site is redirected to the default page. But if he make a refresh of the page the code isn't execute, attribute is ignored and the page is loaded. When debugging I see that this attribute is executed only once.
Where is my fault?
I don't need Net Core solution because the project has old assemblies.
Thanks.
Ingd
I am assuming here that you are trying to define custom attribute similar to ActionFilter Attributes in MVC. Unfortunately ASP.Net does not work in the same way.
You have two options
Create an HttpModule and use one of the events available to build your logic
Write the logic you want to execute in Page Load. Use Page.IsPostBack to identify if it is initial load of the page or if the page is being posted back. Write the logic you need within the if.. else if conditions
In case my assumption was incorrect then please provide more details on your query specifically what is it that you are trying to achieve using the Attribute.

How to use MVC custom attribute on aspx.cs page?

My application is in Asp.net MVC 4. I'm using .aspx page for opening of report. I've implemented custom user rights attribute on all action of application. I want to use it on my .aspx.cs page class or every function that is in .aspx.cs page. How to use it? can i use MVC custom attribute in aspx page
In mvc I'm using like this
[AuthorizeUserControls("urlInventoryReport")]
public ActionResult Inventory(string ReportTitle)
{
}
How to use in .aspx.cs page
public partial class ReportViewer : System.Web.UI.Page
{
[AuthorizeUserControls("urlInventoryReport")] //it's not working
private void ViewInventoryReport()
{
}
}
Attributes are static objects that apply metadata to a type in .NET. They contain no behavior.
The reason why your attribute works in ASP.NET MVC is because MVC has a filter which runs before and after the call to the action method is performed. This filter is called by the MVC framework, which in turn is called by the route handler (a specialized HTTP handler).
The fact that the behavior is defined in the same class as the attribute (yielding an ActionFilterAttribute) is just for convenience. You could just as well separate the attribute from the action filter as is done in this answer.
Following the MVC approach to make your IActionFilter function, would be to use .NET routing for your page and make a specialized IRouteHandler that can scan your page object after it is instantiated using Reflection to determine if the attribute exists, and then execute the behavior in the associated IActionFilter. I suggest if you go this route, you analyze the MVC source code and extract the bits that you need, but it is not for the faint of heart.
Alternatively, you could put the scanning implementation into the Page_Init event, but at that point you might just be better off not bothering with declaring the attribute statically and just executing the behavior locally.
Assuming your attribute derives from ActionFilterAttribute, you could do something like:
protected void Page_Init(object sender, EventArgs e)
{
var attribute = new AuthorizeUserControls("urlInventoryReport");
var filterContext = CreateFakeActionExecutingContext(); // TODO: Implement this.
attribute.OnActionExecuting(filterContext);
}

Custom AuthorizeAttribute not called

There are a lot of similar questions out there but this has me stumped.
If I used [Authorize] I get prompted for a username and password but if I use [InternalAuthorizeV2] I don't
I have a custom AuthorizeAttribute that for the moment does not do any anything special (I'm limiting things that could be wrong).
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, Inherited = true, AllowMultiple = false)]
public class InternalAuthorizeV2Attribute: AuthorizeAttribute
{}
and a Action in my Controller
[InternalAuthorizeV2(Roles = "MobileApps_Parkingggg")]
public ActionResult Index()
{
var model = new VmParking();
return View(model);
}
The login is handled in a different app but they have identical web config lines
<machineKey compatibilityMode="Framework20SP2" validationKey="editedOut" decryptionKey="editedOut" validation="SHA1" decryption="AES"/>
<authentication mode="Forms">
<forms name="emLogin" loginUrl="/Login/Index" timeout="540" protection="All" path="/" enableCrossAppRedirects="true" cookieless="UseCookies" />
</authentication>
<sessionState timeout="540" />
I know that if I login by going to a page with [Authorize] then back to my trouble page I can see the username but it doesn't seem to be calling my customer attribute.
New information:
My attribute is in a shared DLL as it's used by many apps. It seems that if I copy the cs file to the web project it works. No idea why, still looking for hints or tips.
From what you've said, it all behaves fine if you use [Authorize] but not [InternalAuthorizeV2].
Your shared dll shouldn't make any difference if it is set up correctly; I have the same thing working. Make sure the web project is using the latest version of the dll and you have the right assembly references in the shared dll - System.Web.Mvc, v4.0.0.0 in my project.
You say its used by many apps? Do all apps have the same problem with the shared dll or just one of them? If it's just one, check the references for the one with the problem.
If the below tests all work then the final option is that whatever you are doing in your authorize attribute in the dll isn't picking up the right context for that app, or using the right membership provider or database - you haven't included the code you are using inside your attribute so it's hard to know if that could be causing a problem.
Test dependencies
You could try adding a base authorize attribute to your shared dll, and then implementing another authorize attribute in your web project that inherits the base attribute you just created. This should show that you have your shared dll set up correctly.
// in the dll:
public class BaseAuthorizeAttribute : System.Web.Mvc.AuthorizeAttribute { ... }
// in the web project:
public class InternalAuthorizeV2Attribute : BaseAuthorizeAttribute { ... }
If simply moving it from your dll project to the web project fixes it, the most likely issue is the web project is not using the right version of the dll (try cleaning and doing a complete rebuild) or your dll is referencing the wrong dlls for the System.Web.Mvc.AuthorizeAttribute. You say you have triple checked, but trying the above debugging should help you work out if this really is the case.
Debug authorization method calls
If that doesn't work then try adding the following override methods to a very simple attribute, and seeing if you hit the breakpoint on the call to base.OnAuthorization. If you don't, then it may not be the actual attributes causing your problem.
[AttributeUsageAttribute(AttributeTargets.Class|AttributeTargets.Method,
Inherited = true, AllowMultiple = true)]
public class InternalAuthorizeV2Attribute : System.Web.Mvc.AuthorizeAttribute {
protected override bool AuthorizeCore(System.Web.HttpContextBase httpContext) {
return false; // breakpoint here, and this should force an authorization failure
}
public override void OnAuthorization(System.Web.Mvc.AuthorizationContext filterContext)
{
base.OnAuthorization(filterContext); // breakpoint here
}
}
This should completely prevent any user access to the Action. If that doesn't work then you know the issue doesn't lie in your attribute, but that your attribute is not being applied.
You can also add the following to your controller and check that it is hit before the authorize attribute:
protected override void OnAuthorization(AuthorizationContext filterContext) {
base.OnAuthorization(filterContext);
}
Authorization chaining
Note that you have your attribute attached to the Action method, so it will only be hit if a an authorization attribute earlier in the chain (e.g. a global filter or controller attribute) hasn't already prevented the user being authorized (see my answer here), or prematurely returns an ActionResult that stops the chain reaching your Action attribute. However it's unlikely this is the problem if simply moving it from the dll to the project makes it work. Similarly it's unlikely you have an AllowAnonymous in the wrong place from what you've said.

Use Attribute In Asp.net

I have something issue on how to use Attribute in asp.net page class.
The below code slice is the background:
A method is declared like below in a aspx class page:
[SomeAttribute(Name=”Test”,TargetType=typeof(System.Int32)]
Public void Verify(object obj)
{
//code to verify…
}
And other pages would use the attribute too.
Now I want a Module to do is that it will invoke a method before the Verify method is calling.
Currently, my solution is using a customer IHttpModule implement class to do it by registering the BeginRequest event.
In the method referred to the event, how can I get the method that is calling currently by request in asp.net ? This is the way I could know the request is calling Verify method so that I can do something with the Attribute on it.
I'd recommend checking out PostSharp:
http://www.sharpcrafters.com/
It's got all that goodness, and more, built in.

.Net Form POST

I've got a client that, during testing, is giving me conflicting information. I don't think they are lying but more confused. So, I would like to setup some simple auditing in my ASP.Net application. Specifically, right when any page is called, I want to immediately insert the Querystring and/or form POST data into a log table. Just the raw values.
Querystring is easy. But there doesn't seem to be a way to get the raw form POST'ed data without using BinaryRead, and if I do that, then I screw myself out of using the Request.Form collection later on.
Does anyone know a way around this?
EDIT: tvanfosson suggested Request.Params. I was looking for something that was easier to use (like Request.Querystring, only for POST), but I guess I could just as easily loop through all params and build a string of name=value&, etc).
You can create a custom HttpModule to capture all request made to your application so you don't need to touch every page and you can use it only during testing just not to slow down performance in production.
A sample implementation would be:
public class CustomModule : IHttpModule
{
public void Init(HttpApplication context)
{
context.EndRequest += new EventHandler(context_BeginRequest);
}
private void context_BeginRequest(object sender, EventArgs e)
{
HttpContext context = ((HttpApplication)sender).Context;
// you can use the context.Request here to send it to the database or a log file
}
}
You need to add the module to your web.config
<httpModules>
<add name="CustomModule" type="CustomModule"/>
</httpModules>
All of the form data should be in Request.Params. You'd need to do this on every page, though or maybe use an HttpModule.
[EDIT] If you want to get the form parameters separately use Request.Form, along with Request.QueryString
I would recommend implementing and HttpHandler or an HttpModule for this type of scenario. You can get to the POST Data from the Page_Load event but implementing this logging facility here is not as maintainable.

Categories

Resources