I am developing a Windows Service that submits some data to a web api. As Part of this I need to submit a GUID that I am generating with
Guid.NewGuid():
This GUID would be individual per machine, never change, and be the same for all users who log in. I'm struggling with where to actually store this though. I came across the Properties.Setting which seemed perfect, but if I scope to Application instead of User, it won't let me set the property as it is read only.
How and where do I store the GUID? It will only generate once (when the service starts on a PC for the first time).
In your case, you can use the ConfigurationManager Class in order to access and write the GUID in your application setting. From the link above example:
static void AddUpdateAppSettings(string key, string value)
{
try
{
var configFile = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
var settings = configFile.AppSettings.Settings;
if (settings[key] == null)
{
settings.Add(key, value);
}
else
{
settings[key].Value = value;
}
configFile.Save(ConfigurationSaveMode.Modified);
ConfigurationManager.RefreshSection(configFile.AppSettings.SectionInformation.Name);
}
catch (ConfigurationErrorsException)
{
Console.WriteLine("Error writing app settings");
}
}
you can use it like:
AddUpdateAppSettings("MachineGuid", Guid.NewGuid().ToString());
Related
In short:
I have a C# console app which i used to test and write data from SQL to SharePoint lists.
Everything works fine while it is ran as console app. I get the connection towards SQL, context is created, then I connect to SharePoint site and proceed with update of certain fields.
Now, when I deploy working solution as a timerjob (a .wsp) for sharepoint, and when I update it to the server farm and deploy it as feature to the site, and run it as a timerjob, it does work, but only, so to speak "once".
When I run that timer job, it recives SQL context, connects, and updates SharePoint lists. But when I change data in a SQL table (eg. a field called "price" from 10.99 to 11.99), and run timerjob again, it still only updates the "old" data, to be exact, the 10.99 value.
Now when doing this with console app .exe, on the server, no matter how many db changes I perform, it always updates the newest data, but as a timerJob it seems like it "hanges" onto previous context connection, and updates previous data only.
Do I need to specify, in the code, to drop context after the timerjob has ended it's run, so it can call the same but "fresh" context on the next run.
Here is inital code in the .wsp
class TimerJobPromoToolsDefinition : SPJobDefinition
{
public TimerJobPromoToolsDefinition() : base()
{
}
public TimerJobPromoToolsDefinition(string jobName, SPService service) : base(jobName, service, null, SPJobLockType.None)
{
this.Title = "PromoTools_Timer_Job";
}
public TimerJobPromoToolsDefinition(string jobName, SPWebApplication webapp) : base(jobName, webapp, null, SPJobLockType.ContentDatabase)
{
this.Title = "PromoTools_Timer_Job";
}
public override void Execute(Guid targetInstanceId)
{
System.Diagnostics.Trace.Assert(false);
Main();
}
private static TimerJobConnection _context;
public static void Main()
{
PrintInitializing();
_context = new TimerJobConnection();
string siteURL = "http://somesite.com/";
try
{
using (SPSite site = new SPSite(siteURL))
{
using (SPWeb web = site.OpenWeb())
{
var catalogs = GetArtikliFromPromoTools(web);
var articlesFiltered = GetArtikliFromDB(catalogs);
PrintFinishedLoadingArticles();
GetSharePointCatalogHeaders(web);
UpdateArticles(catalogs, articlesFiltered, web);
PrintEndOfOperation();
Console.WriteLine("Press any key to continue...");
}
}
}
catch (Exception)
{
PrintErrorSharepointConnection();
PrintPressKeyToExit();
}
finally
{
}
}
I think the "context" should not the issue based on my experience.
As you catched the exception, try to check is any exception, You could try to debug the code by attaching to owstimer process also.
I have the following code that creates a band profile:
var bandProfile = _profileService.CreateBandProfile(model.BandProfile, file, UserId);
if (bandProfile != null)
{
userManager.AddToRole(UserId, "Band");
//Store the bandprofile ID anywhere?
return RedirectToAction("Index", "Welcome");
}
No I want to store and make the bandprofile ID accessible through the application. Keep It accessible while the user is logged in with the profile.
How can I accomplish this?
For example, to get the userId, you can do like this through the application:
UserId = System.Web.HttpContext.Current.User.Identity.GetUserId();
I want to do the same thing, but with bandprofileId.
There is some debate as to the "correctness" of doing so (linked below), but you can store the variable in HttpContext.Current.Application["BandProfile"].
if (bandProfile != null)
{
userManager.AddToRole(UserId, "Band");
//Store the bandprofile ID anywhere?
HttpContext.Current.Application["BandProfile"] = bandProfile;
return RedirectToAction("Index", "Welcome");
}
Alternatively, you can use a static variable in a class somewhere.
public static class BandProfile
{
public static whatever Profile;
}
if (bandProfile != null)
{
userManager.AddToRole(UserId, "Band");
//Store the bandprofile ID anywhere?
BandProfile.Profile = bandProfile;
return RedirectToAction("Index", "Welcome");
}
Here is a related question that deals with the same issue, and here is another.
EDIT:
To then access these variables, you can use
var bandProfile = HttpContext.Current.Application["BandProfile"];
or
var bandProfile = BandProfile.Profile;
According to Microsoft:
ASP.NET includes application state primarily for compatibility with classic ASP so that it is easier to migrate existing applications to ASP.NET. It is recommended that you store data in static members of the application class instead of in the Application object.
That said, you should use the static variable method. Static variables are available by calling ClassName.Variable and will exist for the duration of the app running. If the app is closed or the variable is otherwise changed, you will lose this information.
In order to save the information, it's necessary to write the contents of this variable to an external source (DB, file, etc.) and read it in when the app starts.
I have a Web service for creating user session basically its a login web service. This web service basically creates a session key so that for every web service that i need to access is I need to attach this Session ID in my header, my question is where is the good place to store this session ID, I'm basically newbie in mobile development that has session id, not like web applications, browser have cookies and sessions, but how about in mobile application? Is it okay to save it in SQLite database? or there's other way to store this session ID? So that even though the user close the app and reopens it, the session will restore.
by the way, I'm using xamarin to create my mobile applications, I'm actually thinking if there's a storage that I can use to store and restore my session id in both iOS and android.
Thanks
I would suggest creating a private SharedPreferences for your App, and holding the value there. But then i would also suggest having the session expire every so often so that if the users phone was stolen, they would not be able to log in to your application and get information assuming that the expiration time was reached.
To save to shared preferences:
// create a String for the SharedPreferences
private static final String PREFS = "MyAppsPrivatePrefs";
private static final String SESS_KEY = "Session";
private String session = "";
// then access preferences
SharedPreferences sharedPrefs = getSharedPreferences(PREFS, Context.MODE_PRIVATE);
// Open preferences for editting
SharedPreferences.Editor editor = sharedPrefs.edit();
editor.putString(SESSION, session);
editor.commit();
This should work but again I would suggest adding logic to clear this if some time has passed...
You can work with SharedPreferences.
http://developer.android.com/reference/android/content/SharedPreferences.html
The preferences will be removed only if the user clear the cache!
If you are using android (not Xamarin) then Use SharedPreferences classes in android and set your user session and get user session.I written code as. First Create SharedPreferences class named DataStore as
package com.example.examplesharedpreferenced.utils;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
public class DataStore {
private static final String PREF_NAME = "com.example.examplesharedpreferenced.pref";
public static final String KEY_SESSION = "key_session";
public static void setUserSession(Context context, String session) {
SharedPreferences sharedPreferences = context.getSharedPreferences(
PREF_NAME, Context.MODE_PRIVATE);
Editor editor = sharedPreferences.edit();
editor.putString(KEY_SESSION, session);
editor.commit();
}
public static String getUserSession(Context context) {
SharedPreferences sharedPreferences = context.getSharedPreferences(
PREF_NAME, Context.MODE_PRIVATE);
return sharedPreferences.getString(KEY_SESSION, null);
}
}
Then use theses above methods in Main Activity like
package com.example.examplesharedpreferenced;
import com.example.examplesharedpreferenced.utils.DataStore;
import android.support.v7.app.ActionBarActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
public class MainActivity extends ActionBarActivity {
private static final String TAG = MainActivity.class.getSimpleName();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//get user session
String userSession = DataStore.getUserSession(MainActivity.this);
Log.d(TAG, "userSession : "+userSession);
//setting user session
DataStore.setUserSession(MainActivity.this, "abc345asd");
//get user session after setting it.
String userSessionAfter = DataStore.getUserSession(MainActivity.this);
Log.d(TAG, "userSessionAfter : "+userSessionAfter);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
}
For Xamarin you should follow link
A program that I am currently working on collects and exports data to a SQL database. If there is a failure in the database, I have coded so that it will write the data to a CSV file. It is going to be an application that is always running with a config file that the user can change info (Such as Database connection) while the process is running. I'm having the problem of once I get into a loop of writing to a CSV file, I cannot get back to putting the data in a database until the application is restarted. Here is the relevant code:
class MethodClass
{
public static void Method()
{
while (true)
{
ConfigurationManager.RefreshSection("appSettings");
//Normally Running Code that Generates the Data
//Tries to write data to database 3 times
if (dbWrite != 2 && dbWrite != 3)
{
dbWrite = 0;
}
while (dbWrite < 2)
{
try
{
db.TblData.InsertOnSubmit(newrecord);
db.SubmitChanges();
break;
}
catch
{
dbWrite++;
}
}
if (dbWrite == 2)
{
try
{
db.TblData.InsertOnSubmit(newrecord);
db.SubmitChanges();
}
catch (Exception e)
{
dbWrite++;
log.Warn("Database Write Error", e);
BackupMethod();
}
}
if (dbWrite == 3)
{
try
{
db.TblData.InsertOnSubmit(newrecord);
db.SubmitChanges();
dbWrite = 0;
}
catch
{
BackupMethod();
log.Info("Still not writing to Database");
}
}
}
}
Class ConfigVariables
{
public static string SqlUser = ConfigurationManager.appSettings["SqlUser"];
//Other Config Variables
}
For reference, I just checked and the issue seems to be with getting the info from my Config file while the program is running. If I change other values in the config file, they have no effect until the next time that the program is run. Just so people know, I am editing the App.exe.config file in the Debug/Release folder.
UPDATE: It seems that if I assign the variable after RefreshSection();, that it will work. However, I put the variables in a separate class for a reason. Is there a better way to do this?
I was able to fix the issue by creating a method in my ConfigVariables class that refreshed and reassigned the variables in a while loop on a separate thread. This allowed me to keep my variables organized in another class and not change anything with referencing them in the my code. Now I just have to do some performance testing; hopefully constantly doing this won't cause performance issues.
In my application I want to do something like:
SomeApiClient apiClient = new SomeApiClient();
List<User> apiClient.getUsers();
In my web.config, I will a few configuration key/value pairs.
How can I write the constructor of SomeApiClient in such a way that it loads the values from the web.config, but not each time, only once when the application starts or first request?
Here ya go.
namespace dm2
{
using System.Collections.Specialized;
using System.Configuration;
public class SomeApiClient
{
internal static NameValueCollection Config
{
get
{
if (config == null) config = ConfigurationManager.AppSettings;
return config;
}
}
internal static NameValueCollection config;
}
}
Basically you just use a static property in a non static class...so in order to get your config settings,
public void DoFunConfigStuff()
{
for (var i = 0; i < Config.Count;i++ )
{
Console.WriteLine("[{0}]: {1}",Config.Keys[i] ,Config[i]);
}
}
Since you mentioned web.config, I'm assuming this is a web app. So I'd like to point out that you should expect that your app pool could be recycled at any time, at which point this would cause the static getter to reevaluate and load new settings. It's best not to reply on this.
One thing you could do is serialize this info to some medium, be it disk or database, and then have some kind of db switch, or webpage that will force a reload.
So in that getter it would check for the serialized data, if it doesn't exist, check web.config, and then save that data somewhere. Next time it gets recycled it will then pick up the old data. Really depends on your setup I suppose.