Hy,
I'm trying to call api from my web application every hour and store data in my database.
This is my Code to call
public class GetNationFromAPI
{
public static async Task GetNation()
{
try
{
string connectionString = ConfigurationManager.ConnectionStrings["PW"].ConnectionString;
string url = ConfigurationManager.GetSection("url").ToString();//Get Url from appsettings.json
var response = await GetApi.GetClient.GetStringAsync(url);
var obj = JsonConvert.DeserializeObject<RootDataModel>(response);
using SqlConnection con = new SqlConnection(connectionString);
string deleteQuery = "Delete From Nation";
SqlCommand com = new SqlCommand(deleteQuery, con);
con.Open();
com.ExecuteNonQuery();
con.Close();
string nationtblname = ConfigurationManager.GetSection("nationtblname").ToString();//Get Table name from appsettings.json
string nationquery = string.Format("insert into {0} (Nation_Id, Nation, Alliance_Id, Alliance, Score, VacMode, Alliance_Position, soldiers, tanks, aircraft, ships) " +
"Values (#nation_Id, #nation, #alliance_Id, #alliance, #alliance_Position, #score, #vacMode,#v_mode_turns, #soldiers, #tanks, #aircraft, #ships)", nationtblname);
foreach (var nations in obj.data)
{
SqlCommand comm = new SqlCommand(nationquery, con);
con.Open();
comm.Parameters.AddWithValue("#nation_Id", nations.nation_id);
comm.Parameters.AddWithValue("#nation", nations.nation);
comm.Parameters.AddWithValue("#alliance_Id", nations.alliance_id);
comm.Parameters.AddWithValue("#alliance", nations.alliance);
comm.Parameters.AddWithValue("#alliance_Position", nations.alliance_position);
comm.Parameters.AddWithValue("#score", nations.score);
comm.Parameters.AddWithValue("#vacMode", nations.v_mode);
comm.Parameters.AddWithValue("#v_mode_turns", nations.v_mode_turns);
comm.Parameters.AddWithValue("#soldiers", nations.soldiers);
comm.Parameters.AddWithValue("#tanks", nations.tanks);
comm.Parameters.AddWithValue("#aircraft", nations.aircraft);
comm.Parameters.AddWithValue("#ships", nations.ships);
comm.ExecuteNonQuery();
con.Close();
};
}
catch
{
throw new Exception();
}
}
}
Initially I did it from console application and it worked fine however I want my web app to do automatically every hour so I tried this in startup class of web application.
public class Startup
{
private static Timer atimer;
public static async Task Main()
{
atimer = new Timer
{
Interval = 3600000
};
atimer.Elapsed += await OnTimedEventAsync();
atimer.AutoReset = true;
atimer.Enabled = true;
}
private static async Task<ElapsedEventHandler> OnTimedEventAsync()
{
GetApi.InitializeClient();
await GetNationFromAPI.GetNation();
throw new Exception();
}
When I start my application and prompted to localhost and try to view nation. I get object reference not set to an instance of object instead of blank web page.
Related
First time working with SQL Dependency... but after having gone over several examples I feel as I am doing everything correct. I've checked that the Broker is Enabled. I've further checked that my query is correct. I am not receiving any exceptions at all! All and all everything seems as it should work... but it is not, and I have no idea how to begin to troubleshoot it without any exceptions being thrown.
Any help would be VERY much appreciated!
Here is my class:
public class NotificationEvent
{
private delegate void RateChangeNotification(DataTable table);
private SqlDependency dependency;
string ConnectionString = #"ConnectionString";
string UserName = Environment.UserName;
public async void StartNotification()
{
SqlDependency.Start(this.ConnectionString, "UserNotificationsQueue");
SqlConnection connection = new SqlConnection(this.ConnectionString);
await connection.OpenAsync();
SqlCommand command = new SqlCommand();
command.Connection = connection;
command.CommandType = CommandType.Text;
command.CommandText = string.Format("SELECT [NotificationID],[UserFrom],[UserTo],[DateTimeSent],[Notification] FROM [dbo].[PersonnellNotifications]", UserName);
command.Notification = null;
this.dependency = new SqlDependency(command, "Service=PostUserNotificationsQueue;", Int32.MaxValue);
dependency.OnChange += new OnChangeEventHandler(this.SqlDependencyOnChange);
await command.ExecuteReaderAsync();
}
private void SqlDependencyOnChange(object sender, SqlNotificationEventArgs eventArgs)
{
if (eventArgs.Info == SqlNotificationInfo.Invalid)
{
Console.WriteLine("The above notification query is not valid.");
}
else
{
Console.WriteLine("Notification Info: " + eventArgs.Info);
Console.WriteLine("Notification source: " + eventArgs.Source);
Console.WriteLine("Notification type: " + eventArgs.Type);
}
}
public void StopNotification()
{
SqlDependency.Stop(this.ConnectionString, "QueueName");
}
}
I am initializing this from another classes IniatializeComponent() as seen:
private void InitializeComponent()
{
// Initialize SQL Dependancy
ne.StartNotification();
}
I have just tested following in my Code and Its working good. I have simplified your code. Please see if this is working and you are getting a call in OnNotificationChange on Db Change.
public async void RegisterForNotification()
{
var connectionString = #"ConnectionString";
using (var connection = new SqlConnection(connectionString))
{
await connection.OpenAsync();
var queryString = "Your Query String";
using (var oCommand = new SqlCommand(queryString, connection))
{
// Starting the listener infrastructure...
SqlDependency.Start(connectionString);
var oDependency = new SqlDependency(oCommand);
oDependency.OnChange += OnNotificationChange;
// NOTE: You have to execute the command, or the notification will never fire.
await oCommand.ExecuteReaderAsync();
}
}
}
private void OnNotificationChange(object sender, SqlNotificationEventArgs e)
{
Console.WriteLine("Notification Info: " + e.Info);
//Re-register the SqlDependency.
RegisterForNotification();
}
Are you setting SQLClientPermission? see:
https://learn.microsoft.com/en-us/dotnet/framework/data/adonet/sql/enabling-query-notifications
// Code requires directives to
// System.Security.Permissions and
// System.Data.SqlClient
private bool CanRequestNotifications()
{
SqlClientPermission permission =
new SqlClientPermission(
PermissionState.Unrestricted);
try
{
permission.Demand();
return true;
}
catch (System.Exception)
{
return false;
}
}
I want to use OracleChangeNotifications in an ASP.NET MVC 3 App. I have created a simple console application with the example code from here, and it works as expected. If I change the registered database table, a notification gets fired in the console application.
Then I created an ASP.NET MVC 3 app with the same sample code but the MVC app is not getting any notifications. Im using oracle 11g. Apparently the listener gets registered in the oracle database. If I run the query:
SELECT * FROM user_change_notification_regs;
I get the following result:
REGID: 127
REGFLAGS: 4
CALLBACK: net8://(ADDRESS=(PROTOCOL=tcp)(HOST=127.0.0.1)(PORT=59747)?PR=0
OPERATIONS_FILTER: 0
CHANGELAG: 0
TIMEOUT: 48556
TABLE_NAME: MyTable
My guess is that IIS is somehow blocking the callback, but I cannot figure out why?
Any ideas?
Heres is the code I am using:
using System;
using System.Data;
using NLog;
using Oracle.DataAccess.Client;
namespace CacheTestWebApp.Services
{
public class Notification
{
private static Logger _logger = LogManager.GetCurrentClassLogger();
private const string ConnectionString = "<connection_string>";
private const string TableName = "MyTable";
private const string QueryString = "select * from " + TableName;
public static void RegisterNotification()
{
try
{
using (var con = new OracleConnection(ConnectionString))
{
con.Open();
var cmd = new OracleCommand(QueryString, con);
var dependency = new OracleDependency();
dependency.OnChange += dependency_OnChange;
dependency.AddCommandDependency(cmd);
cmd.Notification.IsNotifiedOnce = false;
cmd.AddRowid = true;
cmd.ExecuteNonQuery();
con.Close();
con.Dispose();
}
}
catch (Exception e)
{
_logger.Error(e.Message);
}
}
private static void dependency_OnChange(object sender, OracleNotificationEventArgs eventArgs)
{
// handle notification
}
}
}
Notification.RegisterNotification() is executed in Application_Start() in the Global.asax.cs:
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
RegisterGlobalFilters(GlobalFilters.Filters);
RegisterRoutes(RouteTable.Routes);
Notification.RegisterNotification();
}
We have been dealing with an error for the last couple of days, so we created a small page (quick and dirty programming, my apologies in advance) that connects to the database, checks if a document exists, and displays some data related to the document. If there is an exception, an email is sent with the exception information and some log data.
Here's a simplified version of the code (short explanation below):
namespace My.Namespace
{
public partial class myClass : System.Web.UI.Page
{
private static SqlConnection conn = null;
private static SqlCommand command1 = null;
private static SqlCommand command2 = null;
private static string log = "";
protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
try
{
log += "START\n";
string docId = Request.QueryString["docId"];
if (!String.IsNullOrEmpty(docName))
{
bool docExists = doesDocExist(docId);
if (docExists == true)
{
string docMetadata = getMetadata(docId);
Response.Write(docMetadata);
}
}
else
{
// display error message
}
}
catch (sqlException sqlex)
{
// process exception
sendErrorMessage(sqlex.Message);
}
catch (Exception ex)
{
// process exception
sendErrorMessage(ex.Message);
}
}
}
private static bool doesDocExist(string docId)
{
log += "In doesDocExist\n";
bool docExists = false;
try
{
// open db connection (conn)
string cmd = String.Format("SELECT COUNT(*) FROM docs WHERE id='{0}'", docId);
command1 = new SqlCommand(cmd, conn);
conn.Open();
var val = command1.ExecuteScalar();
int numberOfRows = int.Parse(val.ToString());
if (numberOfRows > 0) { docExists = true; }
}
finally
{
// close db connection (conn)
}
return docExists;
}
protected string getMetadata(string docId)
{
log += "In getMetadata\n";
string docMetadata = "";
try
{
// open db connection (conn)
string cmd = String.Format("SELECT metadata FROM docs WHERE id='{0}'", docID);
command2 = new SqlCommand(cmd, conn);
conn.Open();
SqlDataReader rReader = command2.ExecuteReader();
if (rReader.HasRows)
{
while (rReader.Read())
{
// process metadata
docMetadata += DOCMETADATA;
}
}
}
return docMetadata;
}
public static void sendErrorMessage(string messageText)
{
HttpContext.Current.Response.Write(messageText);
// Send string log via email
}
}
}
I know it's too long, so here is a quick description of it. We have a class with the Page_Load method and three other methods:
doesDocExists: returns a bool value indicating if an document ID is in the database.
getMetadata: returns a string with metadata related to the document.
sendErrorMessage: sends an email with a log generated during the page.
From Page_Load we call doesDocExists. If the value returned is true, then it calls getMetadata and displays the value on the screen. If there's any error, it is caught in the Page_Load and sent as an email.
The problem is that when there's an error, instead of getting an email with the log (i.e.: START - In Function1 - In Function2), the log appears 100 times in the email (i.e.: START - In Function1 - In Function2 - Start - In Function1 - In Function2 - START... and so on), as if Page_Load was fired that many times.
We read online (http://www.craigwardman.com/blog/index.php/2009/01/asp-net-multiple-page-load-problem/) that it could be because of the PostBack. So, we added the condition if (!Page.IsPostBack), but the result is still the same.
Is there any reason why Page_Load would be triggered multiple times? Or is it that we are doing something wrong with the log variable and/or the try/catch that causes this behavior?
The log may be long because you are declaring the string log as static. Does it need to be static?
private static SqlConnection conn = null;
private static SqlCommand command1 = null;
private static SqlCommand command2 = null;
private static string log = "";
The problem is that log is Singleton along with other properties.
Whenever you access that page, you append text to log property which ends up being START - In Function1 - In Function2 - Start - In Function1 - In Function2 - START... and so on
Base on your scenario, you do not need to use Singleton inside myClass.
FYI: Since I do not know the rest of your code, ensure to instantiate conn, command1, command2.
If your page load functions are execute twice because post back is possible when you clicking on the button or link, so should check it and run by the below
if (!IsPostBack)
{
try
{
log += "START\n";
string docId = Request.QueryString["docId"];
if (!String.IsNullOrEmpty(docName))
{
bool docExists = doesDocExist(docId);
if (docExists == true)
{
string docMetadata = getMetadata(docId);
Response.Write(docMetadata);
}
}
else
{
// display error message
}
}
catch (sqlException sqlex)
{
// process exception
sendErrorMessage(sqlex.Message);
}
catch (Exception ex)
{
// process exception
sendErrorMessage(ex.Message);
}
}
}
I'm having a really tough time wrapping my head around how to pass data back and forth between classes. I have taken some college courses Introduction to OOP, Beginning C++, Beginning C# and gone through several self paced online tutorials. I believe I'm grasping when to use classes but not how to use them. So heres what I'm trying to do, I just need a little guidance on how to accomplish this. Please don't tell me to google because I have searched until my fingers bled (ok not literally) and just need something more to go on at this point such as specific terminology. If someone could explain to me in C# terms anyways it would be helpful as I will have something specific to start searching on again.
So here is where I'm at...
I wrote an app that puts everything into the same class (Form1) and have it working. I'm using values from a dropdown list that preform a database query and assigns some variables that I use to play a video.
Heres the my complete code all in Form1
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Data.SqlServerCe;
namespace Tests
{
public partial class Tests : Form
{
public Tests()
{
InitializeComponent();
using (var conn = new SqlCeConnection("Data Source=TestDB.sdf;Password=;Persist Security Info=True"))
{
conn.Open();
var comm = new SqlCeCommand("SELECT DISTINCT ColumnOne FROM main", conn);
SqlCeDataReader reader = comm.ExecuteReader();
while (reader.Read())
columnOneComboBox.Items.Add(reader["ColumnOne"]);
}
}
private void columnOneComboBox_SelectedIndexChanged(object sender, EventArgs e)
{
testsListBox.Items.Clear();
testVideoMediaPlayer.Visible = false;
var columnOne = columnOneComboBox.SelectedItem.ToString();
using (var conn = new SqlCeConnection("Data Source=TestDB.sdf;Password=;Persist Security Info=True"))
{
conn.Open();
var comm = new SqlCeCommand("SELECT * FROM main WHERE ColumnOne='" + columnOne + "' ORDER BY ColumnTwo", conn);
SqlCeDataReader reader = comm.ExecuteReader();
while (reader.Read())
testsListBox.Items.Add(reader["ColumnTwo"]);
}
}
private void TestListBox_SelectedIndexChanged(object sender, EventArgs e)
{
var columnTwo = testsListBox.SelectedItem.ToString();
using (var conn = new SqlCeConnection("Data Source=TestDB.sdf;Password=Tr#1n!ng;Persist Security Info=True"))
{
conn.Open();
var comm = new SqlCeCommand("SELECT * FROM main WHERE ColumnTwo='" + columnTwo + "'", conn);
SqlCeDataReader reader = comm.ExecuteReader();
if (reader.Read())
{
bodyPositionRichTextBox.Text = reader["ColumnThree"].ToString();
techniqueRichTextBox.Text = reader["ColumnFour"].ToString();
string videoPath = reader["Video"].ToString();
if (videoPath != "")
{
testVideoMediaPlayer.URL = #"Videos/" + videoPath;
testVideoMediaPlayer.settings.playCount = 1000;
testVideoMediaPlayer.uiMode = "none";
testVideoMediaPlayer.Visible = true;
testVideoMediaPlayer.stretchToFit = true;
testVideoMediaPlayer.fullScreen = false;
}
else
{
testVideoMediaPlayer.Visible = false;
}
}
}
}
}
}
Now, what I was thinking about doing is creating separate class called MediaPlayer but I need to use a variable from Form1 in the MediaPlayer class where all the video controls are specified then have From1 call that player. So the following is what I was thinking of moving to MediaPlayer.cs:
if (videoPath != "")
{
testVideoMediaPlayer.URL = #"Videos/" + videoPath;
testVideoMediaPlayer.settings.playCount = 1000;
testVideoMediaPlayer.uiMode = "none";
testVideoMediaPlayer.Visible = true;
testVideoMediaPlayer.stretchToFit = true;
testVideoMediaPlayer.fullScreen = false;
}
else
{
testVideoMediaPlayer.Visible = false;
}
Am I going about this the wrong way? I'm not getting how to pass the string variable "Videos" from Test.cs to MediaPlayer.cs or how to call the MediaPlayer.cs from Test.cs. Thanks for any guidance that can be offered.
Your class MediaPlayer like this (substitute for your component type) :
public class MediaPlayer
{
/* your video type */ TestVideoMediaPlayer { get; set; }
public MediaPlayer(/* your video type */ testVideoMediaPlayer)
{
TestVideoMediaPlayer = testVideoMediaPlayer;
}
public void SetMediaPlayer(string url, int playerCount, string uiMode, bool visible, bool stretch, bool fullScreen)
{
if (url != "")
{
TestVideoMediaPlayer.URL = #"Videos/" + url;
TestVideoMediaPlayer.settings.playCount = playerCount;
TestVideoMediaPlayer.uiMode = uiMode;
TestVideoMediaPlayer.Visible = visible;
TestVideoMediaPlayer.stretchToFit = stretch;
TestVideoMediaPlayer.fullScreen = fullScreen;
}
else
{
TestVideoMediaPlayer.Visible = false;
}
}
}
And substitute your call to:
if (reader.Read())
{
bodyPositionRichTextBox.Text = reader["ColumnThree"].ToString();
techniqueRichTextBox.Text = reader["ColumnFour"].ToString();
string videoPath = reader["Video"].ToString();
MediaPlayer mp = new MediaPlayer(testVideoMediaPlayer);
mp.SetMediaPlayer(videoPath, 1000, "none", true, true, false);
}
I have got 3-tier where carry out my code in business layer I run code for update
public override bool LoadProperties2List(string TypeOfOperation)
{
SortedList Sl = new SortedList();
Sl.Add("#CommandType", TypeOfOperation);
Sl.Add("#UserName",UserName);
Sl.Add("#SecondarySchool",SecondarySchool);
Sl.Add("#University",University);
Sl.Add("#Qualification",Qualification);
Sl.Add("#JobTitle",JobTitle);
Sl.Add("#Company",Company);
Sl.Add("#PhotoUrl", PhotoUrl);
ProcedureName = "MangeUserInfo";
if (db.RunProcedure(ProcedureName, Sl) == 1)
return true;
else
return false;
}
public bool updateUser(string User, string SecondaryS, string Unvi, string Qua, string jobtitle, string company)
{
this.UserName = User;
this.SecondarySchool = SecondaryS;
this.University = Unvi;
this.Qualification = Qua;
this.JobTitle = jobtitle;
this.Company = company;
if (Update())
return true;
else
return false;
}
and in data access layer
public void ConnectDB(CommandType CT,string ProNameSQl)
{
cn = new SqlConnection("Data Source=.;Initial Catalog=Conversation;Integrated Security=True");
cmd = new SqlCommand();
cmd.Connection = cn;
cmd.CommandType = CT;
cmd.CommandText = ProNameSQl;
cn.Open();
}
public int RunProcedure(string ProcedureName, SortedList Paraval)
{
ConnectDB(CommandType.StoredProcedure, ProcedureName);
for (int x = 0; x < Paraval.Count; x++)
{
try
{
cmd.Parameters.AddWithValue(Paraval.GetKey(x).ToString(), Paraval.GetByIndex(x));
}
catch
{
;
}
}
return ExceNoneQuery();
}
and then in another layer I use this method to call procedure process kind and run
public bool Update()
{
return LoadProperties2List("u");
}
at last layer presentation layer
I do that
protected void btnsave_Click(object sender, EventArgs e)
{
//upadate info
bool Result = false;
UsersInfo Upd = new UsersInfo();
try
{
Result = Upd.updateUser(username, TxtSecondarySchool.Text, TxtUniversity.Text, TxtQualification.Text, TxtJobTitle.Text, TxtCompany.Text);
if (Result==true)
lblMessage.Text = "Record Updated Successfully.";
else
lblMessage.Text = "Record couldn't updated";
}
catch (Exception ee)
{
lblMessage.Text = ee.Message.ToString();
} finally
{
Upd = null;
}
}
When I run the code only the result is
lblMessage.Text = "Record couldn't updated";
What is the error which makes it not to work correctly?
I also find something strange that the textboxes doesn't take the new values it pass the same value despite change why? I need help
The error is that the textbox loads in a routine in the Page's Startup event, with the routine placed outside the If IsNotPostback loop. So, the default value just reloads every time the page is refreshed, and thus appears to be 'unchangeable'.