Scenario: You want to know if a client completes a large download successfully.
Possible Solution: Create a custom ActionResult (perhaps derived from FileStreamResult) that streams the data and checks to see if the client remains connected.
public class CheckedFileStreamResult : FileStreamResult { public CheckedFileStreamResult(FileStream stream, string contentType) :base(stream, contentType) { DownloadCompleted = false; } public bool DownloadCompleted { get; set; } protected override void WriteFile(HttpResponseBase response) { var outputStream = response.OutputStream; using (FileStream) { var buffer = new byte[_bufferSize]; var count = FileStream.Read(buffer, 0, _bufferSize); while(count != 0 && response.IsClientConnected) { outputStream.Write(buffer, 0, count); count = FileStream.Read(buffer, 0, _bufferSize); } DownloadCompleted = response.IsClientConnected; } } private const int _bufferSize = 0x1000; }
You can now log or audit the DownloadCompleted property of the result from an action filter. I'm sure this isn't 100% foolproof, but it seems to work reasonably well. Note: The IsClientConnected property of the response only tells the truth when running under IIS. With the WebDev server the property always returns true.
Comments
Don't forget to turn off the buffer. So that your file is sent in chuncks to the client
response.BufferOutput = false;
I don't know if you set this in your web.config or somewhere else, but it is important for your readers to understand the ASP.NET by default buffers all output before it is sent back to the client.
Nice sample anyhow :D
Erik
Second point is that due to Lazy execuation of ActionResult in ASP.NET MVC, there is no way to query DownloadCompleted property. The reason is that ASP.NET MVC internally calls the ExecuteResult method which results in call of WriteFile method.
When we derive from FileSteamResult we can still override WriteFile - this is a streaming operation after all.
It's easy to check DownloadCompleted during OnActionExecuted (which is after the result executes).
For my second point, the only way to inspect DownloadCompleted property is to use ResultExecuted filter not ActionExecuted filter because ActionExecuted is executed before WriteFile method. But at this point you have no choice to change Result.
On your second point - yes, my mistake. I meant to say OnResultExecuted not OnActionExecuted.
protected override void OnResultExecuted(ResultExecutedContext filterContext)
{
var download = filterContext.Result as CheckedFileStreamResult;
if(download != null)
{
// ...
}
}
I'm not worried about changing the result - just logging if the download appears to have been successful.
just curious, why is it not logical to override a method in a child class when the same method is overriden in the parent class. Can you point me to any resource that touch upon this topic?
Thanks!
Zen
You need to be more precise. You have to mention this is article related to MVC in very first stage. Please take this as my request.Also please mention where this will be used in applciation. An example will be enough.
Thanks,
Thani
I have seen lot of methods which are overridden in child and are declared as virtual in parent but never seen a method which is defined as override in parent and again overridden in child.
But the truth fact is that override method is by default virtual for it's child classes(From a Microsoft Book). So I am agreeing that your method is not illogical.
I have seen lot of methods which are overridden in child and are declared as virtual in parent but never seen a method which is defined as override in parent and again overridden in child.
But the truth fact is that override method is by default virtual for it's child classes(From a Microsoft Book). So I am agreeing that your method is not illogical.
Could you make a complete example?
/Frank
Apologies if you think this is blatant spam, but you could then use my open source Google Analytics wrapper - GaDotNet to log the download success to your GA account :)
www.diaryofaninja.com/projects/details/ga-dot-net
keep up the great work - you have a new subscriber!