save and retrieve values within web app - c#

I have a simple web app built in asp.net webforms c#
where and how would be the best way to save info from the code behind?
(and also retrieve that info)
eg all i want to save is a dateTime. and a flag set to True or False.
and be able to access them in the code behind.
Im not using a db for this web app.
Edit: and can't really use session variables for this purpose.
thanks

If you have to save data for an arbitrary period of time, then you need to store it in a database.

If you need to read the saved variable after a lengthy period of time, you should store it in a local file or a database.
You can create a file using a FileStream object and then write your value to the file.
To get a path where your application has sufficient rights to write a file, use Server.MapPath.
Note : If possible, and if the data you store should not be available to users, you should configure your IIS WebSite to forbid him to serve this file to clients.

Use Application variable like Application["thedate"] = date; and you can get back as date = Application["thedate"].
The date will be saved untill app pool restarts (which also happens when IIS or system restarts).
For a more longer time, save in an xml file on the disk (Use XMLReader and XMLWriter for this purpose).

If this is per user info you could use either browser cookie or viewstate.

Use the Session object:
Session["thedate"] = date;
DateTime date = (DateTime)Session["thedate"];

Related

When listing a Drive folder's changes (via ChangeResource) for the first time, what page token should be used?

Lets say the user already has files synchronized (via my app) to their Drive folder. Now they sign into my app on a second device and is ready to sync files for the first time. Do I use the Changes API for the initial sync process?
I ask because using the Changes API requires a StartPageToken, which requires that there had been a previous sync operation. Well there is no possible way for user to already have a StartPageToken if they are synchronizing data on a device for the first time.
Google's documentation is a joke. They shouldn't leave it up to us to read between the lines and just figure this out. I'm sure I can cook up something that will "work", but how do I ever know that it is the "appropriate" and EFFICIENT way to go about handling this?
public async Task<AccessResult> GetChangesAsync(CancellationToken cancellationToken, string fields = "*")
{
ChangesResource.ListRequest listRequest = new ChangesResource.ListRequest(DriveService, startPageToken)
{
Spaces = Folder_appDataFolder,
Fields = fields + ", nextPageToken",
IncludeRemoved = true,
PageSize = 20
};
ChangeList changeList = await listRequest.ExecuteAsync(cancellationToken);
}
Here, I am looking to start syncing the user's for the first time and so a page token doesn't even make sense for that because during the first sync your goal is to get all of the users data. From then on you are looking to only sync any further changes.
One approach I thought of is to simply use ListRequest to list all of the users data and start downloading files that way. I can then simply request a start page token and store it to be used during sync attempts that occur later...
...But what if during the initial download of the user's files (800 files, for example) an error occurs, and the ListRequest fails on file 423? Because I cannot attain a StartPageToken in the middle of a ListRequest to store in case of emergency, do I have to start all over and download all 800 files again, instead of starting at file 423?
When doing changes.list for the first time you should call getStartPageToken this will return the page token you can use to get the change list. If its the first time then there will be no changes of course.
If the user is using your application from more then one device then the logical course of action would be for you to save the page token in a central location when the user started the application for the first time on the first deceive. This will enable you to use that same token on all additional devices that the user may chose to use.
This could be on your own server or even in the users app data folder on drive
I am not exactly user what your application is doing but i really dont think you should be downloading the users files unless they try to access it. There is no logical reason i can think of for your application to store a mirror image of a users drive account. Access the data they need when they need it. You shouldn't need everything. Again i dont know exactly what your application does.

Save and retrieve connection details in C#

I'm using SQL Server 2008. I need to Enter the connection details through a windows form and save the connection details in a file.
The issue is, I need to use the same credentials for other forms without embedding the credentials in the code. Other forms should retrieve the connection details. In short, once the credentials are saved, other forms should also be able to use them without re-entering the credentials again and again
The question is, How do I do this?
You can accomplish what you're looking for by storing the connection string in your app.config.
You can check out this article on storing custom values in the app.config which would be a good strategy if there are individual values that you want to store and then you want to dynamically build the connection string.
If you prefer to just store and retrieve the complete connection string then you can check out this article.
Varun (I am assuming that you are able to write source code to read and write files using c#) to solve this problem you need to do 2 tasks in the form load event.
Check if the file containing your login credentials already exists at your desired location then read the file and fill the relevant details in the text boxes accordingly.
If the file does not exists then create the new file at a specific location of your choice with credential details.
So whenever the user opens the login form it's form_load() method will work accordingly based on above two conditions.
Apart from this, if you don't want to do this you can use your app.config file for the same job.

Server.MapPath Access is denied On Azure

I am exporting an excel using c# code and spreadsheetlight dll.
I am trying to insert a picture into excel, everything works well on local machine but on live web site it gives following error
Access to the path 'F:\sitesroot\0\Images\Logo.png' is denied
My c# code.
string filePath = Server.MapPath("~/Images/Logo.png");
SLPicture pic = new SLPicture(filePath); //SLPicture - An inbuilt class for inserting image
Currently what I am doing is manually providing access rights on IIS server but which is not the correct way to go since each time I upload the service I have to redo that again and again
Any expert advice - How I can provide access right through code?
Or How to get rid of this error.
Thanks.
Assuming you are using Cloud services...
You are supposed to use Local Storage for this (http://msdn.microsoft.com/en-us/library/windowsazure/ee758708.aspx).
Basically;
In your Cloud project, go to the properties for the Role and select Local Storage.
Add a new local storage and give it a name, i.e. "foo" and a maximum size. If this is for temporary processing rather than caching, you probably want to tick "Clean on role recycle".
In your code call RoleEnvironment.GetLocalResource("foo") to get the folder name you can use and then do something like Path.Combine("path","Logo.png") to get a file name which you can then write to.

Saving setting to a exe

I have a program which I want to store information in a string. I have been using the Properties.Setting.Default.STRINGname to store the information, which works fine on my PC, and I can see the saved strings (when I go to the settings in the application). But when I take the application to a new PC it losses the strings. Is there a way to be able to edit this information and save it in the app? So basically I need to be able to convert the user setting to application setting, but after the runtime.
var settings = Properties.Settings.Default;
settings.H1 = textbox1.text;
settings.H2 = textbox2.text;
settings.Save();
MSDN explicit says something about this:
Settings that are application-scoped are read-only, and can only be changed at design time or by altering the .config file in between application sessions. Settings that are user-scoped, however, can be written at run time just as you would change any property value. The new value persists for the duration of the application session. You can persist the changes to the settings between application sessions by calling the Save method.
For this, Application setting will never work for you. However, if you are using a User scoped settings it does work, but soon you change the application from one computer to another (as you say you want to) you will loose the settings as that's another machine (another user-scope)...
There are way to continue to have the same settings, you can do, at least 2 things:
use a .config file to save the settings (it's an XML file)
use a service to host the settings and you can read if user has internet access
What you can't do is
using only one executable file, save the settings from computer to computer.
User settings are compiled differently than Application settings, and thus cannot be converted after compilation. Why not compile with Application Settings?
The code you are using should save the user settings. Rememeber that user settings will be saved in the user's data folder. Not in the configuration file where the app was installed (say program files). This is the usual path:
<Profile Directory>\<Company Name>\<App Name>_<Evidence Type>_<Evidence Hash>\<Version>\user.config
See this links form more information

How can I overwrite/update a file that is currently being served by IIS?

The problem:
My company puts out a monthly newsletter which I host on our internal website. I have a page for the author of the newsletter to upload the latest version. Once the author has uploaded the latest newsletter, he sends a broadcast email to announce the new newsletter. Employees invariably check the new newsletter and send feedback to the author with corrections that need to be made.
Once the author has made the necessary corrections (typically within an hour of sending the broadcast email), he revisits my page and replaces the latest version with the updated newsletter.
Immediately following the replacement (or update, if you will) of the newsletter, anyone attempting to access it gets a 500 - Internal Server Error.
My IT guy who maintains the server cannot delete/rename/move the file because of a permissions error and has to do a lot of convoluted things to get the file deleted (and once the file is deleted, the author of the newsletter can re-upload the corrected copy and it works fine.
My IT guy and I are pretty sure that the problem stems from that I'm trying to replace the file while IIS is actively serving it to users (which I thought of and thought that I had coded against happening).
The code that runs the replacement is as follows:
Protected Sub ReplaceLatestNewsletter()
Dim dr As DataRow
Dim sFile As String
Dim mFileLock As Mutex
Try
If Me.Archives.Rows.Count > 0 Then
dr = Me.Archives.Rows(0)
sFile = dr("File").ToString
If dr("Path").ToString.Length > 0 Then
mFileLock = New Mutex(True, "MyMutexToPreventReadsOnOverwrite")
Try
mFileLock.WaitOne()
System.IO.File.Delete(dr("Path").ToString)
Catch ex As Exception
lblErrs.Text = ex.ToString
Finally
mFileLock.ReleaseMutex()
End Try
End If
fuNewsletter.PostedFile.SaveAs(Server.MapPath("~/Newsletter/archives/" & sFile))
End If
Catch ex As Exception
lblErrs.Text = ex.ToString
End Try
dr = Nothing
sFile = Nothing
mFileLock = Nothing
End Sub
I thought the Mutex would take care of this (although after re-reading documentation I'm not sure I can actually use it like I'm trying to). Other comments on the code above:
Me.Archives is a DataTable stored in ViewState
dr("File").ToString is the filename (no path)
dr("Path").ToString is the full local machine path and filename (i.e., 'C:\App_Root\Newsletters\archives\20120214.pdf')
The filenames of the newsletters are set to "YYYYMMDD.pdf" where YYYYMMDD is the date (formatted) of the upload.
In any case, I'm pretty sure that the code above is not establishing an exclusive lock on the file so that the file can be overwritten safely.
Ultimately, I would like to make sure that the following happens:
If IIS is currently serving the file, wait until IIS has finished serving it.
Before IIS can serve the file again, establish an exclusive lock on the file so that no other process, thread, user (etc.) can read from or write to the file.
Either delete the file entirely and write a new file to replace it or overwrite the existing file with the new content.
Remove the exclusive lock so that users can access the file again.
Suggestions?
Also, can I use a Mutex to get a mutually exclusive lock on a file in the Windows filesystem?
Thank you in advance for your assistance and advice.
EDIT:
The way that the links for the newsletter are generated is based on the physical filename. The method used is:
Get all PDF files in the "archives" directory. For each file:
Parse the date of publication from the filename.
Store the date, the path to the file, the filename, and a URL to each file in a DataRow in a DataTable
Sort the DataTable by date (descending).
Output the first row as the current issue.
Output all subsequent rows as "archives" organized by year and month.
UPDATE:
In lieu of not being able to discern when all existing requests for that file have completed, I took a closer look at the first part of #Justin's answer ("your mutex will only have an effect if the process that reads from the file also obtains the same mutex.")
This led me to Configure IIS7 to server static content through ASP.NET Runtime and the linked article in the accepted answer.
To that end, I have implemented a handler for all PDF files which implements New Mutex(True, "MyMutexToPreventReadsOnOverwrite") to ensure that only one thread is doing something with the PDF at any given time.
Thank you for you answer, #Justin. While I did not wind up using the implementation you suggested, your answer pointed me towards an acceptable solution.
Your mutex will only have an effect if the process that reads from the file also obtains the same mutex. What is the method used to serve up the file? Is ASP.Net used or is this just a static file?
My workflow would be a little different:
Write the new newsletter to a new file
Have IIS start serving up the new file instead of the old one for the given Newsletter url
Delete the old file once all existing requests for that file have completed
This requires no locking and also means that we don't need to wait for requests for the current file be completed (something which could potentially take an indefinite amount of time if people keep on making new requests). The only interesting bit is step 2 which will depend on how the file is served - the easiest way would probably be to either set up a HTTP redirect or use URL rewriting
HTTP Redirect
A HTTP Redirect is where the server tells the client to look in a different place when it gets a request for a given resource so that the browser URL is automatically updated to match the new location. For example if the user requested http://server/20120221.pdf then they could be automatically redirected to another URL such as http://server/20120221_v2.pdf (the URL shown in the browser would change however the URL they need to type in would not).
You can do this in IIS 7 using the httpRedirect configuration element, for example:
<configuration>
<system.webServer>
<httpRedirect enabled="true" exactDestination="true" httpResponseStatus="Found">
<!-- Note that I needed to add a * in for IIS to accept the wildcard even though it isn't used in this case -->
<add wildcard="*20120221.pdf" destination="20120221_v2.pdf" />
</httpRedirect>
</system.webServer>
</configuration>
The linked page shows how to change these settings from ASP.Net
Url Rewriting
Alternatively IIS can be set up to automatically serve up the content of a different file for a given URL without the client (the browser) ever knowing the difference. This is called URL rewriting and can be done in IIS using something like this however it does require that additional components be installed to IIS to work.
Using a HTTP Redirect is probably the easiest method.

Categories