WCF Service Reference in ASP.net Page - When to Dispose? - asp.net

I have an ASP.net page that is creating a service reference to a WCF service and making calls in multiple places in my page. I instantiate the service reference in Page_Load and have an instance variable to store it:
private FooClient _serviceClient;
protected void Page_Load(object sender, EventArgs e)
{
_serviceClient = nwe FooClient();
_serviceClient.GetAllFoos();
}
protected void btnSave_Click(object sender, EventArgs e)
{
_serviceClient.SaveFoo();
}
I just discovered that I need to be disposing of the service reference when I am done using it or else the connections will be kept alive and will block incoming connections if I reach the max number of connections. Where would the best place to dispose of these references be? I was thinking of doing it on the OnUnLoad event.
Is there a better way of doing this?

Personally, I would open FooClient when I need it, so not in Page_Load but in the methods that do web service calls. This way, you know exactly what happens to it. I usually take the following approach:
var client = OpenClient();
try
{
// Perform operation(s) on client.
}
finally
{
CloseClient(client);
}
This way you are sure you close your proxy, whatever happens (if there are exceptions you need to catch, simply add a catch clause). The CloseClient method should look like the one in PaulStack's answer.
Another benefit you get when you do this is that multiple calls don't interfere with eachother. Suppose one of you web service calls leads to an unexpected exception. The client channel is now in a faulted state and therefore unusable for any other calls.
And third, suppose an exception does occur that you can not catch or do not want to catch, I'm not sure Page_Unload is actually called (and I don't know what page method will be called in that event). This will also leave connections open.

according to MSDN documentation and personal experience do something as follows:
try
{
...
client.Close();
}
catch (CommunicationException e)
{
...
client.Abort();
}
catch (TimeoutException e)
{
...
client.Abort();
}
catch (Exception e)
{
...
client.Abort();
throw;
}
this would allow the correct closing or abortion of the service when necessary rather than leaving them to be disposed at a predefined time - only keep the connection open as long as you definately have to. personally i dont like inheriting from IDisposable as its very heavy in performance

Related

Context is null in the global.asax file

I have global.asax file, and I use this two functions to update cache value every 15 seconds by this code:
protected void Application_Start(object sender,EventArgs e)
{
Context.Cache.Insert("value","some value",null,DateTime.Now.AddSeconds(15),Cache.NoSlidingExpiration,CacheItemProirirt.Default,new CacheItemRemovedCallback(updating));
}
private void updating(string key,object value,CacheItemRemoveReason reason)
{
Context.Cache.Insert("value","updated value",null,DateTime.Now.AddSeconds(15),Cache.NoSlidingExpiration,CacheItemProirirt.Default,new CacheItemRemovedCallback(updating));
}
but it give me an NullReferenceException, and the context is null, please why I can't use context at the "updating" function?
Application_Start doesn't have any context.
The first event that does is Begin_Request.
Application_Start occurs when the particular website gets fired up for the first time, or after been recycled.
To keep the cache item renewed I suggest you do that in the Begin_Request, where you check if it's there, and if not, initiate it again.
This way it's only use memory while the site is being hit, otherwise not.

Page_Load is finished, keep the thread alive?

I do a test in Page_Load function in asp.net
protected void Page_Load(object sender, EventArgs e)
{
Task.Factory.StartNew(() =>
{
while (true)
{
Response.Write("Hi");
Thread.Sleep(100);
}
});
Thread.Sleep(2000);
Response.Write("hello");
}
I found the fact is that the task will be killed when the pageload function is finished.
Is that true? Or the task is still alive?
If I want the task is still alive, how can I do?
Using the Response object on multiple threads is not safe. Also, after a request has ended using the Response is not going to be successful. Let's assume that you had properly locked it:
The task is not killed because ASP.NET does not even know that task exists. How could it? You never give a reference to that task to ASP.NET. Probably, you haven't really looked at the error message you get. That task probably had an exception.
Don't use ASP.NET objects in an unsafe way if you want that task to continue to run.

Response.Redirect() ThreadAbortException Bubbling Too High Intermittently

I understand (now) that Response.Redirect() and Response.End() throw a ThreadAbortException as an expensive way of killing the current processing thread to emulate the behaviour of ASP Classic's Response.End() and Response.Redirect methods.
However.
It seems intermittently in our application that the exception bubbles too high. For example, we have a page that is called from client side javascript to return a small string to display in a page.
protected void Page_Load(object sender, EventArgs e)
{
// Work out some stuff.
Response.Write(stuff);
Response.End();
}
This generally works, but sometimes, we get the exception bubbling up to the UI layer and get part of the exception text displayed in the page.
Similarly, else where we have:
// check the login is still valid:
if(!loggedin) {
Response.Redirect("login.aspx");
}
In some cases, the user is redirected to login.aspx, in others, the user gets an ASP.NET error page and stack dump (because of how our dev servers are configured).
i.e. in some cases, response.redirect throws an exception all the way up INSTEAD of doing a redirect. Why? How do we stop this?
Have you tried overloading the default Redirect method and not ending the response?
if(!loggedin) {
Response.Redirect("login.aspx", false);
}
You can use the following best-practice code instead, as explained by this answer to prevent the exception from happening in the first place:
Response.Redirect(url, false);
Context.ApplicationInstance.CompleteRequest();
Since I was looking for an answer to this question too, I am posting what seams to me a complete solution, rounding up the two above answers:
public static void Redirect(this TemplateControl control, bool ignoreIfInvisible = true)
{
Page page = control.Page;
if (!ignoreIfInvisible || page.Visible)
{
// Sets the page for redirect, but does not abort.
page.Response.Redirect(url, false);
// Causes ASP.NET to bypass all events and filtering in the HTTP pipeline
// chain of execution and directly execute the EndRequest event.
HttpContext.Current.ApplicationInstance.CompleteRequest();
// By setting this to false, we flag that a redirect is set,
// and to not render the page contents.
page.Visible = false;
}
}
Source:
http://www.codeproject.com/Tips/561490/ASP-NET-Response-Redirect-without-ThreadAbortExcep

How do I crash the App Pool?

Our ASP.NET 2 web application handles exceptions very elegantly. We catch exceptions in Global ASAX in Application_Error. From there we log the exception and we show a friendly message to the user.
However, this morning we deployed the latest version of our site. It ran ok for half an hour, but then the App Pool crashed. The site did not come back up until we restored the previous release.
How can I make the app pool crash and skip the normal exception handler? I'm trying to replicate this problem, but with no luck so far.
Update: we found the solution. One of our pages was screenscraping another page. But the URL was configured incorrectly and the page ended up screenscraping itself infinitely, thus causing a stack overflow exception.
The most common error that I have see and "pool crash" is the loop call.
public string sMyText
{
get {return sMyText;}
set {sMyText = value;}
}
Just call the sMyText...
In order to do this, all you need to do is throw any exception (without handling it of course) from outside the context of a request.
For instance, some exception raised on another thread should do it:
protected void Page_Load(object sender, EventArgs e)
{
// Create a thread to throw an exception
var thread = new Thread(() => { throw new ArgumentException(); });
// Start the thread to throw the exception
thread.Start();
// Wait a short while to give the thread time to start and throw
Thread.Sleep(50);
}
More information can be found here in the MS Knowledge Base
Aristos' answer is good. I've also seen it done with a stupid override in the Page life cycle too when someone change the overriden method from OnInit to OnLoad without changing the base call so it recursed round in cirlces through the life cycle: i.e.
protected override void OnLoad(EventArgs e)
{
//some other most likely rubbish code
base.OnInit(e);
}
You could try throwing a ThreadAbortException.

exception (ab)use in web development

I find myself using exception in web development even for conditions that are not really errors, let alone exceptional ones - just logic decisions, validations...
in a web page, I often write code like so:
try
{
int id;
if(!int.TryParse(txtID.Text, out id))
throw new Exception("ID must be an integer");
if(IdAlreadyExists(id))
throw new Exception("ID already exists in database");
//and so on...
}
catch(Exception ex)
{
SetErrorLine(ex.Message);
}
I was wondering if this is really the correct way of using exceptions and enforcing Business Logic in web development.
P.S.: I am using asp.net, and obviously I could use ASP.NET validators for some of these and also seperate UI from logic, but I'm trying to make a point on the general idea.
You've just answered your own question, really.
Exceptions are for exceptional circumstances. Assuming the code you posted is from a page that takes "ID" as input from the user, then it's not exceptional for user input to be bad. Use the validation infrastructure for that, or do it manually, but don't use exceptions for that.
Also, don't get into the habit of displaying Exception.Message to users. It is meant for developers to see to know what went wrong and how to fix it.
I wouldn't consider the first example to be an acceptable use of an Exception. A user could easily screw up entering that information, and user input should be validated anyways.
An exception should be 'exceptional'. Something that you don't expect to happen, shouldn't happen or really don't want to happen. Anything that can be validated or handled before needing to throw an exception should just be treated like an error.
Different communities differ in their acceptable use of exceptions. The Python community is a little bit more liberal with their use of exceptions: http://wiki.sheep.art.pl/Ask%20for%20Forgiveness
I'm a fan of using them as long as it doesn't disrupt the logic of your application.
Just wanted to add that for asp.net adding a global exception handler HttpModule to catch unhandled exceptions is a very clean way to train yourself out of try/catch/finally abuse.
Throw exceptions when the assumptions your methods take on are broken, or if a method simply cannot complete.
In your example, your IdAlreadyExists method might query a database. That method will assume that there is a database to connect to, you have enough memory to do what you need, and so on. If an assumption is broken, throw an exception.
I, for one, like to let lower level code throw exceptions, and higher level code catch exceptions. That's not a hard and fast rule, just a general guideline I like to follow. It's typically not necessary to throw exceptions to the same level, but I could imagine that it would make sense at times.
still missing the way it SHOULD be done
Set an error mesage and return.
Log error and dont display it to user.
protected void Button1_Click(object sender, EventArgs e)
{
try
{
int id = 0;
if(!int.TryParse(txtID.Text, out id))
{
SetErrorLine("Thats not a valid number dude! Need to go to school again");
return;
}
if(IdAlreadyExists(id))
{
SetErrorLine("I already have this entry in store. Sorry. Call again!");
return;
}
...the rest of your code
}
catch(Exception ex)
{
_log.Error(ex);
SetErrorLine("Something unexpected happened dear user ... ");
}
}
Edit: your comment
try {
string error = "";
int id = 10;
if(BO.DoSomething(out error, id, otherParams))
{
SetErrorLine(error);
return;
}
}
catch(Exception ex)
{
//log
}
My guess:
try {
string meaningfullErrorMessage= "";
int id = 10;
if(!BO.DoSomething(out meaningfullErrorMessage, id, otherParams))
{
SetErrorLine(meaningfullErrorMessage);
return;
}
}
catch(Exception ex)
{
//log
}

Resources