We had a problem recently where one of the developers had changed a line of code from using HttpResponse.End to using HttpApplication.CompleteRequest when forcing a PDF to download in a similar fashion to the following:
https://stackoverflow.com/a/8590579/3856039
Doing so caused some PDF's to fail to download due to a non-breaking space issue so the code was changed back to using HttpResponse.End.
However, in helping my colleague I was carrying out some research and I came across the following question:
Is Response.End() considered harmful?
Which links to:
https://blogs.msdn.microsoft.com/aspnetue/2010/05/25/response-end-response-close-and-how-customer-feedback-helps-us-improve-msdn-documentation/
Given what is documented in the MSDN blog post, it sounds like using HttpResponse.End is the wrong approach, so I was wondering if it is even needed or whether there is a better approach?
Here is the actual code from Response.End:
public void End()
{
if (this._context.IsInCancellablePeriod)
{
HttpResponse.AbortCurrentThread();
return;
}
this._endRequiresObservation = true;
if (!this._flushing)
{
this.Flush();
this._ended = true;
if (this._context.ApplicationInstance != null)
{
this._context.ApplicationInstance.CompleteRequest();
}
}
}
The ThreadAbortException is used for control of flow-- basically allowing you to use Response.End in place of return. But if you've designed your handler well, you may not need it, e.g. if there is no code after Response.End(). It is generally better not to throw the exception if you can avoid it, since it (like all exceptions) will cause a stack unwind and some performance overhead.
Perhaps you can write your own version of Response.End and pick and choose which lines of code actually execute, e.g. maybe you want to flush the buffer and call CompleteRequest but you don't want to throw the exception.
Here is the approach I have used in the past
// Sends all currently buffered output
HttpContext.Current.Response.Flush(); to the client.
// Gets or sets a value indicating whether to send HTTP content to the client.
HttpContext.Current.Response.SuppressContent = true;
/* 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();
Related
I don't like error handling via try catch blocks but in this case I did not see any other clear path. In my code I'm calling a web service but it might soon be a rest API in the near future. This web service is external and unfortunately not 100% reliable. What I need to do is create code that can handle an unresponsive web service. Today it looks like this:
SOAP Proxy is set to have a timeout of 120 seconds
var myProxy = new WebReference.ProxyClass();
myProxy.Timeout = 120000;
try
{
CreditInformation creditInformation = myProxy.Retrieve(prospect.CorporateIdentity);
agreement.Company.Name = creditInformation.CompanyName;
agreement.FinancialInformation.NetRevenue = creditInformation.Revenue / 1000;
}
catch (WebException e) when (e.Status == WebExceptionStatus.Timeout)
{
logger.Error("Web service timed out");
}
//Continiue running code even if the web service time out
Is this a bad standard and could it be better performed? As I said before I don't like handling errors via try catch but it seemed viable here. I thought about creating some code to check if the web service was responding but i decided not to go this way. This is because the web service is quite slow, a request takes 30-60 seconds by default and that would leave the user waiting even longer for me to check if it is up. Another solution might be to ping the host but it does not guarantee that the service is actually up. Sample code:
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
if (response != null && response.StatusCode == HttpStatusCode.OK)
{
//Do stuff here
}
There are two opposite camps about how to handle exceptional situations. One camp prefers exceptions, another camp prefers to return error codes (or similar) from a function that might fail in one form or another. What is "better" is arguable and situation-dependent (see for example: http://www.joelonsoftware.com/items/2003/10/13.html for the arguments of "error code" camp). I'm telling this because as I understand you would prefer that myProxy.Retrieve return some error code on timeout, not throwing an exception. It might be reasonable, but that's not how it works and you cannot change that. Whole .NET framework uses exceptions almost everywhere (sometimes in situations which might be considered "part of normal flow", though definition of normal flow is again not trivial).
Long story short - a lot of code you use in .NET will throw exceptions on errors, even in sutations which you consider normal, and you have to live with that and act accordingly - catch and handle them - that's perfectly normal. Usually there are 2 points against exceptions:
They cost some time and resources to construct, as you mention in comment. That's reasonable concern in some code which executes thousands of operations per second, and those operations throw thousands of exceptions. In your case however, request takes 30-60 seconds, and as such cost of exception is absolutely zero compared to that.
They change control flow, sometimes moving it very far from actual exception source (like goto statement). To handle this (if you are in the "error code" camp, but have to work with exceptions anyway), you should put try-catch block as close as possible to the function which produces it, and handle exception immedatly, because you know exactly where and why it happened. This if what you already do in your example.
So, surrounding soap service call with try-catch block and handling timeout exception is the best way to go here, and there is absolutely no need to try to avoid this exception being thrown. You might want to not throw exceptions in "normal" conditions yourself, in your own code, but if that happens in third party code - you have to handle and not avoid them.
I have a huge website with a huge backend. Somewhere, somehow, there is a Response.Redirect called while trying to open a site (debug environment).
Is there a way to find out, which Response.Redirect causes the redirect?
An certain way would be to set a debug breakpoint on every Response.Redirect in the whole website. But this is a lot of effort.
Another idea I had was to stop at the "ThreadAbortException" (which is thrown by Response.Redirect) with "Debug->Exceptions..". But this doesn't work. Seems like the frame or whatever is no longer executed to get a break on it.
Last attempt was to watch the call-stack. But the stack never gets to the last Response.Redirect because it is a new frame call.
Well, I got an idea which solved my problem but required massive code replacement (which is not a problem with 'Find and replace').
I created an static class:
public static class OwnResponse
{
public static void Redirect(string Url, bool EndResponse = true)
{
HttpContext.Current.Response.Redirect(Url, EndResponse); // set the breakpoint here
}
}
Then I replaced every Response.Redirect in the code with OwnResponse.Redirect. Now I was able to set my breakpoint onto the first line in the class. I called the website and the breakpoint got hit. Then I just watched the call-stack and knew where the redirect occurs.
There is another possible solution, which requires a bit more work. You have to get "Stepping into .NET code" to run. Then you can easily set a break point in the .NET method's first line.
Open the Exception Settings window and search for "threadabort". Check the checkbox for the ThreadAbortException. Now, when a redirect is executed from code, your debug session will enter break mode.
You can use below code in landing page:-
string yourPreviousUrl = Request.UrlReferrer.ToString();
if(!string.IsNullOrEmpty(yourPreviousUrl))
{
//Referrer was found!
}
else
{
//Unable to detect a Referrer
}
As mention in official site :-
HttpRequest.UrlReferrer Property
Gets information about the URL of the client's previous request that
linked to the current URL.
You could try to implement tracing and save the results to a file. The trace data might help you to pinpoint your redirect.
Here is a link with some more background on ASP.NET tracing:
http://www.codeproject.com/Articles/82290/Step-by-Step-Guide-to-Trace-the-ASP-NET-Applicatio
Use fiddler or another http traffic capture tool and capture the network traffic. You should be able to see the request that was initiated and take it from there.
I had this situation not sure how to best handle this. Input would be appreciated. Imagine I Have such method:
void loaddata()
{
try
{
// EXTRA: I also want to skip below SaveSomething if there was exeption
// last time I called DecryptAndloadXMLdata. This may happen
// if user calls loaddata twice. This is exaclty similar situation
// as app quitting just it happens is user calls loaddata twice
// and during first call there was exception say with DecryptAndloadXMLdata
Savesomething(listOfObjects, xmlPath);//save old data first
xmlPath = newValue;
// some operations
xmlDoc = DecryptAndloadXMLdata(xmlPath);
// some other operations- populate List with data from above XML file
listOfObjects.Add(objectFromXML);
// Here also possibly modify contents of listOfObjects elements
}
catch(Exception ex)
{
xlmPath="";
}
}
Now the thing is when app is quiting I have such feature
to automatically save the List object populated in above
method to a file. Like:
void whenAppisQuitting()
{
Savesomething(listOfObjects, xmlPath);
}
But the problem is. Imagine xmlDoc = loadXMLdata(); throws in above method. What will happen is the List I mentioned won't be populated and when app is quitting empty elements (e.g. empty listOfObjects) will be written to xmlPath - thus damaging my original file because there was unrelated exception say due to encryption in loadXMLData method.
I hope I have made my issue clear. What is the way to deal with such situations? For example what I did you can see I set xmlPath to empty in catch - thus in case of any exception I considered data was not loaded successfully - hence now on application exit I can be calm because nothing will be written to file because its xmlPath ="". Is it reasonable way to solve this issue?
Getting bit confused because this kind of issues now raise error handling to different level - I need to account for all possible kind of failures?
What is the way to deal with such situations?
I would set a flag indicating there was an error when parsing. Setting the path to string.Empty can lead to confusion (IMO). Perhaps an empty string could be a possible value bring passed to your method.
catch(Exception ex)
{
// Log
IsParsingSuccessful = false;
}
And look upon that flag when you want to write:
void AppIsQuitting()
{
if (IsParsingSuccessful)
{
SaveSomething(listOfObjects, xmlPath);
}
}
As a general guidance, you probably should never overwrite files without explicit intent from the user.
As for your error handling, use a simple flag / boolean to indicate valid behavior. Only set that flag to true after everything is processed and only if that flag is true, save the contents to the file.
I was wondering whether if it was necessary to keep a return statement after my Response.RedirectPermanent call in my codebehind? It doesn't seem like it, but I wanted to confirm with others.
Response.RedirectPermanent(vpd.VirtualPath);
return;
Is there any reason to do so either for a functional or performance gain?
Answer overhaul:
Hold the phone! The detail in my previous answer was, following further research, not at all true. In fact, the MSDN documentation specifies the following:
When you use this method in a page handler to terminate a request for one page and start a new request for another page, set endResponse to false and then call the CompleteRequest method. If you specify true for the endResponse parameter, this method calls the End method for the original request, which throws a ThreadAbortException exception when it completes. This exception has a detrimental effect on Web application performance, which is why passing false for the endResponse parameter is recommended.
http://msdn.microsoft.com/en-GB/library/a8wa7sdt.aspx
So, in actual fact, the rest of the page is not executed (in theory - see 'Update' below for an example of when this falls over); however, there is still a very tangible issue with doing it the way you are, which is that the endResponse mechanism is implemented by throwing a ThreadAbortException, which is a relatively expensive way of terminating the processing of the current thread.
Instead, you should tell it to let the thread continue, but return immediately - also be sure that other methods in the call stack are doing what they should:
Response.RedirectPermanent(vpd.VirtualPath, false);
return;
Better yet, wrap the call in a conditional to ensure that undesirable code doesn't get called and then use the CompleteRequest method (which does not terminate the currently-executing code but will bypass all subsequent events):
if (_redirecting)
{
Response.RedirectPermanent(vpd.VirtualPath, false);
Context.ApplicationInstance.CompleteRequest();
}
else
{
/* Code I don't want to execute if I do a redirect */
DeleteUsersDataForever(_currentUser);
}
There's an in-depth article on this very topic here and even the documentation itself seems to have an unhealthy distaste for the HttpResponse.End method, which is what's called if you allow Response.Redirect to do the response termination for you.
Update: Additionally, given that the thread is terminated by raising an exception, consider what happens if you try and do your redirect inside a try/catch:
try
{
// Redirect and terminate execution
Response.Redirect(someUrl, true);
}
catch
{
// Handle some errors.
}
DeleteUsersDataForever(_currentUser);
The exception that's raised by Response.End is caught in your catch block. The rest of your code is, therefore, still executed and you have accidentally deleted all of _currentUser's data (unless you do something to prevent this in your catch block, such as bubbling the exception to the caller).
I have tried the code below :
Page1.aspx
protected void Page_Load(object sender, EventArgs e)
{
Response.RedirectPermanent("~/Page2.aspx");
Session["afterRedirect"] = "after redirect";
}
Page2.aspx
protected void Page_Load(object sender, EventArgs e)
{
Response.Write(Session["afterRedirect"] ?? "nothing to show");
}
Result
nothing to show
Code after RedirectPermanent does not execute so Iguess using a return or not will have the same effect.
My local test server crashes as soon as I'm trying to write to a logfile. I'm using this for an ASP.NET-Page, codebehind is C#.
Structure:
/
Functions.cs
index.aspx
index.aspx.cs
I create an instance of Functions as my index.aspx loads. In Functions, I define a function for logging, which is called from index.aspx.cs and looks like this:
if (_WriterOpen == false)
{
_Writer = new StreamWriter(_WorkingDir + _Logfile, true);
_WriterOpen = true;
_Writer.AutoFlush = true;
}
_Writer.WriteLine(DateTime.Now.ToString() + ": " + String.Format(Note, Args));
_Writer is defined globally for the Class and contains, as you see, a StreamWriter. The class itself has a destructor to close any connections to the files;
~Functions()
{
_Writer.Flush();
_Writer.Close();
_Writer.Dispose();
}
So, when I open up my page, the logs are written but then the server crashes. So I assume the problem is somewhere in the descructor, but I can't figure out why...
You don't need any destructor, StreamWriter already have it's own.
You should not access other objects from a destructor as it will be called by the Garbage collector, the other objects are in an undeterminable state. You don't know when it will be called and you don't know on which thread it will be called.
NEVER, NEVER, NEVER write a destructor, it's almost always a bad idea.
You may place your cleanup code in the Unload event, see ASP.NET Page Life Cycle.
I'd recommend the using statement which automatically invokes the dispose call. For your purposes the code would look something like:
StreamWriter _Writer;
using(_Writer)
{
if (_WriterOpen == false)
{
_Writer = new StreamWriter(_WorkingDir + _Logfile, true);
_WriterOpen = true;
_Writer.AutoFlush = true;
}
_Writer.WriteLine(DateTime.Now.ToString() + ": " + String.Format(Note, Args));
}
Note I haven't tested this out but it should work (or at least be close). I'll update if needed after checking it out
Also see the following two articles:
Article 1
Article 2
This sounds most likely to be a stack overflow error, caused by a recursive call.
Are you logging an error, that is causing an error, that is logging, causing...etc.
Can you run it in debug mode from Visual Studio?
First: you don't need to call both close and dispose.
See the link from MSDN:
link text
This implementation of Close calls the Dispose method passing a true value.
You must call Close to ensure that all
data is correctly written out to the
underlying stream. Following a call to
Close, any operations on the
StreamWriter might raise exceptions.
If there is insufficient space on the
disk, calling Close will raise an
exception.
If you cant run it through in the debugger, try commenting lines out of Functions until it stops falling over. This should give you a clue.
The garbage collector will call the destructor at some indeterminate time, so if you are getting a regular crash, its probably not the destructor.
I would prefer to make the class inherit from IDisposable and put the clean up code in there. Use the dispose pattern : here