stupid caching in asp.net - asp.net

i use such code
string.Format("<img src='{0}'><br>", u.Avatar);
u.Avatar-it's like '/img/path/pic.jpg'
but in this site i can upload new image instead old pic.jpg. so picture new, but name is old. and browser show OLD picture (cache). if i put random number like /img/path/pic.jpg?123 then works fine, but i need it only ufter upload, not always. how can i solve this?

string imgUrl = _
string.Format("<img src='{0}?{1}'><br>", _
u.Avatar, _
FunctionThatLookupFileSystemForItsLastModified(u.Avatar).Ticks.ToString());

Instead of linking to the images directly, consider setting up a generic HTTP handler to serve the images.
MSDN: HTTP Handlers and HTTP Modules Overview
Stack Overflow: How to use output caching on .ashx handler

Append DateTime.Now.Ticks to the image url:
string imgUrl =
string.Format("<img src='{0}?{1}'><br>", u.Avatar,DateTime.Now.Ticks);
EDIT: I don' think this best practice are even a practice I would use. This is just a suggestion given the limited information given in case the Random implementation isn't truly Random.

Read your post again,,, sorry for general answer.
To workaround it do following
On Application_Start create a Dictionary with uploaded images save it on Application object, set it to null. Once you upload an image add it to this Dictionary. Wrap every place avatars appear on your website with function that evaluates image in Dictionary if found return imagename.jpg?randomnumber and then delete it from a Dictionary else return just an imagename.jpg.
This is going to be heavy because you will need to check each image in Dictionary but this will do exactly what you need.

You can set cache dependancy using the System.Web.Caching.CacheDependency namespace.
This can set the dependancy on the file uploaded, and will release the cache for that file automatically when the file changes.
There are lots of articles and stuff on MSDN and other places so I will not go into details on all that level of detail.
You can do inserts, deletes and other management of cache using the tools available.
(and this does not require you to change the file names or tack on stuff - it knows by the file system that the file changed)

Related

Pass value WinForm =>(page.html?query123)=> HTML =>(page.aspx?query123)=> asp.net //esle?

The problem here is the middle of the line (HTML).
The chain:
I have WinForm program that uses awesomium (alternative to native webBrowser) to view Html page that has a part of asp.net page in it's iframe.
The problem:
The problem is that I need to pass value to asp.net page, it is easily achieved without middle of the chain (Html iframe) by sending hashed and crypted querystring.
How it works:
WinForm do some thing, then use few-step-crypt to code all the needed values into 1 string.
Then it should send this string to asp.net page through the iframe (and that's the problem, it is easy to receive query string in asp.net page, but firstly I need to receive it in Html and send to asp.net).
Acceptable answers:
1) Probably the most easily one - using JavaScript. I have heard it is possible to be done in that way.
How I imagine this - I send query string from WinForm to Html page as http:\\HtmlPage.html?AspNet.aspx?CryptedString
Then Html receive it with JavaScript and put querystring "AspNet.aspx?CryptedString" into iframe's "src=http:\\" resulting in "src=http:\\AspNet.aspx?CryptedString"
And then I easily get it in asp.net page.
2) Somehow create >>>VIRTUAL<<<(NOTE: Virtual, I don't want querystring to be saved on the HDD, even don't suggest) asp.net or html page with iframe source taken directly from WinForm string.
Probably that is possible with awesomium, but I'm new to it and don't know how to (if it is possible ofc).
3) Some web service with which I can communicate between asp.net and WinForm through the existing HTML iframe.
4) Another way that replace one of 3 previous, that doesn't save "values" in querystring/else on HDD nor is visible for the user, doesn't use asp.net page's server to create iframe-page on it. On HTML page's server HTML is only allowed, PhP isn't.
5) If you don't know any of 4 above - suggest free PhP hosting without ads (if such exists, what I highly doubt).
Priority:
The best one would be #3, then #2, then #1, then #5 (#4 is excluded as it is unknown).
And in the end:
Thanks in advance for your help.
P.S.Currently at work, so I'll check/try all answers later on and will report tomorrow if any suits my needs. Thanks again.
Answering my own question. I have found 2 ways that can do what I did want.
The first one:
Creating a RAM file System.IO.MemoryStream or another method (google c# create a file in ram).
The second one:
Creating a hidden+encrypted+system+custom-readable-only-by-program-crypt file somewhere in the far away folder via File.SetAttributes Method and System.IO.StreamWriter/Reader or System.IO.FileStream or System.IO.TextWriter, etc. depending on what it should be.
Once this file was used for needs delete it + delete on exit + delete on start using
if (File.Exists(path)
{
File.Delete(path);
}
(Need more reputation to post few links -_-, and I don't want to post only part of them, either all or no at all, so use google if you'll need anything from here).
If you'll need to store "Small temp file" and not for a long time use first one, if "Heavy" use second one, unless you badly need to use RAM for it.

Working with big files in classic ASP

I was wondering what's the best practise for serving a generated big file in classic asp.
We have an application with "export to excel" function that produces 10MB files. The excels are created by just calling a .asp page that has the Response.ContentType set to excel and has an HTML table for the data.
This gives as problem that it takes 4 minutes before the user sees the "Save as..." dialog.
My current solution is to call an .asp page that creates the excel on the server with AJAX and lets the page return the URL of the generated document. Then I can use javascript to display the on the original page.
Is this easy to do with classic asp (creating files on server with some kind of stream) while keeping security in mind? (URL should make people be able to guess the location of other files)
How would I go about handling deleted the generated files overtime? They have to be deleted periodicly as the data changes in realtime.
Thanks.
edit: I realized now that creating the file on the server will probably also take 4 minutes...
I think you are selecting a complex route, when the solution is simple enough (Though I may be missing some requirements)
If you to generate an excel, just call an asp page that do the following:
Response.clear
Response.AddHeader "content-disposition", "attachment; filename=myexcel.xls"
Response.ContentType = "application/excel"
'//write the content of the file
Response.write "...."
Response.end
This will a start a download process in the browser without needing to generate a extra call, javascript or anything
See this question for more info on the format you will choose to generate the excel.
Edit
Since Thomas update the question and the real problem is that the file take 4 minutes to generate, the solution could be:
Offer the user the send the file by email (if this is a workable solution in you server or hosting).
Generate the file async, and let the user know when the file generation is done (with an ajax call, like SO does when other user have added an answer)
To generate the file on the server
'//You should change for a random name or something that makes sense
FileName = "C:\temp\myexcel.xls"
FileNumber = FreeFile
Open FileName For Append As #FileNumber
'//generate the content
TheRow = "...."
Print #FileNumber, TheRow
Close #FileNumber
To delete the temp files generated
I use Empty Temp Folders a freeware app that I run daily on the server to take care of temp files generated. (Again, it depends on you server or hosting)
About security
Generate the files using random numbers or GUIds for a light protection. If the data is sensitive, you will need to download the file from a ASP page, but I think that you will be in the same problem again...(waiting 4 minutes to download)
Read file using FSO.
Set headers for Excel file-type, name according to file read and for download (attachment)
Flush response after headers are set. The client should display "save as" dialogue.
Output FSO to response. Client will download file and see progress bar.
How do you plan to generate the Excel? I hope you don't plan to call Excel to do that, as it is unsupported, and generally won't work well.
You should check to see if there are COM components to generate Excel that you can call from Classic ASP. Alternatively, add one ASP.NET page for the purpose. I know for a fact that there are compoonents that can be called from ASP.NET pages to do this. Worse come to worst, there's an Excel exporter component from Infragistics that works with their UltraWebGrid control to export. The grid need not be visible in order to accomplish this, but styles in the grid translate to styles in the spreadsheet. They also allow you to manipulate the spreadsheet programmatically.

Is there an enum for the ContentType property on a HttpWebResponse ("text/plain", "application/octet-stream" etc.)?

The closest thing I could find was System.Net.Mime.MediaTypeNames but that doesn't seem to have everything (like json) since it seems to be more focused around email attachments.
An enum doesn't make much sense. MIME types are open-ended. That is, the list is not finite: new types are added from time to time.
See RFC4288: Media Type Specifications and Registration Procedures
In 2022, with .NET Core and .NET5+, this is now available via MediaTypeNames. For example:
MediaTypeNames.Application.Json
MediaTypeNames.Image.Png
MediaTypeNames.Text.Html
Microsoft documentation around MediaTypeNames, and each of Application, Image, Text.
https://learn.microsoft.com/en-us/dotnet/api/system.net.mime.mediatypenames?view=net-6.0
https://learn.microsoft.com/en-us/dotnet/api/system.net.mime.mediatypenames.application?view=net-6.0
https://learn.microsoft.com/en-us/dotnet/api/system.net.mime.mediatypenames.image?view=net-6.0
https://learn.microsoft.com/en-us/dotnet/api/system.net.mime.mediatypenames?view=net-6.0
https://learn.microsoft.com/en-us/dotnet/api/system.net.mime.mediatypenames.text?view=net-6.0
IANA's database is most likely to be complete. Currently, they have the list available in CSV format at https://www.iana.org/assignments/media-types/application.csv. I am assuming this is a stable URL whose content changes as updates are made. If you want to stay up to date, you'd need to put together a mechanism that is appropriate for your needs.
There is also the mime.types file that comes with Apache which seems to have been derived from the said list.
If like me you wanted to have no hard-coded string in your code you can use something like below
httpHeaders.add(HttpHeaders.CONTENT_TYPE,MediaType.APPLICATION_JSON_VALUE);
which is essentially
httpHeaders.add("Content-Type","application/json");

Best Practice for Saving Images

I am allowing users of the admin panel of my website to upload photos, its a simple process where I check the validity of the image and then save it to a folder, then I also have to record a couple of database records for that image to be able to retrieve it later, my saving function is as follows...
The function that uploads and saves the picture in the folder with a name i construct in another function:
My_HTMLInputFile.PostedFile.SaveAs(HttpContext.Current.Server.MapPath("~/photos\" & pta.FileName))
And the function that creates the database record for that same picture:
Public Function InsertPhoto() As Integer
Dim pta As New GKPTableAdapters.tblPhotosTableAdapter
Return pta.InsertPhoto(PhotoCaption, PhotoDescription, ("http://www.myURL.com/photos/" & FileName), IsDefault, IsPicture)
End Function
Now I know that what I am doing is full of best-practices violations, so please point me out to what I should do, keep in mind that the users might delete the pictures later, so I wanna make sure that I can delete the database and file of the picture, and the whole issue of the path is confusing me :P
Thanks in advance.
Something I've noticed right off the bet is that you are hardcoding the FULL PATH to the image.
I'd just store the image name, and then prepend the relative path when i display it in the application
If you allow your users to delete the files via your application, you should delete the record in the database, and then delete the file itself by using File.Delete method
You may also want to look at your file name generation. If you use an md5 hash of the image data as the file name, for example, you can prevent people from uploading duplicate images and you also don't have to think of a way to generate "unique" names for the images.
Exposing your photos directory directly to the internet may be a bad idea if there are images in there that the public should not see and your naming policy is predictable. People will start guessing image URLs and stumble upon something they are not allowed to see.

Asp.NET / VB.NET: Getting the path from the URL / URI?

Say I have a project that I am deploying at
www.foo.com/path1/default.aspx
and
www.foo.com/path2/default.aspx
What would be the most reliable way to know if I was in the folder "path1", or "path2"? Can I grab that directly, or do I need to split() somehow on the Request.Url.AbsolutePath, or... ?
I just want to change colors, etc. based on which folder the user is in.
Thanks for any assistance!
If you want to code that logic directly into the page, then yeah, I'd go with split() on Request.Url.AbsolutePath.
That said, I'd consider storing this kind of setting in the AppSettings section of web.config. That way if you decide to change the color in path2, you just need to edit the web.config for path2. If you need to add a new path, just deploy there and edit the web.config as appropriate.
Yeah use Request.Url.AbsolutePath.
I do it to create Breadcrumbs, using Split to split the URL, then in your case I suggest to use Switch statement to change color based on the case of the Switch statement
Here is a great article about Paths in ASP.
Check out the MSDN docs on System.IO.Path. It contains a number of useful functions for dealing with path names. You can get GetDirectoryName() or GetFullPath() or GetFileName() or GetFileNameWithoutExtension().

Resources