SignalR Content dont update if send to Client.Caller - c#

Hello and thanks for reading this.
This is my NotificationHub.cs
public class NotificationHub : Hub
{
private static readonly ConcurrentDictionary<string, User> Users = new ConcurrentDictionary<string, User>(StringComparer.InvariantCultureIgnoreCase);
private static List<User> UserList = new List<User>();
Int16 totalNewMessages = 0;
string UserID;
[HubMethodName("check")]
public Task Check(string id)
{
string profileId = id; //Context.QueryString["id"];
string connectionId = Context.ConnectionId;
var user = Users.GetOrAdd(profileId, _ => new User
{
ProfileId = profileId,
ConnectionIds = id
});
lock (user.ConnectionIds)
{
Groups.Add(connectionId, user.ProfileId);
}
return base.OnConnected();
}
[HubMethodName("sendNotifications")]
public Task SendNotifications(string id)
{
UserID = id;
using (var connection = new SqlConnection(ConfigurationManager.ConnectionStrings["DefaultConnection"].ConnectionString))
{
string query = "SELECT NotificationNumber FROM [dbo].[NotificationStatus] WHERE UserID=" + UserID;
connection.Open();
using (SqlCommand command = new SqlCommand(query, connection))
{
command.Notification = null;
DataTable dt = new DataTable();
SqlDependency dependency = new SqlDependency(command);
dependency.OnChange += new OnChangeEventHandler(dependency_OnChange);
if (connection.State == ConnectionState.Closed)
connection.Open();
var reader = command.ExecuteReader();
dt.Load(reader);
if (dt.Rows.Count > 0)
{
totalNewMessages = Int16.Parse(dt.Rows[0]["NotificationNumber"].ToString());
}
}
}
User CurrentUser = UserList.FirstOrDefault(i => i.ProfileId == UserID);
IHubContext context = GlobalHost.ConnectionManager.GetHubContext<NotificationHub>();
//return context.Clients.All.RecieveNotification(totalNewMessages);
return context.Clients.Client(Users.Values.FirstOrDefault(i => i.ProfileId == UserID).ConnectionIds).RecieveNotification(totalNewMessages);
}
private void dependency_OnChange(object sender, SqlNotificationEventArgs e)
{
if (e.Type == SqlNotificationType.Change)
{
NotificationHub nHub = new NotificationHub();
nHub.SendNotifications(UserID);
}
}
}
These 2 lines is what I want to focus on.
//return context.Clients.All.RecieveNotification(totalNewMessages);
return context.Clients.Client(Users.Values.FirstOrDefault(i => i.ProfileId == UserID).ConnectionIds).RecieveNotification(totalNewMessages);
If i use the first line it returns the totalNewMessages back to ALL people on the website, but i only want to to return back to the user that requested it.
The second line is my attempt to return the totalNewMessages back tot he specific user, but it dont work.
How can i return the totalNewMessages Back to only the specific user?

I came across this problem a while back. I got it working by returning the messages depending on the user who's logged in
string userName = HttpContext.Current.User.Identity.Name;
return context.Clients.User(userName).RecieveNotification(totalNewMessages);
Also look into parameterized queries to prevent sql injection. There's a handy documentation for what you're trying to achieve here

Related

Discord.net task call issue

I'm trying to create a discord bot in .NET with a command to put a user on markers. For example, a server admin gives a user 50 markers and the user would get all of his roles removed and would be given a role called "Markers". Then, a text channel will appear where the user needs to spam 50 messages to remove the markers and he'd get everything back. I have made commands for giving markers and removing them but when I try to remove someone's markers by calling the function from the Program.cs it gives a null pointer exception for some reason. Here's the code:
Program.cs event:
private async Task MessageRecieved(SocketMessage arg)
{
//Checking if the user has markers
var roles = (arg.Author as SocketGuildUser).Roles;
bool imaMarkere = false;
foreach (var role in roles)
{
if (role.Id == 844558286611152917)
imaMarkere = true;
}
if (arg.Channel.Id == 844558185024585770 && imaMarkere)
{
int markerCount = 0;
using (SqliteConnection con = new SqliteConnection(connectionString))
{
con.Open();
string query = $"select markercount from markers";
var com = con.CreateCommand();
com.CommandText = query;
var rdr = com.ExecuteReader();
if (rdr.Read())
{
markerCount += Convert.ToInt32(rdr["markercount"]) - 1;
}
rdr.Close();
//Removing 1 marker per message recieved
if (markerCount > 0)
{
com.CommandText = $"update markers set markercount={markerCount} where userid='{arg.Author.Id}'";
com.ExecuteNonQuery();
}
//If no markers are left returning the user roles
else
{
Commands c = new Commands();
await c.Skini(arg.Author as IGuildUser);
}
con.Close();
}
}
else return;
}
Commands.cs
[Command("skini"), RequireUserPermission(GuildPermission.Administrator, ErrorMessage = "Nemate potrebnu dozvolu ``ADMINISTRATOR``")]
public async Task Skini(IGuildUser user = null)
{
if(user == null)
{
await ReplyAsync($"{Context.User.Mention},kome da skinem?");
}
string rolesString = "";
string[] roles;
using (SqliteConnection con = new SqliteConnection(connectionString))
{
con.Open();
var com = con.CreateCommand();
string readQuery = "select pastroles from markers";
com.CommandText = readQuery;
var rdr = com.ExecuteReader();
if (rdr.Read())
{
rolesString += rdr["pastroles"].ToString();
}
rdr.Close();
string deleteQuery = $"delete from markers where userid = '{user.Id}'";
com.CommandText = deleteQuery;
com.ExecuteNonQuery();
con.Close();
}
roles = rolesString.Split(",");
foreach (var roleid in roles)
{
var role = Context.Guild.GetRole(Convert.ToUInt64(roleid));//this line is where the exception happens
if(!role.IsEveryone)
await user.AddRoleAsync(role);
}
var roleMarkeri = Context.Guild.GetRole(844558286611152917);
await user.RemoveRoleAsync(roleMarkeri);
var EmbedBuilder = new EmbedBuilder()
.WithTitle("**MARKERI**")
.WithColor(Color.Blue)
.WithDescription($":white_check_mark: {Context.User.Mention} je **skinuo** markere {user.Username}")
.WithFooter(footer =>
{
footer
.WithText("Marker log");
});
Embed embed = EmbedBuilder.Build();
await ReplyAsync(embed: embed);
}

Retrieve multiple rows from SQL Server in a web service and xamarin android?

I want to retrieve multiple rows from SQL Server in a web service. I get 2 rows as result when I search jo number 1 and my table name is TestOrderStatus.
While I get only one row in the search result.
Thanks for all
public class ReturnOrder
{
public string Message;
public int QtqSlit;
public int QtyPcs;
public string Design;
}
[WebMethod(MessageName = "OrderStatus", Description = "OrderStatus new Order")]
[System.Xml.Serialization.XmlInclude(typeof(ReturnOrder))]
public ReturnOrder OrderStatus(string JO) /// get list of notes
{
int QtqSlit = 0;
int QtyPcs = 0;
String Design = "";
string Message = "";
SqlDataReader reader;
using (SqlConnection connection = new SqlConnection(DBConnection.ConnectionString))
{
SqlCommand cmd = new SqlCommand("SELECT QtqSlit,QtyPcs,Design FROM TestOrderStatus where JO=#JO");
cmd.CommandType = CommandType.Text;
cmd.Connection = connection;
cmd.Parameters.AddWithValue("#JO", JO);
connection.Open();
reader = cmd.ExecuteReader();
while (reader.Read())
{
for (int i = 0; i < reader.FieldCount; i++)
{
QtqSlit = reader.GetInt32(0);
QtyPcs = reader.GetInt32(1);
Design = reader.GetString(2);
}
}
if (QtqSlit == 0)
{
Message = " user name or password is incorrect";
}
reader.Close();
connection.Close();
}
ReturnOrder rt = new ReturnOrder();
rt.Message = Message;
rt.QtqSlit = QtqSlit;
rt.QtyPcs = QtyPcs;
rt.Design = Design;
return rt;
}
You need a List for multiple rows if you want more than one result. So your code may be like this.
public class ReturnOrder
{
public string Message;
public int QtqSlit;
public int QtyPcs;
public string Design;
}
[WebMethod(MessageName = "OrderStatus", Description = "OrderStatus new Order")]
[System.Xml.Serialization.XmlInclude(typeof(List<ReturnOrder>))]
public List<ReturnOrder> OrderStatus(string JO) /// get list of notes
{
List<ReturnOrder> result=new List<ReturnOrder>();
int QtqSlit = 0;
int QtyPcs = 0;
String Design = "";
string Message = "";
//try
//{
SqlDataReader reader;
using (SqlConnection connection = new SqlConnection(DBConnection.ConnectionString))
{
SqlCommand cmd = new SqlCommand("SELECT QtqSlit,QtyPcs,Design FROM TestOrderStatus where JO=#JO");
cmd.CommandType = CommandType.Text;
cmd.Connection = connection;
cmd.Parameters.AddWithValue("#JO", JO);
connection.Open();
reader = cmd.ExecuteReader();
while (reader.Read())
{
QtqSlit = reader.GetInt32(0);
QtyPcs = reader.GetInt32(1);
Design = reader.GetString(2);
ReturnOrder rt = new ReturnOrder();
rt.Message = Message;
rt.QtqSlit = QtqSlit;
rt.QtyPcs = QtyPcs;
rt.Design = Design;
result.add(rt);
}
if (QtqSlit == 0)
{
Message = " user name or password is in correct";
}
reader.Close();
connection.Close();
}
//}
//catch (Exception ex)
//{
// Message = " cannot access to the data";
//}
return result;
}
Thank you to much now web service is ok , But when he summoned the values in Xamrian Android doesn't know.
public class Mainlistview : Activity
{
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
// Set our view from the "main" layout resource
SetContentView(Resource.Layout.Mainlistview);
ListView ListView = FindViewById<ListView>(Resource.Id.listView1);
Selling.WebServiceDB ws = new Selling.WebServiceDB();
ws.OrderStatusListCompleted += Ws_OrderStatusListCompleted;
ws.OrderStatusListAsync(Convert.ToString(1));
}
private void Ws_OrderStatusListCompleted(object sender, Selling.OrderStatusListCompletedEventArgs e)
{
ListView ListView = FindViewById<ListView>(Resource.Id.listView1);
string msg = "";
if (e.Result.QtqSlit.ToString().Equals("0"))
{
msg = e.Result.Message;
}
else
{
// full class
List<TableItem> tableItems = new List<TableItem>();
tableItems.Add(new TableItem("" + e.Result.QtqSlit, "" + e.Result.QtyPcs, Resource.Drawable.Icon));
ListView.Adapter = new HomeScreenAdapter(this, tableItems);
}
}

SQLDependency with group by is not working

I have below code for SqlDependency. Below call back function is get called every time when data reader is executed. Rather than this call back function not get executing when i change some value in Table.
public IEnumerable<Messages> GetAllMessages()
{
var messages = new List<Messages>();
using (var connection = new SqlConnection(_connString))
{
connection.Open();
using (var command = new SqlCommand("SELECT SUM(MessageID) FROM [dbo].[Messages] group by Message", connection))
{
command.Notification = null;
var dependency = new SqlDependency(command);
dependency.OnChange += new OnChangeEventHandler(dependency_OnChange);
if (connection.State == ConnectionState.Closed)
connection.Open();
var reader = command.ExecuteReader();
while (reader.Read())
{
// messages.Add(item: new Messages { MessageID = (int)reader["MessageID"], Message = (string)reader["Message"], EmptyMessage = reader["EmptyMessage"] != DBNull.Value ? (string)reader["EmptyMessage"] : "", MessageDate = Convert.ToDateTime(reader["Date"]) });
}
}
}
return messages;
}
CallBack:
private void dependency_OnChange(object sender, SqlNotificationEventArgs e)
{
if (e.Type == SqlNotificationType.Change)
{
MessagesHub.SendMessages();
}
}
Any Help please!

Invalid attempt to read data when no data is present

I have a SQL Server database in C# [built before I got to my present job, creator is gone], and it was fine until last week. On the first page clerk_search.aspx it searches SQL Server for people and posts back to a datagrid that's fine.
There is a ASP Image button that's clicked on and it goes forward to the next page, to enter the reason the for the customers visit with loaded fields about the customer that post back. For some persons the next page populates, for others it does not. The SQL statement used checks out fine in query analyzer, I don't understand. I don't think its the reader because others are logged in fine, and the other customers are present in the rows in SQL and can be queried just fine. All is posted below, I am not savvy with coding, please assist.
System.InvalidOperationException: Invalid attempt to read when no data is present.
SqlDataReader reader2 = cmd.ExecuteReader();
reader2.Read();
[InvalidOperationException: Invalid attempt to read when no data is present.]
Here is the actual: ....clerk_create.aspx.cs
public partial class clerk_create : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
if (Request.Cookies["us"] == null)
{
Response.Write("Sorry, you do not have access to this page. Please see
data systems.");
Response.End();
}
if (!IsPostBack)
{
using (SqlConnection connection = new SqlConnection
(WebConfigurationManager.ConnectionStrings["walkin2"].ConnectionString))
{
TextBox txtsct = (TextBox)Page.PreviousPage.FindControl("Txtsct");
Txtsct.Text = txtsct.Text;
TextBox txt = (TextBox)Page.PreviousPage.FindControl("Txtssn");
Txtssn.Text = "" + txt.Text;
connection.Open();
string strsql2 = "SELECT dbo.table_name.SSN,
dbo.table_name.LAST_NAME,
dbo.table_name.FIRST_NAME, dbo.table_name.MIDDLE_INITIAL,
dbo.table_name.COMPONENT_CODE, dbo.table_name.PRESENT_CODE FROM
dbo.table_name INNER JOIN dbo.table_name ON dbo.table_name.SSN = '" +
Txtssn.Text + "')";
SqlCommand cmd = new SqlCommand(strsql2, connection);
SqlDataReader reader2 = cmd.ExecuteReader();
reader2.Read();
LblLName.Text = "" + reader2["LAST_NAME"];
LblFName.Text = "" + reader2["FIRST_NAME"];
}
}
}
...
}
You should check the return value of Read method.
If read method returns false then there is no more data. In that case you should not read the data from reader. Doing so will cause this exception.
If you're sure that you'll get only one record try this
if(reader2.Read())
{
LblLName.Text = "" + reader2["LAST_NAME"];
LblFName.Text = "" + reader2["FIRST_NAME"];
}
usually DataReader is used as below, since it can contain number of records
while (reader2.Read())
{
//Consume reader using reader2["Column"] etc
}
Your code is not properly disposing some objects and it is vulnerable to SQL injection.
DTO:
public class Employee
{
public string FirstName { get; set; }
public string LastName { get; set; }
}
Code:
private static readonly Lazy<string> ConnectionString = new Lazy<string>(() => WebConfigurationManager.ConnectionStrings["walkin2"].ConnectionString);
private const string GetEmployeeBySSNQuery = "SELECT dbo.table_name.SSN, dbo.table_name.LAST_NAME, dbo.table_name.FIRST_NAME, dbo.table_name.MIDDLE_INITIAL, dbo.table_name.COMPONENT_CODE, dbo.table_name.PRESENT_CODE FROM dbo.table_name INNER JOIN dbo.table_name ON dbo.table_name.SSN = #SSN";
protected void Page_Load(object sender, EventArgs e)
{
// ...
if(!IsPostBack)
{
GetEmployeeInformation();
}
}
private void GetEmployeeInformation()
{
var sctTextBox = (TextBox)Page.PreviousPage.FindControl("Txtsct");
Txtsct.Text = txtsct.Text;
var ssnTextBox = (TextBox)Page.PreviousPage.FindControl("Txtssn");
Txtssn.Text = ssnTextBox.Text;
var ssn = ssnTextBox.Text;
var employee = GetEmployeeBySSN(ConnectionString.Value, ssn);
if(employee != null)
{
LblFName.Text = employee.FirstName;
LblLName.Text = employee.LastName;
}
}
private Employee GetEmployeeBySSN(string connectionString, string ssn)
{
Employee employee = null;
using(var connection = new SqlConnection(connectionString))
{
connection.Open();
using(var command = new SqlCommand(GetEmployeeBySSNQuery, connection)
{
command.Parameters.AddWithValue("#SSN", ssn);
using(var reader = command.ExecuteReader())
{
if(reader.Read())
{
employee = new Employee
{
FirstName = Convert.ToString(reader["FIRST_NAME"]),
LastName = Convert.ToString(reader["LAST_NAME"])
};
}
}
}
}
return employee;
}

Check whether record existed

Do anyone know how to insert data into database only once during runtime? because right now whenever i run my system, the data would be always inserted into the database. its there any way just to insert the data only once even if i have run the program for many times?Here are my codes
public async void getUserName()
{
LiveConnectClient client = new LiveConnectClient(session);
LiveOperationResult operationResultUserID = await client.GetAsync("me");
dynamic resultUserID = operationResultUserID.Result;
userID = resultUserID.id;
//getUserInfo();
Service1Client client1 = new Service1Client();
name = await client1.RetrieveNameAsync(userID);
dob = await client1.RetrieveDOBAsync(userID);
aboutMe = await client1.RetrieveAboutMeAsync(userID);
country = await client1.RetrieveCountryAsync(userID);
email = await client1.RetrieveEmailAddressAsync(userID);
gender = await client1.RetrieveGenderAsync(userID);
//status = await client1.RetrieveUserStatusAsync(userID);
UserImage = await client1.RetrieveUserImgAsync(userID);
vote = await client1.retrieveVotesAsync(userID);
count = await client1.retrievecountLearningstoryAsync(userID);
txtAboutmeDisplay.Text = aboutMe;
txtCountryDisplay.Text = country;
txtDOBDisplay.Text = dob;
txtEmailDisplay.Text = email;
txtGenderDisplay.Text = gender;
txtName.Text = name;
txtvotes.Text = vote;
txtCountDisplay.Text = count.ToString();
int numberofvotes = int.Parse(txtvotes.Text);
if (numberofvotes >=1000)
{
txtstars.Text = "Gold";
}
else if (numberofvotes >= 700)
{
txtstars.Text = "Silver";
}
else if (numberofvotes >= 500)
{
txtstars.Text = "Bronze";
}
//txtstars.Visibility == false;
InMemoryRandomAccessStream randomAccessStream = new InMemoryRandomAccessStream();
DataWriter writer = new DataWriter(randomAccessStream.GetOutputStreamAt(0));
writer.WriteBytes(UserImage);
await writer.StoreAsync();
// Create bitmap image
BitmapImage b = new BitmapImage();
b.SetSource(randomAccessStream);
// Update Image on XAML Page
imgProfilePic.Source = b;
int countstory = int.Parse(txtCountDisplay.Text);
if (countstory >= 7)
{
achievement = await client1.updateachievementAsync(userID, "wisemen");
}
else if (countstory == 6)
{
achievement = await client1.updateachievementAsync(userID, "Smartboy");
}
else if (countstory == 5)
{
achievement = await client1.insertAchievementAsync(userID, "novice");
}
}
My webservice codes
public string insertAchievement(string userid, string achievements)
{
SqlConnection con = new SqlConnection(connectionString);
con.Open();
string insertInterBadges = "Insert into [Achievement] (UserID, Achievement) VALUES " + " (#userid,#achievements)";
SqlCommand cmd = new SqlCommand(insertInterBadges, con);
cmd.Parameters.AddWithValue("#userId", userid);
cmd.Parameters.AddWithValue("#achievements", achievements);
int check = cmd.ExecuteNonQuery();
con.Close();
if (check > 0)
{
return "Success";
}
else
{
return "Fail";
}
}
public string updateachievements(string userid, string achievements)
{
SqlConnection con = new SqlConnection(connectionString);
con.Open();
string updateAchievements = "UPDATE Achievement SET Achievement=#achievement Where UserID=#userid";
SqlCommand cmd = new SqlCommand(updateAchievements, con);
cmd.Parameters.AddWithValue("#userId", userid);
cmd.Parameters.AddWithValue("#achievement", achievements);
int check = cmd.ExecuteNonQuery();
con.Close();
if (check > 0)
{
return "Success";
}
else
{
return "Fail";
}
}
my reference.cs
[System.ServiceModel.OperationContractAttribute(Action = "http://tempuri.org/IService1/updateachievement", ReplyAction = "http://tempuri.org/IService1/updateachievement")]
System.Threading.Tasks.Task<string> updateachievementAsync(string userId, string achievements);
[System.ServiceModel.OperationContractAttribute(Action = "http://tempuri.org/IService1/insertAchievement", ReplyAction = "http://tempuri.org/IService1/insertAchievement")]
System.Threading.Tasks.Task<string> insertAchievementAsync(string userId, string achievements);
public System.Threading.Tasks.Task<string> updateachievementAsync(string userId, string achievements)
{
return base.Channel.insertAchievementAsync(userId, achievements);
}
public System.Threading.Tasks.Task <string> insertAchievementAsync(string userId, string achievements)
{
return base.Channel.insertAchievementAsync(userId, achievements);
}
i am using webservice by the way
By the looks of your code, specifically the UPDATE statement, a single user can only be assigned a single achievement. That limitation makes the easy-way-out of creating a unique index on UserId, AcheivementId not a viable option (this index, if created, would prevent duplicate entries via a SQL insertion error).
The alternative, more correct, solution is to query the table prior to inserting to see if the values already exist:
SELECT COUNT(*) FROM Achievement WHERE UserId = #userId AND Achievement = #achievement
This could be used in a block like:
using (SqlConnection conn = new SqlConnection(connectionString)) {
conn.Open();
bool isNewValue = true;
using (SqlCommand cmd = new SqlCommand("SELECT COUNT(*) FROM Achievement WHERE UserId = #userId AND Achievement = #achievement")) {
cmd.Parameters.AddWithValue("#userId", userid);
cmd.Parameters.AddWithValue("#achievement", achievements);
isNewValue = ((int)cmd.ExecuteScalar() == 0);
}
if (isNewValue) {
// insert user achievement / etc
}
}

Categories

Resources