I'm building an application that generates excel files in asp .net core 2.2.
The excel generation may takes some time depending on the user's needs. (like sometimes, it's up to 20-30s).
My question is : how can I run this generation without blocking user's navigation?
Like, the user could starts the file generation, then continue his navigation on website and come back later to download the generated files. What would be the way to do so?
Run generation in a background task. generate name of the excel file and save the relation either in DB or in tokken (depends on your needs). when the thread will generate excel file update status in db. you can notify user or let user see the info on specific page. there are a lot more ways to do it tho...
Not much a technical, c#-specific question, but more like a UX problem.
You could leave a button the user can click on to request the generation of said files. You run a service that receives such requests, and start processing.
When the service starts the generation, the page simply shows a message saying "Please wait, generating...".
When it finishes, change the page content to a link that allows the user to download it.
In JS you can open a new tab, and you will be processing the excel file in this new tab.
Or, you can create the excel file on the serveur (displaying that its's currently being created), without blocking the navigation, and when your user comes back to the generating page, if a file is found, you can make it downloadable.
Related
I am working on a WPF 4.5 application which needs to interact with PDFs and I am stuck with an issue as described below:
I have template pdfs stored at a specific location. Based on requirement, a copy of the template pdf is created. This pdf has certain fields including text boxes, dropdowns etc. Some of these fields need to be pre-populated like the dropdown values.
Once it is ready, I need to open it, and let the user complete the form. Once completed, the user saves the file and closes it.
Now I need to read the file and send the updated data to the DB. I was able to do all this using iTextSharp by launching the PDF in a separate process and handling the Exited event. Now, the problem I face is this solution does not work if the user uses the SaveAs option to change the name or location of the opened file.
I thought if it would be possible to disable the Save options and add a button on the form clicking which would automatically save the form and close it at the expected location would be a possible solution.
My questions are:
1) Is it possible to find out using the argument of the Exited event handler to find out the saved file name and location? As soon as the user saves the file with a different name, the title of the reader gets updated with the current file name. So I am assuming that the current process is using the latest file.
2) Is it possible to disable the SaveAs and Save file options and close the file on click of a button in the form, using Adobe SDK (JavaScript or plugin or API)?
3) If I use the Adobe SDK, do all the systems on which the application would be installed need to have a licensed version of the Adobe Acrobat?
If the above options are not possible then we would have to settle with dynamic forms. We wanted to experiment with PDF since it is easy to create, and supports image annotations, for which we might need to develop a separate solution, if the above options are not feasible.
I know this is not a very specific programming question, but I need help in order to be able to figure out which path I can go on to be able to achieve the goal.
Please mark duplicate with the link to the other SO question if it a duplicate since I have not been able to figure out one.
Would appreciate answers, links to other posts on SO that are specific to the questions asked.
Please avoid opinion based answers.
Any help would be appreciated.
Any constructive criticism is also welcome.
There is a heavy-handed way to prevent an Acrobat user from Saving a file. In Acrobat, create a Javascript that executes when "Document Will Save." A script like this causes the application to hang rather than Save the file:
var key = "" + this.getField("Password").value;
if (key != "QWERTY") {
app.alert ("No changes to this PDF are allowed,
so you may not Save it.
You will now have to Force Quit or End Task.");
while (true) {};
}
I am not proud of this, but it does the job. You might want to erase the password field before saving.
I am working on a Version Control/File Sync System for Windows. It would be great to have a checkbox at the bottom of the classical save file dialog with the option to check/uncheck for my file versioning.
Is it possible to listen for opened save file dialogs by any program (word etc.) and replace/override that dialog with a customized one (with an additional checkbox)?
If the checkbox is checked, another window should pop-up where the user could enter some additional metadata. After that the data is stored in a local database.
I already worked with the approach by dmihailescu (link provided) but it's very complex and I do not know how to modify that example to listen for opened save file dialogs by other programs.
http://www.codeproject.com/Articles/19566/Extend-OpenFileDialog-and-SaveFileDialog-the-easy?msg=4779306#xx4779306xx
Another approach is to use the FileSystemWatcher but that's very expensive to watch the whole system and it's not very comfortable because the user has to be asked for any created file if he/she wants to version control it.
I hope someone could help me to solve that problem or has some additional tips / approaches.
Thank you.
Edit: Use-case
A user has to write a documentation and creates a new word-doc. When he/she clicks the Save as menu entry of word, my customized save file dialog should pop-up with a checkbox at the bottom, if this file should be versioned or not. If the checkbox is "active" a new window should appear where the user could enter additional metadata. After that the data should be stored in local database.
In my case, only the metadata (like the path etc.) should be stored in the database. Let's suppose a user stores the same file in two different directotries (one file is "older" and one file is the current one). If the user opens an older version of this file, my system should recognize that a "newer" one is already stored in another place and synchronize those files.
That should just be a very easy example.
You have two pieces of functionality: save and version-control. Both of the tasks are actually rather complicated. Therefore you shouldn't mix them. You better off using standard Windows API to save file and do not change that. Think about how you'd support several different Windows releases and how painful that would be.
I assume you have your own UI, and do not integrate with, say, Windows Explorer (like Tortoise Svn or Dropbox). In this case you can do version-control magic first and then just save the end file using standard API.
If you do integrate with Windows Explorer, I suggest you to have a look at Tortoise svn source code.
I have a web form which takes in user information. The value of various text boxes is used to build a html file. I write this html to a file( with specific name) and then prompt user to Save this file.This html is used for creating outlook email signatures. Currently I have this html within the application.This has been deployed to the server. I had to set write permission on this file for all users for it to work.
Are there any security risks? What happens if multiple users access this applications and write to the file at the same time.
When you say the file has "a specific name", do you mean that it is always the same name? If so, then yes, there will be problems if multiple users use this functionality at the same time. They'll be overwriting the one file and downloading each other's data. You would need to generate a unique filename each time the process runs to avoid this.
But do you actually need to save the file?
Or is your goal purely to produce some HTML for the user to download, and the way you are doing this is by writing it to a file, and then prompting them to download that file?
If you don't need to save the file, but rather just need to generate HTML and prompt the user to save, just serve it up as a normal page, and set response headers such that their browser will download it. Something along these lines:
Response.AddHeader("content-disposition", "attachment;filename=my_file.html");
From what I understand, the user fills the web form and submits. Immediately, an html file pops up for download from the server. I think this is very neat implementation of this scenario. You just need to make sure that resources are released properly in order to prevent locking of files.
When multiple users access this application, it should not break since separate files are created with a specific name (as you have mentioned). I don't know what logic has been used to create unique names. At some peculiar situation (this is purely dependent on your name calculation logic) if the calculated specific file name somehow becomes similar to an existing file, you should have code in place to replace or create a different version of the same file name. Locking could occur if you are writing captured data from web form into the same file again and again without disposing your stream/File objects . Make sure you dispose your objects after use in the code.
It would be great if you give access to the application pool of the web application to a user who has write access to that file/folder instead of giving everyone the write access. In this way, your application gets full rights to perform write operations rather than users having rights. If users have write access on the file/folder, it is very easy for anyone to peek in and do something unexpected.
Hope this helps.
I am developing an application in C# ASP.NET to allow users to customise a number of graphics templates with their company logo.
Typically,
User uploads their company logo.
User selects a number of templates (through a HTML form) of different file types for customising.
My web application will accept the user's request, go through each individual item requested and determine its file type. It will then call the appropriate module depending on the file type (e.g. to customise a PDF) and finally insert the logo in the template. These steps are repeated for each file requested.
Once all requested templates for a user are generated, they are grouped together in a zip file and a link for downloading is sent via email.
I would like some advice on how best to accept the user's requests and process the files in ASP.NET.
One way of doing this is to keep the user waiting until all files are generated, therefore until the form handling script would have completed its execution. I reckon this is likely to trigger script timeout errors quite easily for requests that take long to be processed (large number of templates requested or sizable number of concurrent users), and as such is not a very efficient solution.
Another option would be to register the user's request, redirect him/her to another page immediately after (explaining that an email will be sent shortly with a download link), and then proceed to process the files on the server using some background job or similar without the risk of script timeouts. An email is sent when all files for that user are generated.
I am familiar with web application development but this is one of my first forays into .NET development so your help is greatly appreciated.
How can I implement the second option in C#?
It sounds like what you want is a web site which accepts the user input and then passes control to an offline process (such as a Windows Service) to perform the more intensive tasks asynchronously from the site, allowing the user to continue using the site (or go do something else) while processing takes place. Something like this:
User "initiates" a "batch" on the website. Whether it's setting up some values, uploading some kind of batch of things to process, etc. is entirely up to what you're doing. The main point is that the user starts it off.
The necessary information for the process to do its magic is persisted to the database and the user is told that the process has been queued for processing. The user can now go about doing other things.
The back-end application (or multiple applications) polls the database periodically (every minute, every 5 minutes, etc.) or, in the case of an uploaded "batch" file could use something like a FileSystemWatcher, to look for new things to do and does them. Use multi-threading or whatever you need to make that happen, but the main point is that it's an "offline" process that the website isn't waiting on.
When the process completes, some flag is set in the database (on the record being processed, or maybe a "message" record in the user's "inbox" or whatever) indicating that the process is done.
The website UI has some indicator which, any time it's loaded, checks for the aforementioned flag(s) to indicate to the user that a queued process has been completed and is ready to be viewed.
So, essentially, you have a single database accessed by two applications (your web application and your Windows Service (or console app run by a task scheduler, etc.).
Is that basically what you're looking for? I feel like I could be more specific, do you have any specific concerns about the setup?
I've run into a rather sticky situation and I was hoping you all could help. As part of my application, I'm generating a file for my users. Unfortunately, the time it takes to generate this file could be close to 5 minutes. In order to appease my users, I'm showing a message asking them to please wait. Once I have the file generated, I want to return the file to them and clear the message. I'm using the ASP.NET timer to check when the file has finished generating.
My problem comes once the file has finished generating. At the point, I need to do three things:
Pass the file to the user.
Close the message.
Disable the Timer.
My problem comes from the fact that once I've finished writing the file to the response, my postback doesn't finish, so the Viewstate doesn't get updated, so the message and Timer are still there.
Any ideas?
I think you need to break this down into several stages instead of doing all your processing in a single page request. If I were designing this I'd look to do something like this..
User initiates creation of file by clicking some link on your site. This writes some info to a DB table, or otherwise kicks off a process that generates the file.
User is presented with a "please wait" page that can update itself every N seconds.
When file is generated the DB table is updated with the status of "ready".
The "please wait" page refreshes, the job is seen to be complete, the file is now downloaded.
Assuming the "please wait" page uses some identification based upon an authenticated user then this has the benefit of allowing the user to collect their file regardless of whether they get bored and/or accidentally close their browser.
In fact, why not check out these SO posts which cover similar ground...
Handling Long Running Reports
Long-running code within asp.net process
BackgroundWorker thread in ASP.NET
... and there are others (search for "ASP.NET long running")
I've done similar things but without using the timer. Basically I launch a dialog box OnClientClick and then let the server side to it's thing (OnClick). I use the following javascript to handle the postback returning in the OnClientClick:
Dialog.show();
Sys.WebForms.PageRequestManager.getInstance().add_endRequest(
function(sender, args) {
MyDialog.hide();
});
The KISS method is redirecting to a loading page (with loading message etc.) which in turn calls the slow loading resource. The page churns away showing the loading message until the resource is ready. The only downside is that if your resource really does take 5 minutes to generate, the request will time out. If this is the case, #Martin-Peck has a better solution already posted.