Server cannot modify cookies after HTTP headers have been sent - c#

I am creating a web application in C#.
When my page loads I fire an asynchronous thread to process some data. Part of this processing is the updating of a cookie. However when I save the cookie to the response by
System.Web.HttpContext.Current.Response.Cookies.Add(cookie), I get the following exception:
HttpException: Server cannot modify cookies after HTTP headers have been sent.
Any way I can work around or fix this?

Unless you have a very good reason to, you shouldn't be spinning up background worker threads in an ASP.NET request. Ultimately you still have to wait for this thread to finish its work before you send the response back to the browser.
It sounds like the response stream has already been partially written to and then your thread is trying to add the cookie.
I'd rethink your strategy here and take a read of the following guidelines:
Chapter 6 — Improving ASP.NET Performance - Threading Guidelines
It looks like a dated document but the principles still stand. If the reason for making your call to the data processor is to prevent the ASP.NET worker thread from blocking and using up resources because the data processor is long running, then consider making the page an Asynchronous page instead.

Yes, Cookies are part of the http response and in a async operation you cannot change anything after response is generated and sent to browser.
To workaround this i recommend to build a ajax loop on browser to get async operation result. When operation completed you can return a cookie with ajax response.

What if it is in preinit or init? not sure if this will help though.
http://msdn.microsoft.com/en-us/library/ms178472.aspx#lifecycle_events

Related

Best practise - C# .Net console app POST to a url

What would be the best approach to make a POST request to a web service url, in a Console App?
I tried using WebClient.uploadstring but it fails whenever the POSTed data is slightly bigger.
I tried HTTPClient but it's an async call.. so I had to additionally use ManualResetEvent to keep it alive till the server response is received..
I'd like to know what's the best way to do this. Please let me know if mpre info is required.
What do you mean by "huge"?
If you are posting large amounts of data to the URL, then you could be exceeding the maximum request size, in which case no method of requesting the URL with that amount of post data will work.
I ended up using HTTPClient's PostAsync(url, content).Result which waits till it gets a response! neat stuff..

Trying to use asp.net async page

I have an ASP.NET (webforms) page that needs to call a stored procedure which may take up to a minute to return. I realise that this is not ideal but the the database side of this project is out of my hands and hence I must live with this problem.
Basically I am looking for some method which will allow the page to render without the stored procedure hanging the page - with the results from the database call being displayed when available.
So, I am looking at an async page. I have added "ASYNC=TRUE" to the top of the page and so far, I have the following:
private async void GetCampaignCounts(int CampaignID)
{
Task t = new Task
(
() =>
{
CampaignService cs = new CampaignService();
FilterSet.TargetCounts f = cs.GetCampaignDetails(CampaignID); //LONG RUNNING DB CALL
if (f.Total > 0)
{
panelStatsLeft.Visible = true;
//DO STUFF IN HERE
}
else
panelStatsLeft.Visible = false;
}
);
t.Start();
await t;
}
However, this still hangs the page whilst the database query is running!
Am I doing something totally wrong?!
The asynchronous requests in web applications are not intended to not hang the page. The request will still take the same time as the synchronous version. The benefits are in scalability (i.e. if your page could handle 100 simultaneous users before it would be able to handle 1000 if it is async on the same hardware assuming that the bottleneck was the request pipeline and not the database).
If you want to make the page load and update itself when the operation completes I am afraid you will need significantly more complex architecture. Your best bet is load the page and do an ajax request that runs the query and update the page when the request returns. It is a best practice to use async/await for this ajax request (again for scalability).
Personally i wouldn't bother tying the two together. A better operation is to offload the query elsewhere and return later to get the results.
So use a signalling framework such as signalr. Submit your report parameters, pass them to msmq where they can be handled on a different server or use a one way wcf request. When the request is received optionally store the result in the database and use signalling to notify client (either passing them the actual result or telling them the url where they can download the report from (pick it up from the database in that other url)). Async that into the users current browser page which presumably has a spinner saying "hey we are generating your report".
Consider signalling too.
As I describe in my MSDN article on the topic, async on ASP.NET is not a silver bullet:
When some developers learn about async and await, they believe it’s a way for the server code to “yield” to the client (for example, the browser). However, async and await on ASP.NET only “yield” to the ASP.NET runtime; the HTTP protocol remains unchanged, and you still have only one response per request. If you needed SignalR or AJAX or UpdatePanel before async/await, you’ll still need SignalR or AJAX or UpdatePanel after async/await.
This makes sense if you think about the HTTP protocol: there can be only one response for each request, and async doesn't change the HTTP protocol (more detail on my blog). So, if you return a response to the client (allowing it to render the page), then that request is done. You can't send a followup response later to change the page you already sent.
The proper solution is fairly complex, because ASP.NET wasn't designed to track "background" operations without a request. ASP.NET will recycle your application periodically, and if there are no active requests, it assumes that it's a good time to do so. So, "background" operations are in danger of being terminated without notice.
For this reason, the best solution is to have an independent worker process that actually executes the background operation using a basic distributed architecture (requests are placed into a reliable queue by the ASP.NET handler; requests will re-enter the queue automatically if the worker process fails). This also means your requests should be idempotent.
If you don't want this level of complexity, you can trade-off reliability for complexity. An intermediate step is Hangfire, which requires a database backend at least (which it uses for reliability instead of a queue). If you want the least reliability (and least complexity), you can just use HostingEnvironment.QueueBackgroundWorkItem or my ASP.NET Background Tasks library. I have a longer overview of these options on my blog.

How do you handle an Async Response from a Web Service

I was given the task of creating a web based client for a web service.
I began building it out in c# | .net 4.0 | MVC3 (i can use 4.5 if necessary)
Sounded like a piece of cake until I found out that some of their responses would be asynchronous. This is the flow ... you call a method and they return a response of ack or nack letting you know if your request was valid. Upon an ack response you should expect an async response with the data you requested, which will be sent to a callback url that you provide in your request.
Here are my questions:
If I'm building a web app and debugging on localhost:{portnum} how can I give them a callback url.
If I have already received a response (ack/nack) and my function finishes firing isn't my connection to the client then over ? How would I then get the data back to the client? My only thought is maybe using something like signalR, but that seems crazy for a customer buy flow.
Do I have to treat their response like a webhook? Build something separate that just listens and has no knowledge of the initial request. Just save the data to a db and then have the initial request while loop until there is a record for the unique id sent from the webhook.... oye vey
This really has my brain hurting :-/
Any help would be greatly appreciated. Articles, best practices, anything.
Thanks in advance.
If you create your service reference, it will generate a *ServiceMethod*Completed delegate. Register an event handler on it to process your data.
Use the ServiceMethod_Async() method to call the service.
The way I perceived your question is as follows, though please correct me if I'm wrong about this:
1) You send a request to their endpoint with parameters filled with your data. In addition, you send a:
callback url that you provide in your request. (quoted from your question)
2) They (hopefully) send an ack for your valid request
3) They eventually send the completed data to your callback url (which you specified).
If this is the flow, it's not all that uncommon especially if the operations on their side may take long periods of time. So let's say that you have some method, we'll call it HandleResponse(data). If you had originally intended to do this synchronously, which rarely happens in the web world, you would presumably have called HandleResponse( http-webservice-call-tothem );
Instead, since it is they who are initiating the call to HandleResponse, you need to set a route in your web app like /myapp/givemebackmydata/{data} and hook that to HandleResponse. Then, you specify the callbackurl to them as /myapp/givemebackmydata/{data}. Keep in mind without more information I can't say if they will send it as the body of a POST request to your handler or if they will string replace a portion of the url with the actual data, in which case you'd need to substitute {data} in your callback url with whatever placeholder they stipulate in their docs. Do they have docs? If they don't, none of this will help all that much.
Lastly, to get the data back on the client you will likely want some sort of polling loop in your web client, preferably via AJAX. This would run on a setInterval and periodically hit some page on your server that keeps state for whether or not their webservice has called your callback url yet. This is the gnarlier part because you will need to provide state for each request, since multiple people will presumably be waiting for a callback and each callback url hit will map to one of the waiting clients. A GUID may be good for this.
Interesting question, by the way.

What happens in IIS/C# when a request is aborted

So I'm thinking about a functionality where the user pastes a link and the server-side code crawls the provided link and responds with the contents of that link (such as page title, description, thumbnail, etc).
The user can meanwhile change the link, and in doing that, the ajax-request should be aborted client-side.
I'm wondering what exactly happens in the IIS server and specifically to my C# code.
Is the response thread terminated?
Does the Response object now return null, or Response.Write throw exceptions?
Is an exception thrown in the response thread just whereaver it is? (that one doesn't even make sense, but whatever)
If the server code checks the state of Response.IsClientConnected, it can stop the work and produce an empty response when the client aborts the request, otherwise it will just complete the request as usual.
The request handling will not be aborted automatically just because there is noone waiting for it any more. The server code has to actively check the state of the request.
Your web server doesn't know that the client cancelled the request. The request will still be fulfilled and a response will be sent back. The client-side script that you write will need to be able to handle what the current state of your page should be.
If you are certain that you don't care about the response, I would recommend aborting the request client-side:
xhr.abort()
If you close the connection client side before the response is written an error stating as much is thrown. You could just choose not to handle the response when it comes back from the server.
Once a request is posted to server the IIS will start executing the server side code. Now the server can decide upon whether the code needs to be executed or not.
In the entire page cycle you can check Request.IsClientConnected as mentioned by Guffa and terminate the execution.
But yes it totally depends on the scenario you have.
Hope it helps.

ASP.Net Response.Close issue

I am using ASP.Net + .Net 3.5 + VSTS 2008 + IIS 7.0 + C# to develop a web application. I find when debugging in VSTS 2008, if I call Response.Close() method in page_load (please refer to code below), there will be error (from IE when accessing the page) like can not connect to server.
My question is,
Normally when should we call Response.Close()? Or no need to call (rely on ASP.Net framework to automatically close)?
BTW: my previous understanding is developer should always call Response.Close when processing is completed at server side and all data has been written to client using Response.Write. Am I correct?
2 Why I met with such error in my code? What is the root cause?
protected void Page_Load(object sender, EventArgs e)
{
Response.Write("Hello World! ");
Response.Close();
}
The following from the MSDN website might be useful here:
This method terminates the connection to the client in an abrupt manner and is not intended for normal HTTP request processing. The method sends a reset packet to the client, which can cause response data that is buffered on the server, the client, or somewhere in between to be dropped.
You might use this method in response to an attack by a malicious HTTP client. However, typically you should call CompleteRequest instead if you want to jump ahead to the EndRequest event and send a response to the client.
You should not normally use the Response.Close method in "normal" ASP.NET processing.
All of your data that is written to a HttpResponse "stream" is buffered before being sent to the client browser. The Response.Close method will abruptly terminate the HTTP connection and you may lose data that you have previously Response.Written inadvertently.
If you really want to programmatically "force" the end of a response stream, you should use either: Response.Flush(); followed by Response.End();
The Response.Flush method call ensures that all data that you may have written to the response stream is "flushed" to the client, and Response.End ensures all currently buffered data is correctly sent to client, and also raises the EndRequest event, which you may want to handle.
You can also use the HttpApplication's CompleteRequest() method.
The MSDN documentation states it best:
This method terminates the connection
to the client in an abrupt manner and
is not intended for normal HTTP
request processing. The method sends a
reset packet to the client, which can
cause response data that is buffered
on the server, the client, or
somewhere in between to be dropped.
You might use this method in response
to an attack by a malicious HTTP
client. However, typically you should
call CompleteRequest() instead if
you want to jump ahead to the
EndRequest event and send a response
to the client.
In my experience there is no reason to call Response.Close(); within the code example you've provided, just remove it.
In the pages lifecycle after the Page_Load is fired, there are a number of other methods that will be called that will close your responses for you.
Read here for the Page Lifecycle
To answer question 1:
You should call Response.Close() when your need to terminate the connection - that is, nothing else needs to be sent to the client at all. This does not include what you have posted, since the rest of the page needs to be processed and sent to the client. Normally you would call it when returning data that is not a page from an aspx page (for example a pdf file, an image etc...).
To answer question 2:
You should not call Response.Close() in your Page_Load event handler - it will mean that the rest of the page lifecycle will not run properly.
From MSDN (HttpResponse.Close method):
This method terminates the connection to the client in an abrupt manner and is not intended for normal HTTP request processing. The method sends a reset packet to the client, which can cause response data that is buffered on the server, the client, or somewhere in between to be dropped.
.NET is a very flexible network it will let you do anything you could before .NET. (and more obviously). But the most wonderfull thing is that .NET will take care of verything it can take care of for you.
That means if you create and empty web page and run it in your browser you don't have to do anything else to make it work.
Sometimes however you might find yourself in a situation where you need to do something extraordinary and you will be thankfull for the existance of functions like Reponse.Close()
In your case you're not doing such a thing so there's no need for any special function calling.
Besides that Response.Write() is what we used to use back in the days...Are you still thinking in the classic ASP mode maybe?
Suggestion: Don't use Response.Write()
But put a label in your web page and use:
this.Label1.Text = "Hello world";
Addtional comment:
The purpose of ASP.Net in particular is to send web pages to a browser, collect any posted data, process it, interact with the server OS and so on.
So you might, in my opinion, assume that some care has been taken in 1) serving pages fast and 2) making sure nothing goes wrong when the user follows the guide lines on how to program .Net web pages.
There's no need to implement ALL Page event handlers. Understand the framework, understand what each page event does and learn when to implement which event.
If you're only going to show data from a database you don't even need event handlers.
Read about the Data Controls (Data sources, GridView, ListView, Repeater, etc).
Assume that if you do nothing, the framework will do it for you.
(IF you do nothing at all, nothing happens, that's by design)
Cheers.

Categories

Resources