Clearing MongoDb keys on IIS website - c#

New to IIS and Mongo, and I'm trying to find a way to clear the keys from my server to avoid an "item with the same key has already been added" exception.
IMongoDatabase _db;
IMongoCollection<BoardStorageItem> _boardsCollection;
public MongoDb()
{
var client = new MongoClient("mongodb://localhost");
_db = client.GetDatabase("KanbanDemonstration");
BsonClassMap.RegisterClassMap<CardStorageItem>();
BsonClassMap.RegisterClassMap<ColumnStorageItem>();
BsonClassMap.RegisterClassMap<BoardStorageItem>();
BsonClassMap.RegisterClassMap<EmployeeStorageItem>();
_boardsCollection = _db.GetCollection<BoardStorageItem>("Board");
}
public BoardStorageItem GetBoardByName(string name)
{
var board = _boardsCollection.AsQueryable().FirstOrDefault(b => b.Name == name);
return board;
}
public class MongoConverter
{
MongoDb _mongoDb;
public MongoConverter()
{
_mongoDb = new MongoDb();
}
public BoardStorageItem GetBoardByName(string name)
{
return _mongoDb.GetBoardByName(name);
}
}
and then for the code on the web page itself
protected void Button1_Click(object sender, EventArgs e)
{
_mongoConverter = new MongoConverter();
var board = _mongoConverter.GetBoardByName(TextBox1.Text);
BoardName = board.Name;
BoardId = board.Id;
Label3.Text = BoardName;
Label4.Text = BoardId;
Session.Clear();
}
This works perfectly this first time I use the button to get a board, but if I try a second time, I get an exception "item with the same key has already been added" when attempting to new up MongoConverter. I had thought that clearing the session after would clear out the keys as well, but the only thing that seems to work is resetting the server itself.

Calling BsonClassMap.RegisterClassMap<T>() should only be done once per type. And it should be done at application startup, before opening any database connections according to the documentation.
Since you're in ASP.NET, put this in your Application_Start event in your global application class (global.asax)
void Application_Start(object sender, EventArgs e)
{
BsonClassMap.RegisterClassMap<CardStorageItem>();
BsonClassMap.RegisterClassMap<ColumnStorageItem>();
BsonClassMap.RegisterClassMap<BoardStorageItem>();
BsonClassMap.RegisterClassMap<EmployeeStorageItem>();
}
You can make another method that calls it so you don't pollute your global application class if you want. And of course, remove the registrations from your constructor.

Related

Pass data from one form to another (datagridview)

I'm working on some easy log implementation. I've created some datagridview in Changelog.cs that has columns: user's ID, surname, action name ("authorization", for example), time.
(ex: 16, Brown, authorization, 10:30:00)
So I've got 2 forms: Authorization and Changelog
When user presses the button 'sign in' in Authorization form, I want to insert this data to datagridview in Changelog.
In Changelog I've got this constructor:
public Changelog(string id, string user, string operation, string date)
{
InitializeComponent();
dataGridView1.Rows[0].Cells[0].Value = id;
dataGridView1.Rows[0].Cells[1].Value = user;
dataGridView1.Rows[0].Cells[2].Value = operation;
dataGridView1.Rows[0].Cells[3].Value = date;
}
And in Authorization I've got this:
private void button1_Click(object sender, EventArgs e)
{
DateTime whenClicked = DateTime.Now;
// long authorization code
}
Doing in Authorization:
Changelog cl = new Changelog(currentUser.Id.ToString(), currentUser.Name, "authorization", whenClicked.ToString())
of course creates a new instance of Changelog, but I want to insert this data to the original one
Is there any way to implement this? Thank you!
Since Steve's answer doesn't seem to be working (quite to my surprise), maybe this will help you: The basic idea is using events, and static events at that.
So, in your Authorization Form, you'd declare an event like this:
public static event EventHandler<ActionLogEventArgs> AuthorizationEvent;
// ^^ `ActionLogEventArgs` are `EventArgs` + your id, user, operation ... props
// Trigger function
protected virtual void OnAuthorization( ActionLogEventArgs args )
{
var handler = AuthorizationEvent;
handler?.Invoke(null, args);
}
So, whenever "sign-in" is clicked, you build your ActionLogEventArgs and fire the event by calling OnAuthorization(args)
In your "Changelog" Form you register a handler for that event:
// in ctor:
Authorization.AuthorizationEvent += AddLog;
// ...
private void AddLog(object sender, ActionLogEventArgs e)
{
// Add to your DataGrid; make sure this executes on UI Thread.
}
Mind that I chose to use a static event to avoid having to have an instance.
I'd usually prefer non-static events but that would require some more effort.
Let's see if this could work for you, first.
On DataGridView
What also came to my mind was:
You might want to actually insert a new Row.
grid.Rows[0].Cells[x].Value = ... will change that row, not insert a new one.
You can retrieve the existin instance of a Form looking at the Application.OpenForms property, then use the instance present in that collection to send the new information.
But to do this you need some changes both in Changelog and Authorization.
First remove the parameters passed to Changelog constructor and create a new method that add the info to the DataGridView. So you can call this method independently from the form creation.
public Changelog()
{
InitializeComponent();
}
public void AddNewLog(string id, string user, string operation, string date)
{
dataGridView1.Rows[0].Cells[0].Value = id;
dataGridView1.Rows[0].Cells[1].Value = user;
dataGridView1.Rows[0].Cells[2].Value = operation;
dataGridView1.Rows[0].Cells[3].Value = date;
}
Now in Authorization search for the existing Changelog instance and use that instance and the AddNewLog method to add the information. Of course, if the Changelog instance is not present you can create it as before (but without passing the parameters).
private void button1_Click(object sender, EventArgs e)
{
DateTime whenClicked = DateTime.Now;
// long authorization code
Changelog cl = Application.OpenForms["Changelog"] as Changelog;
if(cl == null)
cl = new Changelog();
cl.AddNewLog(currentUser.Id.ToString(), currentUser.Name, "authorization", whenClicked.ToString());

List.Add reset on asp.net

I try to add dynamically items in a List<> class in asp.net. On Winforms it works but on ASP.NET it doesn't.
This is my code.
class artikuj
{
public int artId { get; set; }
public double sasia { get; set; }
}
List<artikuj> art = new List<artikuj>();
protected void btn_Click(object sender, EventArgs e)
{
try
{
art.Add(new artikuj
{
artId = int.Parse(DropDownListArikujt.SelectedValue),
sasia = double.Parse(tbSasia.Text)
});
Label1.Text = art.Count.ToString();
}
catch(Exception ex)
{
Response.Write(ex);
}
}
Every time I press the button the list resets and the new item is added.
Any idea why this error occurs? I tried and tried but no success. :/
This is one of the first things that trip people over who are used to writing desktop apps and go over to creating web apps. It looks like all the coding should be the same, but the first thing you learn - ASP.NET is stateless.
That means that every time a new request comes in to your page, a new instance of the page is created, and along with it your instance-held list of items.
There are many ways to maintain state between requests with ASP.NET, but they are to expansive and broad to put into an answer. You could start by looking at Getting started with ASP.NET

.NET DataSet not updating with new row

I am trying to add a new typed row in a DataTable and update it to the source but its not working
public partial class JobTableAdapter
{
public OpenMassSenderCore.OpenMassSenderDBDataSet.JobRow getNewRow()
{
return OpenMassSenderDBDataSet.getInstance().Job.NewJobRow();
}
public void submitRow(OpenMassSenderCore.OpenMassSenderDBDataSet.JobRow row)
{
OpenMassSenderDBDataSet.getInstance().Job.Rows.Add(row);
OpenMassSenderDBDataSet.getInstance().Job.AcceptChanges();
Update(OpenMassSenderDBDataSet.getInstance().Job);//thats the default tableadapter's update
}
private static JobTableAdapter instance;
public static JobTableAdapter getInstance()
{
if (instance == null) instance = new JobTableAdapter();
return instance;
}
}
private void button1_Click(object sender, EventArgs e)
{
OpenMassSenderCore.OpenMassSenderDBDataSet.JobRow job=JobTableAdapter.getInstance().getNewRow();
job.ID = 2;
job.query = "";
job.group = "smaplist1";
job.sender_account = 1;
job.status = OpenMassSenderCore.OpenMassSenderDBDataSet.JobRow.JobStatus.PENDING;
job.user = 1;
job.message =1;
JobTableAdapter.getInstance().submitRow(job);
}
If I press the button twice I get the key(ID) existing exception so this part works ok, the only problem is that its not updating the database(access)
Well, duh, you called AcceptChanges.
You basically said "Ok, this data is now committed, everything is fine. By the way, DataAdapter, can you commit all the changes on this dataset to the database? Thanks." "Sure, let me see... okay, your data set has no changes, so I'm done". You've thrown away the only information the data adapter can use to actually update the database :)
(As a side note - please, don't write Java in C#. It hurts. And DataSets are an ancient technology that wasn't updated in years, you might want to find something a bit more uptodate.)

Reload Data every time I navigate to Page

I have this Windows Phone Page where I load data through the standard ViewModel scope.
public Profile()
{
InitializeComponent();
App.PersonalizedViewModel.favorites.Clear();
DataContext = App.PersonalizedViewModel;
this.Loaded += new RoutedEventHandler(MainPage_Loaded);
}
private void MainPage_Loaded(object sender, RoutedEventArgs e)
{
if (!App.PersonalizedViewModel.IsDataLoaded)
{
App.PersonalizedViewModel.LoadData();
}
}
This works fine. However when I navigate to this page from some other page the data is still the same. I mean the LoadData() method should recheck updated data right? Please suggest.
EDIT:
My PersonalizedViewModelClass:
public class PersonalizationViewModel: INotifyPropertyChanged
{
public PersonalizationViewModel()
{
this.favorites = new ObservableCollection<ItemViewModel>();
this.Bar = new ObservableCollection<Bars>();
}
public ObservableCollection<ItemViewModel> favorites { get; private set; }
public ObservableCollection<Bars> Bar { get; private set; }
private string _sampleProperty = "Sample Runtime Property Value";
public string SampleProperty
{
get
{
return _sampleProperty;
}
set
{
if (value != _sampleProperty)
{
_sampleProperty = value;
NotifyPropertyChanged("SampleProperty");
}
}
}
public bool IsDataLoaded
{
get;
private set;
}
/// <summary>
/// Creates and adds a few ItemViewModel objects into the Items collection.
/// </summary>
public async void LoadData()
{
favorites.Clear();
try
{
var query = ParseObject.GetQuery("Favorite")
.WhereEqualTo("user", ParseUser.CurrentUser.Username);
IEnumerable<ParseObject> results = await query.FindAsync();
this.favorites.Clear();
foreach (ParseObject result in results)
{
string venue = result.Get<string>("venue");
string address = result.Get<string>("address");
string likes = result.Get<string>("likes");
string price = result.Get<string>("price");
string contact = result.Get<string>("contact");
this.favorites.Add(new ItemViewModel { LineOne=venue, LineTwo=address, LineThree=likes, Rating="", Hours="", Contact=contact, Price=price, Latitude="", Longitude="" });
}
if (favorites.Count == 0)
{
// emailPanorama.DefaultItem = emailPanorama.Items[1];
MessageBox.Show("You do not have any saved cafes. Long press a cafe in main menu to save it.");
}
}
catch (Exception exc)
{
MessageBox.Show("Data could not be fetched!", "Error", MessageBoxButton.OK);
}
}
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged(String propertyName)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (null != handler)
{
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
}
Implementation of PersonalizedViewModel:
protected async override void OnNavigatedTo(NavigationEventArgs e)
{
base.OnNavigatedTo(e);
await App.PersonalizedViewModel.LoadData();
user_tb.Text = ParseUser.CurrentUser.Username;
if (NavigationContext.QueryString.ContainsKey("item"))
{
var index = NavigationContext.QueryString["item"];
var indexParsed = int.Parse(index);
mypivot.SelectedIndex = indexParsed;
}
if (NavigationService.BackStack.Any())
{
var length = NavigationService.BackStack.Count() - 1;
var i = 0;
while (i < length)
{
NavigationService.RemoveBackEntry();
i++;
}
}
}
I don't see the problem, however, I think you need to narrow in on the problem.
First off, you are calling LoadData from 2 places. 1 from MainPage_Load and 1 from OnNavigatedTo. In MainPage_Load it is conditional and in OnNavigatedTo it is always being called. I suggest that you get to a single path through the code instead of 2 so that you don't get different experiences. I personally recommend (without knowing all the details) that you call load data from OnNavigatedTo instead of MainPage_Load. If you want to do it conditionally that is fine but if you are loading the data from memory, it really is unnecessary as you won't improve performance anymore than a few milliseconds. Also, if you are not loading from memory, you may not want to load it conditionally because the underlying data may have changed. In either case, the choice to load data or not should be moved out of the view and into the data layer (but that is for another post).
Once you have a single path chosen (i.e. calling LoadData from MainPage_Load or OnNavigatedTo) you should use your debugger. Put a break point in LoadData method and if it is being called appropriately, then your problem is more specific than your posted question. Here are some questions to think about (you may want to start from the last question and work your way backward)
Questions:
Is LoadData being called appropriately?
Does ParseObject have the correct data?
Is the ParseUser...UserName set properly?
Is the foreach being executed the proper # of times (i.e. does the result of your query have the right # of items?)
Couple Code Tips completely unrelated to this problem:
Single Path through code. Don't call LoadData from more than one place.
Don't call favorites.clear() twice in the same method. (it is called twice in LoadData)
Consistent naming. favorites is lowercase but Bar is upper case.
User proper data types. On your ItemViewModel you have Hours, Latitude, and Longitude. You have them as strings. These clearly are not strings. Also, you should not set them to empty. Empty means they have been set to a value. Emtpy is a valid value. Null means not set. To keep your objects clean and accurate you want to be accurate in how you set things and then deal appropriately with the impact. If you really really want them to be initialized to empty strings, then at least do it in the constructor of ItemViewModel so that every caller doesn't have to know how to initialize every property. I guarantee this is leading to buggy code if you continue using this practice.
Please take the comments as constructive criticism not criticism. I know many people don't like to hear these things but the teams I lead write bugs until they start following these types of guidelines.
Good luck,
Tom
Instead of defining this
App.PersonalizedViewModel.favorites.Clear();
DataContext = App.PersonalizedViewModel;
this.Loaded += new RoutedEventHandler(MainPage_Loaded);
into constructor i.e. Profile I would suggest remove this code from Constructor and add it into your OnNavigatedTo. so the data will load after navigation
Your OnNavigatedTo Method looks like follows
protected async override void OnNavigatedTo(NavigationEventArgs e)
{
base.OnNavigatedTo(e);
App.PersonalizedViewModel.favorites.Clear();
DataContext = App.PersonalizedViewModel;
this.Loaded += new RoutedEventHandler(MainPage_Loaded);
}
Might be your problem will solve.
Edit
Try this query
var results = (from find in ParseObject.GetQuery("Favorite").WhereEqualTo("user", ParseUser.CurrentUser.Username) select find);
Tried this:
var query = from favorite in ParseObject.GetQuery("Favorite")
where favorite.Get<string>("user") == ParseUser.CurrentUser.Username
select favorite;
IEnumerable<ParseObject> results = await query.FindAsync();
I had a similar Problem.All u want to do here is generate a new instance of the Page.U can do this in two Ways.
One Way is by forcing a GUID along with Page Navigation URI that will create a New Instance of the Page and your Load Data() will work.
NavigationService.Navigate(new Uri(String.Format("/MainPage.xaml?item={0}", Guid.NewGuid().ToString()), UriKind.RelativeOrAbsolute));
The Second Way to implement that Part of your Page in a User Control .Like create a User Control for Load Data() and put it in constructor.It will generate a new Instance everytime you load the Page.
If the problem persists in the front end,you can try this.
1.have you mentioned the below attribute in your xaml page?
<UserControl Loaded="MainPage_Loaded">
So that every time the page loads the data will get loaded on to the page.
2.The data must exist, if you have no problem in the code behind as it is a WPF application and not a web page.
Hope you find it useful.
Two changes required..
Remove the this.Loaded from OnNavigatedTo. That may not be required.
Second move the LoadData to OnNavigatedTo method
protected async override void OnNavigatedTo(NavigationEventArgs e)
{
base.OnNavigatedTo(e);
App.PersonalizedViewModel.favorites.Clear();
DataContext = App.PersonalizedViewModel;
// this.Loaded += new RoutedEventHandler(MainPage_Loaded);
if (!App.PersonalizedViewModel.IsDataLoaded)
{
App.PersonalizedViewModel.LoadData();
}
}
For the purpose of debugging, you can remove the line if (!App.PersonalizedViewModel.IsDataLoaded) and try.

how to store post variable so i can call the variable anytime in ASP.NET

i am developing a web for my final project,and im new to ASP.NET and this forum.
thx to all who help me.
the question is...
example i have 2 pages.
page1.aspx.cs (this page for receive variable from mikrokontroler via network module)
example mikrokontroler send a variable "status" = 1
protected void Page_Load(object sender, EventArgs e)
{
NameValueCollection POST = Request.Form;
int STATUS;
int responcode;
try
{
A = int.Parse(POST["status"]);
}
catch (Exception)
{
status = 0;
}
if (A == 1)
{
responcode = 200;
//when A = 1, i want to store A value to (buffer on something <-- this what i want to ask)).
so i can call the value anytime in page2.
}
else
{
responcode = 400;
}
Response.StatusCode = responcode;
}
}
}
page2.aspx
(in page 2 there is button and textbox)
protected void Button3_Click(object sender, EventArgs e)
{
/*when this button click,
i want to show A value from page1
*/
}
You have a lot of options to store the variable value:
session state: Session["status"]= A
application state: Application["status"] = A
asp net cache: using Cache.Add()
database: here i would store also the timestamps, to trace the historic status of the controller.
local XML file.
It all depends on the scope of the stored data: session data is local to the current user/session and will expire after a predefined timeout(def: 20mins), application will be global to all your users/sessions and will expire when you will restart the application (by iis, iisreset, recompiling...), cache is global and will expire based on the parameters of invocation, the database and xml are global and will maintain state.
In your case i would use database or application store, because the microcontroller and user live in different sessions and the app cache is not a suitable messaging mechanism while Xml introduces some problems on his own (eg: filesystem permissions, data replication...).
write:
Application["status"] = A;
read:
int A = 0;
bool result = int.TryParse(Application["status"],out A);
BTW: to parse the integer you can skip the try/catch part doing this:
int A = 0;
bool result = int.TryParse(POST["status"],out A);
in this case if unable to parse A will be equal to 0;
You can use Session
NameValueCollection POST = Request.Form;
int STATUS;
int responcode;
try
{
A = int.Parse(POST["status"]);
}
catch (Exception)
{
status = 0;
}
if (A == 1)
{
responcode = 200;
//when A = 1, i want to store A value to (buffer on something <-- this what i want to ask)).
Session["Avalie"] = A;
so i can call the value anytime in page2.
}
else
{
responcode = 400;
}
Response.StatusCode = responcode;
}
}
and then on page 2
protected void Button3_Click(object sender, EventArgs e)
{
/*when this button click,
i want to show A value from page1
*/
if(!String.IsNullOrEmpty( Session["Avalie"] ))
int Aval = int.Parse(Session["Avalie"]);
}
Use crosspagepostback to pass values from one page to another (introduced in asp.net 2.0)
One option is to assign the value to a static variable in the first page.
Refer to Static Classes and Static Class Members (C# Programming Guide)
Another option is to use state variables as session state variables or application variables.
Refer to ASP.NET Session State Overview and ASP.NET Application State Overview

Categories