I have some ASP.NET page and webservice WebMethod() methods that I'd like to add some common code to. For example:
<WebMethod()> _
Public Function AddressLookup(ByVal zipCode As String) As Address
#If DEBUG Then
' Simulate a delay
System.Threading.Thread.Sleep(2000)
#End If
Return New Address()
End Function
I currently have the #If Debug code in all of my WebMethod() methods, but I am thinking there must be a better way to do this without having to actually type the code in.
Is there a way to determine if a request is to a WebMethod in Application_EndRequest so that I can add this delay project wide?
Note that some methods are Page methods and some are web service methods.
You can check the request URL in Application_EndRequest to determine whether it is a web method call. E.g. something like this (sorry it's in C#):
protected void Application_EndRequest(Object sender, EventArgs e)
{
if (Request.Url.ToString().IndexOf("MyWebService.asmx") > 0)
{
// Simulate a delay
System.Threading.Thread.Sleep(2000);
}
}
Encapsulate the #if DEBUG code in a method and mark it with <Conditional("DEBUG")>. This way, you just write a method call in each <WebMethod>. Might be useful.
Related
My Webforms application which is based on .Net 4.6 has to use the async/await-functionality quite extensively. Because I'm quite new to this async/await topic I read quite a lot of best practices like this or this. But I still have some questions for which I haven't found any clear informations.
Regarding Page-Lifecycle-Events: I know that e.g. for the Page_Load-Event it's best practice to avoid async void-methods and register such methods like this:
protected void Page_Load(object sender, EventArgs e)
{
PageAsyncTask pageAsyncTask = new PageAsyncTask(SomeAsyncMethod);
Page.RegisterAsyncTask(pageAsyncTask);
//Method to invoke the registered async-methods immedietly and not after the PreRender-Event
Page.ExecuteRegisteredAsyncTasks();
}
My problem is that I want to call the async-method as soon as I registered it and not after the OnPreRender-event. This should be achieved by calling the ExecuteRegisteredAsyncTasks()-method. But in my case this has no effect and the async-method is still invoked after the PreRender-event. But why?
Regarding Control-Events: Is it better to register async-methods the same way I mentioned in the code-example above or can I use the async-void signature like:
protected async void OnClick(object sender, EventArgs e)
{
await SomeAsyncMethod();
}
I found both examples but no clear informations which is the better solution and why.
Regarding Context and ConfigureAwait, it seems to be best practice to use await SomeAsyncMethod.ConfigureAwait(false) for a better performance and where the context is not important and not to use it where the context e.g. when manipulating GUI elements. But in my case it seems to make no difference if I call await SomeAsyncMethod.ConfigureAwait(false) in my click-event. I can still manipulate my GUI-elements wihtout any problems. The example which I uses was this:
private async void button1_Click(object sender, EventArgs e)
{
button1.Enabled = false;
try
{
await SomeAsyncMethod().ConfigureAwait(false);
}
finally
{
//Manipulating still works even it's another context
button1.Enabled = true;
}
}
So I wonder why the manipulating of the GUI-elements still work and if I really should use ConfigureAwait(false) on every async-method where the context is not important, which is quite tedious. I wonder if this has something to do with the usage of the Ajax-Functionality by Telerik which I use for my Webapplication. But this is just an assumption.
ASP.NET WebForms has it's own asynchronous execution engine. Please refer to the documentation.
In any case, you typically want (or need) to get back to the current synchronization context on methods such as event handlers, so you shouldn't call ConfigureAwait(false) inside button1_Click, but you should call it inside SomeAsyncMethod.
My simple method for Asp.net 4.5 webforms:
1) declare aspx page with this attribute
<%# Page ..... Async="true" ValidateRequest="false" EnableEventValidation="false" %>
2) Create this void method in code:
void MyAsyncMethod( ... list parameters )
{
//Insert this on end method code
var objThread = Session["MyAsyncMethod"] as Thread;
if (objThread != null) objThread.Abort();
}
3) Call method MyAsyncMethod:
var objThread = new Thread(
() => MyAsyncMethod(parameters..)) {IsBackground = true};
objThread.Start();
Session["MyAsyncMethod"] = objThread;
I have a UserControl(uc) in my master page, and a method(MyMethod) inside uc that make some calculations.
protected void Page_Load()
{
If(!IsPostBack)
MyMethod();
}
private void MyMethod()
{
SomeCalculations..
}
Because my uc is in master page, i can see the uc in all my aspx pages. My aim is that as soon as a user login the application, run MyMethod() just once (in a thread) and do calculations in an infinite loop until the user logout or application (or browser) closed. Although the calculations are outside of the PostBack, MyMethod will be called more than one time.
Assume that I m in Page-1 and it s loaded first time, MyMethod() will bi called. After another page (Page-2) is loaded, MyMethod will be called again and I want to prevent it. Is there a way to do something like this:
if(LifeCycle of application resumes)
{
MyMethod()
}
You can store a flag in application state and use it in a condition. Something like this, perhaps:
// in Application_Start in Global.asax
Application["IsRunning"] = false;
then:
private void MyMethod()
{
if (!((bool)Application["IsRunning"]))
{
Application["IsRunning"] = true;
// your code
}
}
Note that the state of a web application isn't always stable or intuitive. It's really meant to be a request/response system and is at the mercy of the web server for managing resources. This may not be as reliable as you expect.
You might want to consider having a separate application, such as a Windows Service, for performing ongoing background tasks.
There's an annoying quirk in the way Response.Redirect works: you almost always want to terminate excecution right away and jump to the new page:
If ThisIsTheWrongPage Then
Response.Redirect(sUrl, False)
End If
'this code should not execute
DoSomethingWithThisPage
But Response.Redirect doesn't end execution, it just keeps on going and executes the subsequent lines of code. This is causing a lot of havoc in a legacy app I'm maintaining. So you have to do this:
If ThisIsTheWrongPage Then
Response.Redirect(sUrl, False)
Return
End If
What I would like to do is implement a method like this:
Sub RedirectToUrl(sUrl As String)
'redirect to the specified url
HttpContext.Current.Response.Redirect(sUrl, False)
'return from the CALLING method
End Sub
And then I could write this:
If ThisIsTheWrongPage Then
RedirectToUrl(sUrl)
End If
And not have to worry about the missing Return statement. I know it's not hard to write that return statement, but there are about 1,000 of these in the code, and new ones being added, and I want a method that the developer can call and not have to be careful about that Return statement. It's a bug just waiting to happen.
I know there's no way to do this in traditional .NET code, but I was wondering if it could be implemented in IL, to pop the stack twice and jump to the calling method's return location.
This is not possible. You'd be breaking invariants of the calling method. It would be unpredictable what happens when you call a method that you didn't write.
Redirect has a parameter that can be set to make it throw a ThreadAbortException on the current thread. This is made exactly for your use case. It effectively aborts execution of the page.
The only way a method can change the return point of the method that invoked it is to throw an exception. Considering the way many web apps are written with exception handlers to keep pages from returning 500 errors to the user, it could be difficult to provide your desired behavior by throwing an exception.
One problem with instructing a caller to return is there would be no way to specify the return value of that method. Exceptions work around this by propagating the exception itself up the stack until a handler is found.
Have a look at this, it uses the jmp opcode,
maybe this fits your needs.
.assembly JumpTest{}
.module JumpTest.exe
.namespace Test{
.class public auto ansi JumpClass extends [mscorlib]System.Object {
.method public static void Main() cil managed{
.entrypoint
.maxstack 8
ldstr "start"
call void [mscorlib]System.Console::WriteLine(string)
ldstr ""
call void Test.JumpClass::Page(string)
ldstr "end"
call void [mscorlib]System.Console::WriteLine(string)
ret
}
.method public static void Page(string sUrl) cil managed{
ldc.i4.1 //always redirect in this test
brfalse.s target
jmp void Test.JumpClass::RedirectToUrl(string)
target:
ldstr "Page() stuff here"
call void [mscorlib]System.Console::WriteLine(string)
ret
}
.method public static void RedirectToUrl(string sUrl) cil managed{
ldstr "RedirectToUrl() stuff here"
call void [mscorlib]System.Console::WriteLine(string)
ret
}
}}
This article explains that the PreRequestHandlerExecute event does not fire for PageMethod calls for whatever reason. However, I'm trying to use that event to populate the Principal object with the user's permissions so they can be checked within any web request (PageMethod call or not). I'm caching the permissions in the Session, so I need an event that fires whenever a PageMethod is called, and I need to have access to the Session. This way I can populate the Principal object with the security permissions cached in the session, and User.IsInRole() calls will work as expected. What event can I use?
You should implement an authorization module that will be run with every request that goes up to the server. This way you are able to authorize your principal for any request that come up to the server (page request, method, etc.)
public class AuthorizationModule : IHttpModule, IRequiresSessionState
{
//not going to implement it fully, might not compile
public void Init( HttpApplication context )
{
//you'll prolly want to hook up to the acquire request state event, but read up to make sure this is the one you want on the msdn
context.AcquireRequestState += AuthorizeRequest;
}
public void AuthorizeRequest( HttpContextBase httpContext )
{
// do you work in here
// you can redirect them wherever if they don't have permssion, log them out, etc
}
}
}
After you've crated the module, you'll need to hook it up in the web.config. Your type should include the namespace if it has one.
<httpModules>
<add name="AuthorizationModule" type="AuthorizationModule"/>
</httpModules>
I hope this helps.
You can use the Application_OnPostAuthenticateRequest as shown below (assuming you are using Forms Authentication. Else, pls replace the code with your Authentication mechanism):
public void Application_OnPostAuthenticateRequest(object sender, EventArgs e)
{
IPrincipal usr = HttpContext.Current.User;
if (usr.Identity.IsAuthenticated && usr.Identity.AuthenticationType == "Forms")
{
var fIdent = (FormsIdentity)usr.Identity;
var ci = new CustomIdentity(fIdent.Ticket);
var p = new CustomPrincipal(ci);
HttpContext.Current.User = p;
Thread.CurrentPrincipal = p;
}
}
Page Methods are static, and bypass the normal Page lifecycle, its objects and its events. The best you can do is pass authentication information as parameters to the Page Method itself.
From my point of view, you can:
1.- Use a common method you can call from every page method server code that have access to Session variables. Please refer to:
http://mattberseth.com/blog/2007/06/aspnet_ajax_use_pagemethods_pr.html
2.- Try to capture a similar behaviour later using __doPostBack() function to run server code. See if this work for you to capture page method async posbacks:
http://www.dotnetcurry.com/ShowArticle.aspx?ID=256
Hope that helps,
I'm a first-time user of the AOP features of Unity 2.0 and would like some advice. My goal is to be able to log method calls in an ASPX page, like so:
public partial class Page2 : Page
{
protected void Page_Load(object sender, EventArgs e)
{
}
[Log]
private void Testing()
{
}
}
Here is the code for the LogAttribute:
public class LogAttribute : HandlerAttribute
{
public override ICallHandler CreateHandler(IUnityContainer container)
{
return new LogHandler(Order);
}
}
Now the LogHandler:
public class LogHandler : ICallHandler
{
public LogHandler(int order)
{
Order = order;
}
public IMethodReturn Invoke(IMethodInvocation input, GetNextHandlerDelegate getNext)
{
string className = input.MethodBase.DeclaringType.Name;
string methodName = input.MethodBase.Name;
string preMethodMessage = string.Format("{0}.{1}", className, methodName);
System.Diagnostics.Debug.WriteLine(preMethodMessage);
return getNext()(input, getNext);
}
public int Order { get; set; }
}
The problem I have is how to use the [Log] attribute. I've seen plenty of example of how to configure the interception settings, for example:
container.AddNewExtension<Interception>();
container.Configure<Interception>().SetDefaultInterceptorFor<ILogger>(new InterfaceInterceptor());
But this implies that I have an interface to intercept, which I don't. I have the ASPX page which uses the [Log] attribute.
so how can I configure Unity to make use of the [Log] attribute? I've done this before using PostSharp and would like to be able to use Unity to do the same.
Cheers.
Jas.
You're unfortunately not going to get this to work in an ASP.NET page with Unity interception.
Unity interception uses a runtime interception model. Depending on the interceptor you choose, you'll either get a subclass with virtual method overrides to call the call handlers (VirtualMethodInterceptor) or a separate proxy object (Interface or TransparentProxyInterceptor) which execute the call handlers and then forward to the real object.
Here's the issue - ASP.NET controls creation and calls to your page, and there's no easy way to hook into them. Without controlling the creation of the page object, you can't use the VirtualMethodInterceptor, because that requires that you instantiate a subclass. And you can't use the proxy version either, because you need ASP.NET to make calls through the proxy.
PostSharp gets around this because it's actually rewriting your IL at compile time.
Assuming you could hook into the creation of the page object, you'd have to use the VirtualMethodInterceptor here. It's a private method, so you want logging on "self" calls (calls from one method of the object into another method on the same object). The proxy-based interceptors can't see those, since the proxy is a separate instance.
I expect there is a hook somewhere to customize how ASP.NET creates object - BuildManager maybe? But I don't know enough about the details, and I expect it'll require some pretty serious hacking to get work.
So, how do you get around this? My recommendation (actually, I'd recommend this anyway) is to use the Model-View-Presenter pattern for your ASP.NET pages. Make the page object itself dumb. All it does is forward calls to a separate object, the Presenter. The Presenter is where your real logic is, and is independent of the details of ASP.NET. You get a huge gain in testability, and you can intercept calls on the presenter without all the difficulty that ASP.NET gives you.