问:
My code is not working after dataGridView1.Rows.Clear() until end
My code is not working as I expected and I give the question to last days but I only checked after 2 days and I suppose my chance is gone to being answered. If that's wrong I'm asked second time excuse me well.

I have this weird going on to my codes with my visual studio pro. There are no error messages of disconnected loops. It seems like I give up to check something wrong all files of my point of sales project.

And I've given to updateb() and invoice(). So it's better off up like all codes in my specific file. So up like this.

```<code>using MySql.Data.MySqlClient;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace superpos3
{
    public partial class salesn : Form
    {
        public salesn()
        {
            InitializeComponent();
        }

       public static int totalPrice = 0;
        public static int payment = 0;
        public static int balance = 0;

        MySqlConnection con = new MySqlConnection("server= localhost; database =superpos;  username= root; password=; ");

        public void invoice()
        {

            con.Open();
            string query = "select max(id) from salesmain ";
            MySqlCommand cmd2 = new MySqlCommand(query, con);
            MySqlDataReader dr;
            dr = cmd2.ExecuteReader();
            if (dr.Read())
            {
                string val = dr[0].ToString();
                if (val == "")
                {
                    lbinvoice.Text = "1";

                }
                else
                {
                    int a;

                    a = int.Parse(dr[0].ToString());
                    a = a + 1;
                    lbinvoice.Text = a.ToString();

                }
                con.Close();
            }

        }

        private void richTextBox1_TextChanged(object sender, EventArgs e)
        {

        }

        private void txtno_KeyPress(object sender, KeyPressEventArgs e)
        {
            if (e.KeyChar == 13)
            {
                txtqty.Enabled = true;
                txtqty.Focus();
            }
        }

        private void txtqty_KeyPress(object sender, KeyPressEventArgs e)
        {
            if (e.KeyChar == 13)
            {

                try
                {

                    string txt = "select * from products where id='" + txtno.Text + "'";
                    MySqlCommand cmd = new MySqlCommand(txt, con);
                    con.Open();
                    MySqlDataReader r = cmd.ExecuteReader();
                    while (r.Read())
                    {
                        int price = int.Parse(txtqty.Text.ToString()) * int.Parse(r[4].ToString());
                        totalPrice = totalPrice + price;
                        //discount
                        // totalPrice = totalPrice - totalPrice* Payment.discount/100;

                        dataGridView1.Rows.Add(dataGridView1.RowCount, r[0], r[1], txtqty.Text.Trim(), r[4], price);

                    }
                    lbitems.Text = " " + (dataGridView1.RowCount - 1) + "";
                    lbtotal.Text = " " + totalPrice + " ";

                    con.Close();

                }

                catch (Exception ee)
                {
                    MessageBox.Show(ee.Message, "Error From Database");
                }

                txtno.Focus();
                txtno.Clear();

                txtqty.Enabled = false;
                txtqty.Clear();

            }

        }

        private void txtqty_TextChanged(object sender, EventArgs e)
        {

        }
        private string name;

        public string Staffname
        {
            get { return name; }
            set { name = value; }

        }

      public void updatedb()
        {

            for (int row = 0; row < dataGridView1.Rows.Count; row++)
            {

                string itmno = dataGridView1.Rows[row].Cells[1].Value.ToString();
                string itmqty = dataGridView1.Rows[row].Cells[3].Value.ToString();

                string t = "select * from products where id= '"+ itmno + "'";

                string oldqty = "", newqty = "";

                Connnew.DbSearch(t);

                while (Connnew.dr.Read())
                {

                    oldqty = Connnew.dr[5].ToString();
                    newqty = (int.Parse(oldqty) - int.Parse(itmqty)).ToString();
                }

                string t2 = "update products SET qty = '" + newqty + "' WHERE id = '" + itmno + "'";
                //t2 = t2.Replace("{0}", itmno);
                //t2 = t2.Replace("{2}", newqty);
                Connnew.DbUpdate(t2);
            }

        }

        private void salesn_Load(object sender, EventArgs e)
        {
            label6.Text = Staffname;
            lbldate.Text = DateTime.Today.ToString("dd/MM/yyyy");
            lbltime.Text = DateTime.Now.ToShortTimeString();

            invoice();

        }

        private void button1_Click(object sender, EventArgs e)
        {
            try
            {

                for (int i = 0; i < dataGridView1.Rows.Count; i++)
                {

                    MySqlCommand cmd = new MySqlCommand();
                    cmd.Connection = con;

                    cmd.CommandText = "Insert into salesproducts(saleid,productname,qty,grosstotal)values(@saleid,@productname,@qty,@grosstotal)";
                    cmd.Parameters.AddWithValue("@saleid", lbinvoice.Text);
                    cmd.Parameters.AddWithValue("@productname", dataGridView1.Rows[i].Cells[2].Value);
                    cmd.Parameters.AddWithValue("@qty", dataGridView1.Rows[i].Cells[3].Value);
                    cmd.Parameters.AddWithValue("@grosstotal", dataGridView1.Rows[i].Cells[4].Value);

                    MySqlCommand cmd1 = new MySqlCommand();
                    cmd1.Connection = con;
                    cmd1.CommandText = "insert into salesmain(id,date,time,cashername,qty,grosstotal)values(@id,@date,@time,@cashername,@qty,@grosstotal)";
                    cmd1.Parameters.AddWithValue("@id", lbinvoice.Text);
                    cmd1.Parameters.AddWithValue("@date", lbldate.Text);
                    cmd1.Parameters.AddWithValue("@time", lbltime.Text);
                    cmd1.Parameters.AddWithValue("@cashername", label6.Text);
                    cmd1.Parameters.AddWithValue("@qty", lbitems.Text);

                    cmd1.Parameters.AddWithValue("@grosstotal", lbtotal.Text);

                    con.Open();
                   int x = cmd.ExecuteNonQuery();
                   int y = cmd1.ExecuteNonQuery();

                    MessageBox.Show("Record added ..........");
                    updatedb();

             //until here everything worked fine but if additionally given below codes not wroking
               even the updatedb().

                    dataGridView1.Rows.Clear();
                    lbtotal.Text = "0";
                    lbitems.Text = "0";
                    txtno.Focus();
                    totalPrice = 0;

                    con.Close();
                    invoice();

                }
               }
            catch (Exception ex)
            {
                //MessageBox.Show(ex.Message);
            }

            finally
            {
                con.Close();
            }
           }

        private void button2_Click(object sender, EventArgs e)
        {
            pay p = new pay();
            p.Show();
        }

        private void label6_Click(object sender, EventArgs e)
        {

        }
    }
}
</code>```

And I'm seeing everything is fine and still not find the issue of those.

And the connected with above related to Connnew.DbSearch(t) that "Connnew" is like:

```<code>using MySql.Data.MySqlClient;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using MySql.Data.MySqlClient;
namespace superpos3
{
    class Connnew
    {

        public static MySqlConnection con = new MySqlConnection("server= localhost; database =superpos; username= root; password=; ");
        public static MySqlCommand poscmd = new MySqlCommand();
        public static MySqlDataReader dr;

        public static void DbSearch(string txt)
        {

            con.Close();
            poscmd.Connection = con;
            poscmd.CommandText = txt;
            con.Open();
            dr = poscmd.ExecuteReader();
        }

        public static void DbUpdate(string txt)
        {
            con.Close();
            poscmd.Connection = con;
            poscmd.CommandText = txt;
            con.Open();
            poscmd.ExecuteNonQuery();
        }
    }
}
</code>```

I couldn't display the picture wholly screenshot or there is no permission here whatever. Please click down the below links.

please watch the sales window here

then please watch this one to know whats not work

Please let me know what is here the issue of the structure of codes or what is really going wrong...............(this question is ended and updated my question below)

I checked all but except the form1.cs file are irrelevant of the problem here. So additionally for here:

```<code>using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace superpos3
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {

        }

        private void timer1_Tick(object sender, EventArgs e)
        {
            progressBar1.Value = progressBar1.Value + 1;
            if (progressBar1.Value >= 100)
            {
                Login In = new Login();
                this.Hide();
                In.Show();

                timer1.Enabled = true;
                progressBar1.Visible = false;
                timer1.Enabled = false;
            }
        }

        private void progressBar1_Click(object sender, EventArgs e)
        {

        }
    }
}
</code>```

答:
General recommendation. Please consider changing the code in many places. And don't wrap the MySqlConnection into object because it is already object oriented.
You should not add parameters and open connection at each iteration like this:

```<code>        private void button1_Click(object sender, EventArgs e)
        {
            try
            {

                for (int i = 0; i < dataGridView1.Rows.Count; i++)
                {

                    MySqlCommand cmd = new MySqlCommand();
                    cmd.Connection = con;

                    cmd.CommandText = "Insert into salesproducts(saleid,productname,qty,grosstotal)values(@saleid,@productname,@qty,@grosstotal)";
                    cmd.Parameters.AddWithValue("@saleid", lbinvoice.Text);
                    cmd.Parameters.AddWithValue("@productname", dataGridView1.Rows[i].Cells[2].Value);
                    cmd.Parameters.AddWithValue("@qty", dataGridView1.Rows[i].Cells[3].Value);
                    cmd.Parameters.AddWithValue("@grosstotal", dataGridView1.Rows[i].Cells[4].Value);

                    MySqlCommand cmd1 = new MySqlCommand();
                    cmd1.Connection = con;
                    cmd1.CommandText = "insert into salesmain(id,date,time,cashername,qty,grosstotal)values(@id,@date,@time,@cashername,@qty,@grosstotal)";
                    cmd1.Parameters.AddWithValue("@id", lbinvoice.Text);
                    cmd1.Parameters.AddWithValue("@date", lbldate.Text);
                    cmd1.Parameters.AddWithValue("@time", lbltime.Text);
                    cmd1.Parameters.AddWithValue("@cashername", label6.Text);
                    cmd1.Parameters.AddWithValue("@qty", lbitems.Text);

                    cmd1.Parameters.AddWithValue("@grosstotal", lbtotal.Text);

                    con.Open();
</code>```

Instead if should be done like this:

```<code>        private void button1_Click(object sender, EventArgs e)
        {
            try
            {

                MySqlCommand cmd = new MySqlCommand();
                cmd.Connection = con;
                con.Open();

                cmd.CommandText = "Insert into salesproducts(saleid,productname,qty,grosstotal)values(@saleid,@productname,@qty,@grosstotal)";
                MySqlCommand cmd1 = new MySqlCommand();
                cmd1.Connection = con;
                cmd1.CommandText = "insert into salesmain(id,date,time,cashername,qty,grosstotal)values(@id,@date,@time,@cashername,@qty,@grosstotal)";

                cmd.Parameters.Add ("@saleid", SqlDbType.Int);
                cmd.Parameters.Add ("@productname", SqlDbType.String);
                cmd.Parameters.Add ("@qty", ...);
                cmd.Parameters.Add ("@grosstotal", ...);

                cmd1.Parameters.Add("@id", ...);
                cmd1.Parameters.Add("@date", ...);
                cmd1.Parameters.Add("@time", ...);
                cmd1.Parameters.Add("@cashername", ...);
                cmd1.Parameters.Add("@qty", ...);

                for (int i = 0; i < dataGridView1.Rows.Count; i++)
                {

                    cmd.Parameters["@saleid"] = lbinvoice.Text;
                    cmd.Parameters["@productname"] = dataGridView1.Rows[i].Cells[2].Value;
                    cmd.Parameters["@qty"] = dataGridView1.Rows[i].Cells[3].Value;
                ....
                }
                con.Close();

</code>```

Also consider opening the connection only once at the beginning of the program and close it only once at the end.

Body:
My code is not working as I expected and I give the question to last days but I only checked after 2 days and I suppose my chance is gone to being answered. If that's wrong I'm asked second time excuse me well.

I have this weird going on to my codes with my visual studio pro. There are no error messages of disconnected loops. It seems like I give up to check something wrong all files of my point of sales project.

And I've given to updateb() and invoice(). So it's better off up like all codes in my specific file. So up like this.

using MySql.Data.MySqlClient;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace superpos3
{
    public partial class salesn : Form
    {
        public salesn()
        {
            InitializeComponent();
        }

       public static int totalPrice = 0;
        public static int payment = 0;
        public static int balance = 0;

        MySqlConnection con = new MySqlConnection("server= localhost; database =superpos;  username= root; password=; ");

        public void invoice()
        {

            con.Open();
            string query = "select max(id) from salesmain ";
            MySqlCommand cmd2 = new MySqlCommand(query, con);
            MySqlDataReader dr;
            dr = cmd2.ExecuteReader();
            if (dr.Read())
            {
                string val = dr[0].ToString();
                if (val == "")
                {
                    lbinvoice.Text = "1";

                }
                else
                {
                    int a;

                    a = int.Parse(dr[0].ToString());
                    a = a + 1;
                    lbinvoice.Text = a.ToString();

                }
                con.Close();
            }

        }

        private void richTextBox1_TextChanged(object sender, EventArgs e)
        {

        }

        private void txtno_KeyPress(object sender, KeyPressEventArgs e)
        {
            if (e.KeyChar == 13)
            {
                txtqty.Enabled = true;
                txtqty.Focus();
            }
        }

        private void txtqty_KeyPress(object sender, KeyPressEventArgs e)
        {
            if (e.KeyChar == 13)
            {

                try
                {

                    string txt = "select * from products where id='" + txtno.Text + "'";
                    MySqlCommand cmd = new MySqlCommand(txt, con);
                    con.Open();
                    MySqlDataReader r = cmd.ExecuteReader();
                    while (r.Read())
                    {
                        int price = int.Parse(txtqty.Text.ToString()) * int.Parse(r[4].ToString());
                        totalPrice = totalPrice + price;
                        //discount
                        // totalPrice = totalPrice - totalPrice* Payment.discount/100;

                        dataGridView1.Rows.Add(dataGridView1.RowCount, r[0], r[1], txtqty.Text.Trim(), r[4], price);

                    }
                    lbitems.Text = " " + (dataGridView1.RowCount - 1) + "";
                    lbtotal.Text = " " + totalPrice + " ";

                    con.Close();

                }

                catch (Exception ee)
                {
                    MessageBox.Show(ee.Message, "Error From Database");
                }

                txtno.Focus();
                txtno.Clear();

                txtqty.Enabled = false;
                txtqty.Clear();

            }

        }

        private void txtqty_TextChanged(object sender, EventArgs e)
        {

        }
        private string name;

        public string Staffname
        {
            get { return name; }
            set { name = value; }

        }

      public void updatedb()
        {

            for (int row = 0; row < dataGridView1.Rows.Count; row++)
            {

                string itmno = dataGridView1.Rows[row].Cells[1].Value.ToString();
                string itmqty = dataGridView1.Rows[row].Cells[3].Value.ToString();

                string t = "select * from products where id= '"+ itmno + "'";

                string oldqty = "", newqty = "";

                Connnew.DbSearch(t);

                while (Connnew.dr.Read())
                {

                    oldqty = Connnew.dr[5].ToString();
                    newqty = (int.Parse(oldqty) - int.Parse(itmqty)).ToString();
                }

                string t2 = "update products SET qty = '" + newqty + "' WHERE id = '" + itmno + "'";
                //t2 = t2.Replace("{0}", itmno);
                //t2 = t2.Replace("{2}", newqty);
                Connnew.DbUpdate(t2);
            }

        }

        private void salesn_Load(object sender, EventArgs e)
        {
            label6.Text = Staffname;
            lbldate.Text = DateTime.Today.ToString("dd/MM/yyyy");
            lbltime.Text = DateTime.Now.ToShortTimeString();

            invoice();

        }

        private void button1_Click(object sender, EventArgs e)
        {
            try
            {

                for (int i = 0; i < dataGridView1.Rows.Count; i++)
                {

                    MySqlCommand cmd = new MySqlCommand();
                    cmd.Connection = con;

                    cmd.CommandText = "Insert into salesproducts(saleid,productname,qty,grosstotal)values(@saleid,@productname,@qty,@grosstotal)";
                    cmd.Parameters.AddWithValue("@saleid", lbinvoice.Text);
                    cmd.Parameters.AddWithValue("@productname", dataGridView1.Rows[i].Cells[2].Value);
                    cmd.Parameters.AddWithValue("@qty", dataGridView1.Rows[i].Cells[3].Value);
                    cmd.Parameters.AddWithValue("@grosstotal", dataGridView1.Rows[i].Cells[4].Value);

                    MySqlCommand cmd1 = new MySqlCommand();
                    cmd1.Connection = con;
                    cmd1.CommandText = "insert into salesmain(id,date,time,cashername,qty,grosstotal)values(@id,@date,@time,@cashername,@qty,@grosstotal)";
                    cmd1.Parameters.AddWithValue("@id", lbinvoice.Text);
                    cmd1.Parameters.AddWithValue("@date", lbldate.Text);
                    cmd1.Parameters.AddWithValue("@time", lbltime.Text);
                    cmd1.Parameters.AddWithValue("@cashername", label6.Text);
                    cmd1.Parameters.AddWithValue("@qty", lbitems.Text);

                    cmd1.Parameters.AddWithValue("@grosstotal", lbtotal.Text);

                    con.Open();
                   int x = cmd.ExecuteNonQuery();
                   int y = cmd1.ExecuteNonQuery();

                    MessageBox.Show("Record added ..........");
                    updatedb();

             //until here everything worked fine but if additionally given below codes not wroking
               even the updatedb().

                    dataGridView1.Rows.Clear();
                    lbtotal.Text = "0";
                    lbitems.Text = "0";
                    txtno.Focus();
                    totalPrice = 0;

                    con.Close();
                    invoice();

                }
               }
            catch (Exception ex)
            {
                //MessageBox.Show(ex.Message);
            }

            finally
            {
                con.Close();
            }
           }

        private void button2_Click(object sender, EventArgs e)
        {
            pay p = new pay();
            p.Show();
        }

        private void label6_Click(object sender, EventArgs e)
        {

        }
    }
}

And I'm seeing everything is fine and still not find the issue of those.

And the connected with above related to Connnew.DbSearch(t) that "Connnew" is like:

using MySql.Data.MySqlClient;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using MySql.Data.MySqlClient;
namespace superpos3
{
    class Connnew
    {

        public static MySqlConnection con = new MySqlConnection("server= localhost; database =superpos; username= root; password=; ");
        public static MySqlCommand poscmd = new MySqlCommand();
        public static MySqlDataReader dr;

        public static void DbSearch(string txt)
        {

            con.Close();
            poscmd.Connection = con;
            poscmd.CommandText = txt;
            con.Open();
            dr = poscmd.ExecuteReader();
        }

        public static void DbUpdate(string txt)
        {
            con.Close();
            poscmd.Connection = con;
            poscmd.CommandText = txt;
            con.Open();
            poscmd.ExecuteNonQuery();
        }
    }
}

I couldn't display the picture wholly screenshot or there is no permission here whatever. Please click down the below links.

please watch the sales window here

then please watch this one to know whats not work

Please let me know what is here the issue of the structure of codes or what is really going wrong...............(this question is ended and updated my question below)

I checked all but except the form1.cs file are irrelevant of the problem here. So additionally for here:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace superpos3
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {

        }

        private void timer1_Tick(object sender, EventArgs e)
        {
            progressBar1.Value = progressBar1.Value + 1;
            if (progressBar1.Value >= 100)
            {
                Login In = new Login();
                this.Hide();
                In.Show();

                timer1.Enabled = true;
                progressBar1.Visible = false;
                timer1.Enabled = false;
            }
        }

        private void progressBar1_Click(object sender, EventArgs e)
        {

        }
    }
}

Body:
General recommendation. Please consider changing the code in many places. And don't wrap the MySqlConnection into object because it is already object oriented.
You should not add parameters and open connection at each iteration like this:

        private void button1_Click(object sender, EventArgs e)
        {
            try
            {

                for (int i = 0; i < dataGridView1.Rows.Count; i++)
                {

                    MySqlCommand cmd = new MySqlCommand();
                    cmd.Connection = con;

                    cmd.CommandText = "Insert into salesproducts(saleid,productname,qty,grosstotal)values(@saleid,@productname,@qty,@grosstotal)";
                    cmd.Parameters.AddWithValue("@saleid", lbinvoice.Text);
                    cmd.Parameters.AddWithValue("@productname", dataGridView1.Rows[i].Cells[2].Value);
                    cmd.Parameters.AddWithValue("@qty", dataGridView1.Rows[i].Cells[3].Value);
                    cmd.Parameters.AddWithValue("@grosstotal", dataGridView1.Rows[i].Cells[4].Value);

                    MySqlCommand cmd1 = new MySqlCommand();
                    cmd1.Connection = con;
                    cmd1.CommandText = "insert into salesmain(id,date,time,cashername,qty,grosstotal)values(@id,@date,@time,@cashername,@qty,@grosstotal)";
                    cmd1.Parameters.AddWithValue("@id", lbinvoice.Text);
                    cmd1.Parameters.AddWithValue("@date", lbldate.Text);
                    cmd1.Parameters.AddWithValue("@time", lbltime.Text);
                    cmd1.Parameters.AddWithValue("@cashername", label6.Text);
                    cmd1.Parameters.AddWithValue("@qty", lbitems.Text);

                    cmd1.Parameters.AddWithValue("@grosstotal", lbtotal.Text);

                    con.Open();

Instead if should be done like this:

        private void button1_Click(object sender, EventArgs e)
        {
            try
            {

                MySqlCommand cmd = new MySqlCommand();
                cmd.Connection = con;
                con.Open();

                cmd.CommandText = "Insert into salesproducts(saleid,productname,qty,grosstotal)values(@saleid,@productname,@qty,@grosstotal)";
                MySqlCommand cmd1 = new MySqlCommand();
                cmd1.Connection = con;
                cmd1.CommandText = "insert into salesmain(id,date,time,cashername,qty,grosstotal)values(@id,@date,@time,@cashername,@qty,@grosstotal)";

                cmd.Parameters.Add ("@saleid", SqlDbType.Int);
                cmd.Parameters.Add ("@productname", SqlDbType.String);
                cmd.Parameters.Add ("@qty", ...);
                cmd.Parameters.Add ("@grosstotal", ...);

                cmd1.Parameters.Add("@id", ...);
                cmd1.Parameters.Add("@date", ...);
                cmd1.Parameters.Add("@time", ...);
                cmd1.Parameters.Add("@cashername", ...);
                cmd1.Parameters.Add("@qty", ...);

                for (int i = 0; i < dataGridView1.Rows.Count; i++)
                {

                    cmd.Parameters["@saleid"] = lbinvoice.Text;
                    cmd.Parameters["@productname"] = dataGridView1.Rows[i].Cells[2].Value;
                    cmd.Parameters["@qty"] = dataGridView1.Rows[i].Cells[3].Value;
                ....
                }
                con.Close();

Also consider opening the connection only once at the beginning of the program and close it only once at the end.


来源: stackexchange

问:
ASP.NET Identity Core - too many role related queries
My project uses role-based authorization and it has over 100 roles. I've noticed that before every action, server queries each user role and it's claims separately. That's over 200 queries before each action. Even an empty controller does this, so I assume this is ASP.NET Identity Core functionality. Is there any way to optimize this?

Thanks in advance.

```<code>ASP.NET Core web server output (one out of many role queries):

info: Microsoft.EntityFrameworkCore.Database.Command[20101]
      Executed DbCommand (1ms) [Parameters=[@__role_Id_0='390'], CommandType='Text', CommandTimeout='30']
      SELECT [rc].[ClaimType], [rc].[ClaimValue]
      FROM [AspNetRoleClaims] AS [rc]
      WHERE [rc].[RoleId] = @__role_Id_0
info: Microsoft.EntityFrameworkCore.Database.Command[20101]
      Executed DbCommand (1ms) [Parameters=[@__normalizedName_0='100' (Size = 256)], CommandType='Text', CommandTimeout='30']
      SELECT TOP(1) [r].[Id], [r].[ConcurrencyStamp], [r].[Name], [r].[NormalizedName]
      FROM [AspNetRoles] AS [r]
      WHERE [r].[NormalizedName] = @__normalizedName_0
</code>```

My Startup.cs class:

```<code>    public class Startup
    {
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }

        public IConfiguration Configuration { get; }

        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            services.Configure<CookiePolicyOptions>(options =>
            {
                // This lambda determines whether user consent for non-essential cookies
                // is needed for a given request.
                options.CheckConsentNeeded = context => true;
                options.MinimumSameSitePolicy = SameSiteMode.None;
            });

            services.AddRouting(options => options.LowercaseUrls = true);
            services.AddDistributedMemoryCache();
            services.AddSession(options =>
            {
                options.IdleTimeout = TimeSpan.FromDays(1);
                options.Cookie.IsEssential = true;
            });

            services.AddDbContext<AppDbContext>(options =>
                options
                    .EnableSensitiveDataLogging()
                    .UseSqlServer(Configuration.GetConnectionString("DefaultConnection"), x =>
                    {
                        x.UseRowNumberForPaging();
                        x.UseNetTopologySuite();
                    }));

            services.Configure<WebEncoderOptions>(options =>
            {
                options.TextEncoderSettings = new TextEncoderSettings(UnicodeRanges.All);
            });

            services.Configure<AppConfiguration>(
                Configuration.GetSection("AppConfiguration"));

            services.AddIdentity<User, UserRole>()
                .AddEntityFrameworkStores<AppDbContext>()
                .AddDefaultTokenProviders();

            services.Configure<IdentityOptions>(options =>
            {
                // Password settings
                options.Password.RequireDigit = true;
                options.Password.RequiredLength = 8;
                options.Password.RequireNonAlphanumeric = false;
                options.Password.RequireUppercase = true;
                options.Password.RequireLowercase = false;
                options.Password.RequiredUniqueChars = 6;

                // Lockout settings
                options.Lockout.DefaultLockoutTimeSpan = TimeSpan.FromMinutes(30);
                options.Lockout.MaxFailedAccessAttempts = 10;
                options.Lockout.AllowedForNewUsers = true;

                // User settings
                options.User.RequireUniqueEmail = true;
            });

            services.Configure<SecurityStampValidatorOptions>(options =>
            {
                // enables immediate logout, after updating the users stat.
                options.ValidationInterval = TimeSpan.Zero;
            });

            services.ConfigureApplicationCookie(options =>
            {
                // Cookie settings
                options.Cookie.HttpOnly = true;
                options.Cookie.Expiration = TimeSpan.FromDays(150);
                // If the LoginPath isn't set, ASP.NET Core defaults
                // the path to /Account/Login.
                options.LoginPath = "/Account/Login";
                // If the AccessDeniedPath isn't set, ASP.NET Core defaults
                // the path to /Account/AccessDenied.
                options.AccessDeniedPath = "/Account/AccessDenied";
                options.SlidingExpiration = true;
            });

            // Add application services.
            services.AddScoped<IEmailSenderService, EmailSenderService>();
            services.AddScoped<IUploaderService, UploaderService>();
            services.AddScoped<IPdfService, PdfService>();
            services.AddScoped<ICurrencyRateService, CurrencyRateService>();
            services.AddScoped<IViewRenderService, ViewRenderService>();
            services.AddScoped<IUserCultureInfoService, UserCultureInfoService>();
            services.AddScoped<IUserService, UserService>();
            services.AddHostedService<QueuedHostedService>();
            services.AddSingleton<IBackgroundTaskQueue, BackgroundTaskQueue>();

            services
                .AddMvc(options =>
                {
                    options.EnableEndpointRouting = false;

                    options
                        .RegisterDateTimeProvider(services)
                        .ModelMetadataDetailsProviders
                        .Add(new BindingSourceMetadataProvider(typeof(ListFilterViewModel), BindingSource.ModelBinding));
                })
                .AddSessionStateTempDataProvider()
                .SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IHostingEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
                app.UseDatabaseErrorPage();
                // app.UseMiddleware<StackifyMiddleware.RequestTracerMiddleware>();
            }
            else
            {
#if DEBUG
                app.UseDeveloperExceptionPage();
#else
                app.UseExceptionHandler("/Default/Error");
#endif

                app.UseHsts();
            }

            app.UseHttpsRedirection();
            app.UseStaticFiles();
            app.UseSession();
            app.UseCookiePolicy();
            app.UseAuthentication();

            app.UseMvc(routes =>
            {
                routes.MapAreaRoute(
                    name: "Hubs",
                    areaName:"Hubs",
                    template: "Hubs/{controller=CompanyAddresses}/{action=Index}/{id?}");

                routes.MapRoute(
                    name: "areas",
                    template: "{area:exists}/{controller=Default}/{action=Index}/{id?}"
                );

                routes.MapRoute(
                    name: "default",
                    template: "{controller=Default}/{action=Index}/{id?}");
            });
        }
    }
</code>```

答:
I have found out what causes this weird behavior. It's this code segment in my Startup.cs class:

```<code>services.Configure<SecurityStampValidatorOptions>(options =>
{
    // enables immediate logout, after updating the users stat.
    options.ValidationInterval = TimeSpan.Zero;
});
</code>```

Removing it solved my problem. I've been using this to force logout users by updating their security stamp as described here: How to sign out other user in ASP.NET Core Identity

It seems I will have to look for other solution for force logout, but I'm happy that requests are now not generating hundreds of SQL queries.

ContentLicense: CC BY-SA 4.0

Body:
My project uses role-based authorization and it has over 100 roles. I've noticed that before every action, server queries each user role and it's claims separately. That's over 200 queries before each action. Even an empty controller does this, so I assume this is ASP.NET Identity Core functionality. Is there any way to optimize this?

Thanks in advance.

ASP.NET Core web server output (one out of many role queries):

info: Microsoft.EntityFrameworkCore.Database.Command[20101]
      Executed DbCommand (1ms) [Parameters=[@__role_Id_0='390'], CommandType='Text', CommandTimeout='30']
      SELECT [rc].[ClaimType], [rc].[ClaimValue]
      FROM [AspNetRoleClaims] AS [rc]
      WHERE [rc].[RoleId] = @__role_Id_0
info: Microsoft.EntityFrameworkCore.Database.Command[20101]
      Executed DbCommand (1ms) [Parameters=[@__normalizedName_0='100' (Size = 256)], CommandType='Text', CommandTimeout='30']
      SELECT TOP(1) [r].[Id], [r].[ConcurrencyStamp], [r].[Name], [r].[NormalizedName]
      FROM [AspNetRoles] AS [r]
      WHERE [r].[NormalizedName] = @__normalizedName_0

My Startup.cs class:

    public class Startup
    {
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }

        public IConfiguration Configuration { get; }

        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            services.Configure<CookiePolicyOptions>(options =>
            {
                // This lambda determines whether user consent for non-essential cookies
                // is needed for a given request.
                options.CheckConsentNeeded = context => true;
                options.MinimumSameSitePolicy = SameSiteMode.None;
            });

            services.AddRouting(options => options.LowercaseUrls = true);
            services.AddDistributedMemoryCache();
            services.AddSession(options =>
            {
                options.IdleTimeout = TimeSpan.FromDays(1);
                options.Cookie.IsEssential = true;
            });

            services.AddDbContext<AppDbContext>(options =>
                options
                    .EnableSensitiveDataLogging()
                    .UseSqlServer(Configuration.GetConnectionString("DefaultConnection"), x =>
                    {
                        x.UseRowNumberForPaging();
                        x.UseNetTopologySuite();
                    }));

            services.Configure<WebEncoderOptions>(options =>
            {
                options.TextEncoderSettings = new TextEncoderSettings(UnicodeRanges.All);
            });

            services.Configure<AppConfiguration>(
                Configuration.GetSection("AppConfiguration"));

            services.AddIdentity<User, UserRole>()
                .AddEntityFrameworkStores<AppDbContext>()
                .AddDefaultTokenProviders();

            services.Configure<IdentityOptions>(options =>
            {
                // Password settings
                options.Password.RequireDigit = true;
                options.Password.RequiredLength = 8;
                options.Password.RequireNonAlphanumeric = false;
                options.Password.RequireUppercase = true;
                options.Password.RequireLowercase = false;
                options.Password.RequiredUniqueChars = 6;

                // Lockout settings
                options.Lockout.DefaultLockoutTimeSpan = TimeSpan.FromMinutes(30);
                options.Lockout.MaxFailedAccessAttempts = 10;
                options.Lockout.AllowedForNewUsers = true;

                // User settings
                options.User.RequireUniqueEmail = true;
            });

            services.Configure<SecurityStampValidatorOptions>(options =>
            {
                // enables immediate logout, after updating the users stat.
                options.ValidationInterval = TimeSpan.Zero;
            });

            services.ConfigureApplicationCookie(options =>
            {
                // Cookie settings
                options.Cookie.HttpOnly = true;
                options.Cookie.Expiration = TimeSpan.FromDays(150);
                // If the LoginPath isn't set, ASP.NET Core defaults
                // the path to /Account/Login.
                options.LoginPath = "/Account/Login";
                // If the AccessDeniedPath isn't set, ASP.NET Core defaults
                // the path to /Account/AccessDenied.
                options.AccessDeniedPath = "/Account/AccessDenied";
                options.SlidingExpiration = true;
            });

            // Add application services.
            services.AddScoped<IEmailSenderService, EmailSenderService>();
            services.AddScoped<IUploaderService, UploaderService>();
            services.AddScoped<IPdfService, PdfService>();
            services.AddScoped<ICurrencyRateService, CurrencyRateService>();
            services.AddScoped<IViewRenderService, ViewRenderService>();
            services.AddScoped<IUserCultureInfoService, UserCultureInfoService>();
            services.AddScoped<IUserService, UserService>();
            services.AddHostedService<QueuedHostedService>();
            services.AddSingleton<IBackgroundTaskQueue, BackgroundTaskQueue>();

            services
                .AddMvc(options =>
                {
                    options.EnableEndpointRouting = false;

                    options
                        .RegisterDateTimeProvider(services)
                        .ModelMetadataDetailsProviders
                        .Add(new BindingSourceMetadataProvider(typeof(ListFilterViewModel), BindingSource.ModelBinding));
                })
                .AddSessionStateTempDataProvider()
                .SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IHostingEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
                app.UseDatabaseErrorPage();
                // app.UseMiddleware<StackifyMiddleware.RequestTracerMiddleware>();
            }
            else
            {
#if DEBUG
                app.UseDeveloperExceptionPage();
#else
                app.UseExceptionHandler("/Default/Error");
#endif

                app.UseHsts();
            }

            app.UseHttpsRedirection();
            app.UseStaticFiles();
            app.UseSession();
            app.UseCookiePolicy();
            app.UseAuthentication();

            app.UseMvc(routes =>
            {
                routes.MapAreaRoute(
                    name: "Hubs",
                    areaName:"Hubs",
                    template: "Hubs/{controller=CompanyAddresses}/{action=Index}/{id?}");

                routes.MapRoute(
                    name: "areas",
                    template: "{area:exists}/{controller=Default}/{action=Index}/{id?}"
                );

                routes.MapRoute(
                    name: "default",
                    template: "{controller=Default}/{action=Index}/{id?}");
            });
        }
    }

Body:
I have found out what causes this weird behavior. It's this code segment in my Startup.cs class:

services.Configure<SecurityStampValidatorOptions>(options =>
{
    // enables immediate logout, after updating the users stat.
    options.ValidationInterval = TimeSpan.Zero;
});

Removing it solved my problem. I've been using this to force logout users by updating their security stamp as described here: How to sign out other user in ASP.NET Core Identity

It seems I will have to look for other solution for force logout, but I'm happy that requests are now not generating hundreds of SQL queries.


问:
Why will my images/script not show up on asp.net mvc deployed site?
I have deployed an app to an IIS6 server.  For now, I'm using the wildcard mapping.  My app works perfectly fine on my development machine, but when I try to access it on the server, some pages work and some don't.

It is the scripts & images that are giving me the biggest problem.

I have a url http://localhost/sdev/home/index and the page comes up fine except the images and scripts don't load.  When I view source and look at the url I see:

```<code>../../Content/Images/logo.png
</code>```

If I try to navigate to that url, it tries to go to

```<code>http://localhost/content/images/logo.png
</code>```

instead of

```<code>http://localhost/sdev/content/images/logo.png
</code>```

The strange thing is that some pages work fine, such as:

```<code>http://localhost/sdev/ServiceCall/DivisionStep/ALB?type=fsr
</code>```

Any ideas on what I can do to fix this?  Yes, I have read Phil's instructions and thought I followed them correctly but maybe I missed something.

答:
Use

```<code><%= Url.Content("~/Content/Images/logo.png") %>
</code>```

to generate the urls and you should be ok.

OwnerDisplayName: Mike Roosa

ContentLicense: CC BY-SA 2.5

Body:
I have deployed an app to an IIS6 server.  For now, I'm using the wildcard mapping.  My app works perfectly fine on my development machine, but when I try to access it on the server, some pages work and some don't.

It is the scripts & images that are giving me the biggest problem.

I have a url http://localhost/sdev/home/index and the page comes up fine except the images and scripts don't load.  When I view source and look at the url I see:

../../Content/Images/logo.png

If I try to navigate to that url, it tries to go to

http://localhost/content/images/logo.png

instead of

http://localhost/sdev/content/images/logo.png

The strange thing is that some pages work fine, such as:

http://localhost/sdev/ServiceCall/DivisionStep/ALB?type=fsr

Any ideas on what I can do to fix this?  Yes, I have read Phil's instructions and thought I followed them correctly but maybe I missed something.

Body:
Use

<%= Url.Content("~/Content/Images/logo.png") %>

to generate the urls and you should be ok.

OwnerDisplayName: liammclennan


问:
illegal 0000-00-00 00:00:00 timestamp being sent by php to mysql using codeigniter
here is a Database_update_entry function in my CodeIgniter model which gets executed upon successful form submission.

```<code><?php
    function update_entry(){
        $data = array(
            'sl' => $this->input->post('item_sl'),
            'item_name' => $this->input->post('item_name'),
            'img_url' => $this->input->post('img_url'),
            'sound_url' => $this->input->post('sound_url'),
            'price' => $this->input->post('price'),
            'unit' => $this->input->post('unit'),
            'timestamp' => time(),
        );
        echo "current time: ".  time();
        $this->db->update(MY_TABLE_NAME, $data);
    }
?>
</code>```

the database query gets executed fine.... but the time that gets set into the mysql table is
0000-00-00 00:00:00 whereas the <?php echo time() ?> statement shows 1307018223 in the browser.... which is a valid UNIX timestamp... you can check the timestamp validity here.

here is a screenshot of the table that takes data from mySQL table after successful update_queryhttp://s3.amazonaws.com/awesome_screenshot/658523?AWSAccessKeyId=0R7FMW7AXRVCYMAPTPR2&Expires=1307020816&Signature=AncPjnzG9p9QTX7zebZp7c9teB0%3D

what am i doing wrong??? how can i pass a legal timestamp from my php to mySQL?
[p.s. i have checked that the timestamp field in my mysql table is a timestamp field]

答: format time : date('Y-m-d H:i:s', time())

ContentLicense: CC BY-SA 3.0

Body:
here is a Database_update_entry function in my CodeIgniter model which gets executed upon successful form submission.

<?php
    function update_entry(){
        $data = array(
            'sl' => $this->input->post('item_sl'),
            'item_name' => $this->input->post('item_name'),
            'img_url' => $this->input->post('img_url'),
            'sound_url' => $this->input->post('sound_url'),
            'price' => $this->input->post('price'),
            'unit' => $this->input->post('unit'),
            'timestamp' => time(),
        );
        echo "current time: ".  time();
        $this->db->update(MY_TABLE_NAME, $data);
    }
?>

the database query gets executed fine.... but the time that gets set into the mysql table is
0000-00-00 00:00:00 whereas the <?php echo time() ?> statement shows 1307018223 in the browser.... which is a valid UNIX timestamp... you can check the timestamp validity here.

here is a screenshot of the table that takes data from mySQL table after successful update_queryhttp://s3.amazonaws.com/awesome_screenshot/658523?AWSAccessKeyId=0R7FMW7AXRVCYMAPTPR2&Expires=1307020816&Signature=AncPjnzG9p9QTX7zebZp7c9teB0%3D

what am i doing wrong??? how can i pass a legal timestamp from my php to mySQL?
[p.s. i have checked that the timestamp field in my mysql table is a timestamp field]


问:
How to fix 'Android Soft Keyboard not returning KeyCode'
i'm fairly new to Android and i am trying to create an app that outputs the key code of a soft keyboard input (the android keyboard on screen, NOT a physical keyboard) to a text file from an edit text field.

So the user will type in text into an edit text such as "hello World" and i want to output the key code for each of those to a text file.

I will eventually get the Keyup system time and the keydown system time but that's a later me problem!

I've tried various different methods such as writing my own soft keyboard and using that, as well as using a switch statement for each character. The following code is my main activity:

```<code>package com.example.useridentificationapp;

import android.Manifest;
import android.content.pm.PackageManager;
import android.os.Build;
import android.os.Environment;
import android.support.annotation.NonNull;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.KeyEvent;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;
import android.os.Parcelable;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

public class MainActivity extends AppCompatActivity{

    EditText et_name, et_content;
    Button b_save;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE)
            != PackageManager.PERMISSION_GRANTED) {
            requestPermissions(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, 1000);
        }
        et_name = (EditText) findViewById(R.id.et_name);
        et_content = (EditText) findViewById(R.id.et_content);
        final TextView view = (TextView) findViewById(R.id.view);
        final EditText log  = (EditText) findViewById(R.id.log);
        b_save = (Button) findViewById(R.id.b_save);

        et_content.setOnKeyListener(new View.OnKeyListener(){
            public boolean onKey(View v, int keyCode, KeyEvent event) {
                String keyCodeStr = KeyEvent.keyCodeToString(keyCode);
                view.setText(String.valueOf(keyCodeStr));
                log.setText(keyCodeStr + " " + log.getText());
                return true;
            }
        });

        b_save.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
              String filename = et_name.getText().toString();
              String content = et_content.getText().toString();

              saveTextAsFile(filename, content);
            }
        });
    }

    private void saveTextAsFile (String filename, String content){
        String fileName = filename + ".txt";

        //create file
        File file = new File (Environment.getExternalStorageDirectory().getAbsolutePath(), fileName);

        //write to file
        try {
            FileOutputStream fos = new FileOutputStream(file);
            fos.write(content.getBytes());
            fos.close();
            Toast.makeText(this, "Saved", Toast.LENGTH_SHORT).show();
        } catch (FileNotFoundException e){
            e.printStackTrace();
            Toast.makeText(this, "File not found", Toast.LENGTH_SHORT).show();
        } catch (IOException e){
            e.printStackTrace();
            Toast.makeText(this, "Error saving", Toast.LENGTH_SHORT).show();
        }
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        switch (requestCode){
            case 1000:
                if (grantResults[0] == PackageManager.PERMISSION_GRANTED){
                    Toast.makeText(this, "Permission Granted", Toast.LENGTH_SHORT).show();
                } else{
                    Toast.makeText(this, "Permission Not Granted", Toast.LENGTH_SHORT).show();
                    finish();
                }
        }
    }

}
</code>```

The code above only returns "KEYCODE_ENTER", "KEYCODE_BACK", "KEYCODE_SHIFT" and "KEYCODE_DELETE". This is fine but i want it to return that for each key press so for example if the user pressed A on the keyboard, i would like it to output "KEYCODE_A". I do not get anything in the "log" (a field i created to display the Keycode for debugging), for any other key, it just stays empty, however the key does type into the field.

I would then like to save this in a text file.

Any help would be greatly appreciated! I've read loads of android documentation on KeyEvent and associated methods but i can't seem to get anything working!

Thank you very much in advance for your help! I have spent a good few days (and many hours scouring the internet for help but to no avail!)

答:
Just to answer this, it cannot actually be done due to the way that Android handles soft keyboard inputs.

To resolve the issue i had to recreate a keyboard layout of buttons on the screen which then worked.

Body:
i'm fairly new to Android and i am trying to create an app that outputs the key code of a soft keyboard input (the android keyboard on screen, NOT a physical keyboard) to a text file from an edit text field.

So the user will type in text into an edit text such as "hello World" and i want to output the key code for each of those to a text file.

I will eventually get the Keyup system time and the keydown system time but that's a later me problem!

I've tried various different methods such as writing my own soft keyboard and using that, as well as using a switch statement for each character. The following code is my main activity:

package com.example.useridentificationapp;

import android.Manifest;
import android.content.pm.PackageManager;
import android.os.Build;
import android.os.Environment;
import android.support.annotation.NonNull;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.KeyEvent;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;
import android.os.Parcelable;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

public class MainActivity extends AppCompatActivity{

    EditText et_name, et_content;
    Button b_save;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE)
            != PackageManager.PERMISSION_GRANTED) {
            requestPermissions(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, 1000);
        }
        et_name = (EditText) findViewById(R.id.et_name);
        et_content = (EditText) findViewById(R.id.et_content);
        final TextView view = (TextView) findViewById(R.id.view);
        final EditText log  = (EditText) findViewById(R.id.log);
        b_save = (Button) findViewById(R.id.b_save);

        et_content.setOnKeyListener(new View.OnKeyListener(){
            public boolean onKey(View v, int keyCode, KeyEvent event) {
                String keyCodeStr = KeyEvent.keyCodeToString(keyCode);
                view.setText(String.valueOf(keyCodeStr));
                log.setText(keyCodeStr + " " + log.getText());
                return true;
            }
        });

        b_save.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
              String filename = et_name.getText().toString();
              String content = et_content.getText().toString();

              saveTextAsFile(filename, content);
            }
        });
    }

    private void saveTextAsFile (String filename, String content){
        String fileName = filename + ".txt";

        //create file
        File file = new File (Environment.getExternalStorageDirectory().getAbsolutePath(), fileName);

        //write to file
        try {
            FileOutputStream fos = new FileOutputStream(file);
            fos.write(content.getBytes());
            fos.close();
            Toast.makeText(this, "Saved", Toast.LENGTH_SHORT).show();
        } catch (FileNotFoundException e){
            e.printStackTrace();
            Toast.makeText(this, "File not found", Toast.LENGTH_SHORT).show();
        } catch (IOException e){
            e.printStackTrace();
            Toast.makeText(this, "Error saving", Toast.LENGTH_SHORT).show();
        }
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        switch (requestCode){
            case 1000:
                if (grantResults[0] == PackageManager.PERMISSION_GRANTED){
                    Toast.makeText(this, "Permission Granted", Toast.LENGTH_SHORT).show();
                } else{
                    Toast.makeText(this, "Permission Not Granted", Toast.LENGTH_SHORT).show();
                    finish();
                }
        }
    }

}

The code above only returns "KEYCODE_ENTER", "KEYCODE_BACK", "KEYCODE_SHIFT" and "KEYCODE_DELETE". This is fine but i want it to return that for each key press so for example if the user pressed A on the keyboard, i would like it to output "KEYCODE_A". I do not get anything in the "log" (a field i created to display the Keycode for debugging), for any other key, it just stays empty, however the key does type into the field.

I would then like to save this in a text file.

Any help would be greatly appreciated! I've read loads of android documentation on KeyEvent and associated methods but i can't seem to get anything working!

Thank you very much in advance for your help! I have spent a good few days (and many hours scouring the internet for help but to no avail!)


问:
Problem when toggling between coordinates of a wavefront (.obj) in three.js
So I have a slider in my HTML with values ranging from 1 to 2. When I have the slider value set to 1, I want to set the coordinates of my wavefront to the one described by arrayMin and when the slider is set to 2, I want the coordinates of my wavefront to set to one described by arrayMin.

man is the name of the variable that I used to load the obj in threejs using OBJLoader.

```<code>function render(time)
    {

        let valueOfSlider = document.getElementById('mySlider').value
        scene.remove(man)
        if (valueOfSlider == 1){
                console.log("I want arrayMin to be set")
                man.children[0].geometry.attributes.position.array=Float32Array.from(arrayMin)
            }
        else
        {
                console.log("I want array Max to be set")
                man.children[0].geometry.attributes.position.array=Float32Array.from(arrayMax)

        }
        scene.add(man)
        controls.update()
        renderer.render(scene,camera)
        requestAnimationFrame(render)

    }
</code>```

But it is not working.
The image shows a screenshot of the log, which clearly shows there is no needsUpdate field

答: The first comment worked, i.e., setting needsUpdate as true;</p>

Body:
So I have a slider in my HTML with values ranging from 1 to 2. When I have the slider value set to 1, I want to set the coordinates of my wavefront to the one described by arrayMin and when the slider is set to 2, I want the coordinates of my wavefront to set to one described by arrayMin.

man is the name of the variable that I used to load the obj in threejs using OBJLoader.

function render(time)
    {

        let valueOfSlider = document.getElementById('mySlider').value
        scene.remove(man)
        if (valueOfSlider == 1){
                console.log("I want arrayMin to be set")
                man.children[0].geometry.attributes.position.array=Float32Array.from(arrayMin)
            }
        else
        {
                console.log("I want array Max to be set")
                man.children[0].geometry.attributes.position.array=Float32Array.from(arrayMax)

        }
        scene.add(man)
        controls.update()
        renderer.render(scene,camera)
        requestAnimationFrame(render)

    }

But it is not working.
The image shows a screenshot of the log, which clearly shows there is no needsUpdate field


问:
How can I remove the select option black border in Chrome?
In the latest version of chrome(version:83), it is getting a black border in the select option. Is there any ways to fix it? I fixed the out-line issues of text box and buttons using the following styles

```<code>*,*:focus,*:hover{
outline:none !important;
</code>```

}

I checked the issue How do I remove the select option black border in Chrome? and it says the issue was due to the chrome update. Can we fix it using css?

答: I've tried my hardest in fixing the problem. The newest Chrome update has "upgraded" form handling in the browser. My suggestion was to add outline: none;, but that only works on <input />, <textarea> and <button> elements. As seen everywhere, there is something about disabling a flag, but if you want your site to go out to the public (webserver), this won't work, as disabling that flag only disables it on your computer. I really hope that Google fixes this issue, but they don't seem to notice the number of people complaining about this.

Body:
In the latest version of chrome(version:83), it is getting a black border in the select option. Is there any ways to fix it? I fixed the out-line issues of text box and buttons using the following styles

*,*:focus,*:hover{
outline:none !important;

}

I checked the issue How do I remove the select option black border in Chrome? and it says the issue was due to the chrome update. Can we fix it using css?


问:
Is there a way to have multiple Plotly-Dash maps refer to the same animation slider?
I am trying to have two plotly.express choropleth maps to be animated at the same time (and for the user to pick whichever date they wish) by using a single time slider, affecting both maps. The closest I got to was this:

But instead of two sliders, I want to have just one, which affects both maps at the same time.

I did search for the answer and there are approaches to that for plots (shown here), but I did not find them for maps, especially in express as the slider is created automatically so there is no easy way to change it/connect to another slider. I was therefore wondering if there is any elegant and way of using just one slider within express framework, before going into building a separate slider, moving away from the convenience of express maps and finding the events and somehow connecting them to maps. Thank you for your time!

答:
It is possible to use a single slider for both the graphs, but you would have to create your own slider component using dash core components for example:

```<code>dcc.Slider(
    id='my-slider',
    min=0,
    max=20,
    step=0.5,
    value=10,
),
</code>```

And then in a callback, have two graph outputs react using the slider input. Some pseudo code:

```<code>@app.callback([Output('graph1_id', 'figure'),
           Output('graph2_id', 'figure')],
          Input('my-slider', 'value'))
def change_display(slider_value):
call_fnct_changing_graph(slider_value)
</code>```

Body:
It is possible to use a single slider for both the graphs, but you would have to create your own slider component using dash core components for example:

dcc.Slider(
    id='my-slider',
    min=0,
    max=20,
    step=0.5,
    value=10,
),

And then in a callback, have two graph outputs react using the slider input. Some pseudo code:

@app.callback([Output('graph1_id', 'figure'),
           Output('graph2_id', 'figure')],
          Input('my-slider', 'value'))
def change_display(slider_value):
call_fnct_changing_graph(slider_value)


问:
leverage browser caching - expires or max-age, last-modified or etag
I'm having difficulty finding a clear-cut, practical explanation for what is the correct way to leverage browser caching to increase page speed.

According to this site:

It is important to specify one of Expires or Cache-Control max-age,
  and one of Last-Modified or ETag, for all cacheable resources. It is
  redundant to specify both Expires and Cache-Control: max-age, or to
  specify both Last-Modified and ETag.

Is this correct? If so, should I use Expires or max-age? I think I have a general understanding of what both of those are but don't know which is usually best to use.

If I have to also do Last-Modified or ETag, which one of those? I think I get Last-Modified but am still very fuzzy on this ETag concept.

Also, which files should I enable browser caching for?

答:
Is this correct?

Yes, Expires and max-age do the same thing, but in two different ways. Same thing with Last-Modified and Etag

If so, should I do
expires or max-age?

Expires depends on accuracy of user's clock, so it's mostly a bad choice (as most browsers support HTTP/1.1). Use max-age, to tell the browser that the file is good for that many seconds. For example, a 1 day cache would be:

Cache-Control: max-age=86400

Note that when both Cache-Control and Expires are present, Cache-Control takes precedence. read

If I have to also do Last-Modified or ETag, which one of those? I think I get Last-Modified

You're right, Last-Modified should be better. Although it's a time, it's sent by the server. Hence no issue with user's clock. It's the reason why Last-Modified is better than Expires.
The browser sends the Last-Modified the server sent last time it asked for the file, and if it's the same, the server answsers with an empty response «304 Not Modified»

Also, you must note that ETag can be useful too, because Last-Modified has a time window of one second. So you can't distinguish two different sources with the same Last-Modified value. [2]

Etag needs some more computing than Last-Modified, as it's a signature of the current state of the file (similar to a md5 sum or a CRC32).

Also, which files should I enable browser caching for?

All files can benefit caching. You've got two different approaches:

with max-age: useful for files that never change (images, CSS, javascript). For as long as the max-age value, the browser won't send any request to the server. So you'll see the page loading really fast on the second load. If you need to update files, just append a question mark, and the date of change (for example /image.png?20110602, or for better proxies caching, something like /20110602/image.png or /image.20110602.png). This way you can make files expire if it's urgent (remember that the browser almost never hits the server once it has a max-age file). Main use is to speed things up and limit requests sent to the server.

with Last-Modified: can be set on all files (including those with max-age). Even if you have dynamic pages, you may not change the content of the file for a while (even if it's 10 min), so that could be useful. The main use here is to tell the browser «keep asking me for this file, if it's new, I'll send you the new one». So, there's a request sent on each page load, but the answer is empty if the file is already good (304 Not Modified), so you save on bandwidth.

The more you cache, the faster your pages will show up. But it's a difficult task to flush caches, so use with care.

A good place to learn all this with many explanations: http://www.mnot.net/cache_docs/

[2]: rfc7232 Etag https://www.rfc-editor.org/rfc/rfc7232#section-2.3


问:
Pandas: create columns with deviation from mean in each group
Consider the following DataFrame in Python:

```<code>import pandas as pd
df = pd.DataFrame({'id':[0]*3+[1]*3,'y':np.random.randn(6),'x':np.random.randn(6)})
</code>```

which gives

```<code>   id         y         x
0   0  0.721757  1.595646
1   0  0.359601  1.128473
2   0  1.134922  2.317929
3   1  0.290152 -1.901336
4   1  0.128742  0.982683
5   1  0.556914  0.745208
</code>```

Note that y and x are grouped according to id. I want to creat the following DataFrame

```<code>   id         y         x      y_md      x_md
0   0  0.721757  1.595646 -0.017003 -0.085037
1   0  0.359601  1.128473 -0.379159 -0.552209
2   0  1.134922  2.317929  0.396162  0.637246
3   1  0.290152 -1.901336 -0.035117 -1.843521
4   1  0.128742  0.982683 -0.196527  1.040498
5   1  0.556914  0.745208  0.231644  0.803023
</code>```

where

y_md contains the value of deviation from its group mean (id=0 & 1)

x_md contains the value of deviation from its group mean (id=0 & 1)

What I came up with is

```<code>df_g = df.groupby('id')
yy = pd.Series( df['y'].values - df_g['y'].mean().repeat(3).values )
xx = pd.Series( df['x'].values - df_g['x'].mean().repeat(3).values )
pd.concat([df,yy.rename('y_md'), xx.rename('x_md')],axis=1)
</code>```

but it does not look good to me. I wonder if there is an elegant one liner or similar for the same result? I would appreciate your help.

Body:
Consider the following DataFrame in Python:

import pandas as pd
df = pd.DataFrame({'id':[0]*3+[1]*3,'y':np.random.randn(6),'x':np.random.randn(6)})

which gives

   id         y         x
0   0  0.721757  1.595646
1   0  0.359601  1.128473
2   0  1.134922  2.317929
3   1  0.290152 -1.901336
4   1  0.128742  0.982683
5   1  0.556914  0.745208

Note that y and x are grouped according to id. I want to creat the following DataFrame

   id         y         x      y_md      x_md
0   0  0.721757  1.595646 -0.017003 -0.085037
1   0  0.359601  1.128473 -0.379159 -0.552209
2   0  1.134922  2.317929  0.396162  0.637246
3   1  0.290152 -1.901336 -0.035117 -1.843521
4   1  0.128742  0.982683 -0.196527  1.040498
5   1  0.556914  0.745208  0.231644  0.803023

where

y_md contains the value of deviation from its group mean (id=0 & 1)

x_md contains the value of deviation from its group mean (id=0 & 1)

What I came up with is

df_g = df.groupby('id')
yy = pd.Series( df['y'].values - df_g['y'].mean().repeat(3).values )
xx = pd.Series( df['x'].values - df_g['x'].mean().repeat(3).values )
pd.concat([df,yy.rename('y_md'), xx.rename('x_md')],axis=1)

but it does not look good to me. I wonder if there is an elegant one liner or similar for the same result? I would appreciate your help.

Body:
Use GroupBy.transform for processing multiple columns, subtract by DataFrame.sub, change columns names by DataFrame.add_suffix and append to original by DataFrame.join:

c = ['x','y']
df = df.join(df[c].sub(df.groupby('id')[c].transform('mean')).add_suffix('_md'))
print (df)
   id         y         x      x_md      y_md
0   0  0.721757  1.595646 -0.085037 -0.017003
1   0  0.359601  1.128473 -0.552210 -0.379159
2   0  1.134922  2.317929  0.637246  0.396162
3   1  0.290152 -1.901336 -1.843521 -0.035117
4   1  0.128742  0.982683  1.040498 -0.196527
5   1  0.556914  0.745208  0.803023  0.231645

Or is possible assign new columns names:

df[['x_md','y_md']] = df[['x','y']].sub(df.groupby('id')[['x','y']].transform('mean'))


问:
I'm not able to POST data using JavaScript Ajax
I'm able to get the data from the filltext web api using Ajax GET request ,but when i use Post request then i can't see anything returned to the console and also no errors, how do i solve this?

const xhr = new XMLHttpRequest();
const url = 'http://www.filltext.com/?rows=1&pretty=true&id={index}&fname={sahil}&lname={keshav}&company={business}';

let test = JSON.stringify({
    id:124,
    fname:'sunil',
    lname:'singh',
    company:'reebok'
});

function getData(){
    xhr.onreadystatechange = () => {
        if(this.readyState === 4 && this.status === 200){
            let tes = JSON.parse(this.responseText)
            console.log(tes);
        }
    }
    xhr.open('POST',url,true);
    xhr.setRequestHeader('Content-type','application/json');
    xhr.send(test);
}
```

答:
Since you're making a POST request here, you probably need to check the status between 200 to 400. (I'm including 400 since after this typically codes for bad requests start)

this.status >= 200 && this.status < 400

Here are the links:

MDN- POST status

MDN-statuses

201 Created The request has succeeded and a new resource has been
  created as a result. This is typically the response sent after POST
  requests, or some PUT requests.

Further clarifications: Typical status code for a successful POST request is 201. This is NOT to say that you can't send a 200 code for POST request. But that doesn't happen usually and I believed that's where the mistake in the code could be.


问:
React: onClick on Mobile (iPhone) requires 2 taps?
Video demonstrating issue

I have a bunch of clickable components that, when clicked, adds a "card" to a row. On desktop, it works fine, but on mobile (tested on iPhone, does not seem to be an issue for Android tablet), it requires 2 consecutive taps of the same button to fire the onClick function.

These components also have onMouseEnter/onMouseLeave effects on them, to control a global state, which in turn decides if several components should have additional CSS applied (so I can't make it a simple CSS hover effect).

I believe that the mouse effects are interfering with the click event, but I have no idea how I could fix that. Here is the relevant code for this component:

```<code>const CardSource = ({ addCard, note, setHoveredNote, hoveredNote }) => {
  return (
    <Source
      onClick={() => addCard(note)}
      onMouseEnter={() => setHoveredNote(note)}
      onMouseLeave={() => setHoveredNote(null)}
      className={
        hoveredNote && hoveredNote.index === note.index ? "highlight" : null
      }
    >
      {note.letters[0]}
    </Source>
  );
};
</code>```

Furthermore, once a button has been tapped twice, the hover effect CSS "sticks" to that button, and never moves to another button. This seems to happen on both iPhone and Android tablet. I would love to have this not happen anymore either.

I've created a working demonstration of this issue in a sandbox, which if viewed on mobile you should be able to recreate these issues: https://codesandbox.io/s/mobile-requires-2-taps-i9zri?file=/src/Components/CardSource/CardSource.js

答:
Probably the problem with your code is, the mouse events you're using are non-bubbling. e.g. mouseenter event.

You might want to try with an event bubbling solution using onMouseOver instead of onMouseEnter, and onMouseOut instead of onMouseLeave.

const CardSource = ({ addCard, note, setHoveredNote, hoveredNote }) => {
  return (
    <Source
      onClick={() => addCard(note)}
      onMouseOver={() => setHoveredNote(note)}
      onMouseOut={() => setHoveredNote(null)}
      className={
        hoveredNote && hoveredNote.index === note.index ? "highlight" : null
      }
    >
      {note.letters[0]}
    </Source>
  );
};
```

<p>Should the above NOT work, you could debug this with event type and performing event handling based on it. e.g.</p>

```const CardSource = ({ addCard, note, setHoveredNote, hoveredNote }) => {
  const eventHandler = (event) => {
     const { type, bubbles } = event;
     switch(type) {
         case "mouseover":
         case "mouseenter":
              setHoveredNote(note);
              break;
         case "mouseout":
         case "mouseleave":
              setHoveredNote(null);
         case "click":
              addCard(note);
              if (bubbles) { // handle hover state
                 setHoveredNote(note);
              }
              break;
         default:
             break;
     }
  }

  const onClick = (event) => eventHandler(event);
  const onMouseOver = (event) => eventHandler(event);
  const onMouseOut = (event) => eventHandler(event);

  return (
    <Source
      onClick={onClick}
      onMouseOver={onMouseOver}
      onMouseOut={onMouseOut}
      className={
        hoveredNote && hoveredNote.index === note.index ? "highlight" : null
      }
    >
      {note.letters[0]}
    </Source>
  );
};
```

Also note that, providing arrow functions as props creates new instance of the function on every render. So better use bind in that case or just function references that capture the arguments.

Body:
Video demonstrating issue

I have a bunch of clickable components that, when clicked, adds a "card" to a row. On desktop, it works fine, but on mobile (tested on iPhone, does not seem to be an issue for Android tablet), it requires 2 consecutive taps of the same button to fire the onClick function.

These components also have onMouseEnter/onMouseLeave effects on them, to control a global state, which in turn decides if several components should have additional CSS applied (so I can't make it a simple CSS hover effect).

I believe that the mouse effects are interfering with the click event, but I have no idea how I could fix that. Here is the relevant code for this component:

const CardSource = ({ addCard, note, setHoveredNote, hoveredNote }) => {
  return (
    <Source
      onClick={() => addCard(note)}
      onMouseEnter={() => setHoveredNote(note)}
      onMouseLeave={() => setHoveredNote(null)}
      className={
        hoveredNote && hoveredNote.index === note.index ? "highlight" : null
      }
    >
      {note.letters[0]}
    </Source>
  );
};

Furthermore, once a button has been tapped twice, the hover effect CSS "sticks" to that button, and never moves to another button. This seems to happen on both iPhone and Android tablet. I would love to have this not happen anymore either.

I've created a working demonstration of this issue in a sandbox, which if viewed on mobile you should be able to recreate these issues: https://codesandbox.io/s/mobile-requires-2-taps-i9zri?file=/src/Components/CardSource/CardSource.js

Body:
Probably the problem with your code is, the mouse events you're using are non-bubbling. e.g. mouseenter event.

You might want to try with an event bubbling solution using onMouseOver instead of onMouseEnter, and onMouseOut instead of onMouseLeave.

const CardSource = ({ addCard, note, setHoveredNote, hoveredNote }) => {
  return (
    <Source
      onClick={() => addCard(note)}
      onMouseOver={() => setHoveredNote(note)}
      onMouseOut={() => setHoveredNote(null)}
      className={
        hoveredNote && hoveredNote.index === note.index ? "highlight" : null
      }
    >
      {note.letters[0]}
    </Source>
  );
};

Should the above NOT work, you could debug this with event type and performing event handling based on it. e.g.

const CardSource = ({ addCard, note, setHoveredNote, hoveredNote }) => {
  const eventHandler = (event) => {
     const { type, bubbles } = event;
     switch(type) {
         case "mouseover":
         case "mouseenter":
              setHoveredNote(note);
              break;
         case "mouseout":
         case "mouseleave":
              setHoveredNote(null);
         case "click":
              addCard(note);
              if (bubbles) { // handle hover state
                 setHoveredNote(note);
              }
              break;
         default:
             break;
     }
  }

  const onClick = (event) => eventHandler(event);
  const onMouseOver = (event) => eventHandler(event);
  const onMouseOut = (event) => eventHandler(event);

  return (
    <Source
      onClick={onClick}
      onMouseOver={onMouseOver}
      onMouseOut={onMouseOut}
      className={
        hoveredNote && hoveredNote.index === note.index ? "highlight" : null
      }
    >
      {note.letters[0]}
    </Source>
  );
};

Also note that, providing arrow functions as props creates new instance of the function on every render. So better use bind in that case or just function references that capture the arguments.


问:
How do i remove .0 from the result if the resultant number is a full number in a calculator
I am making an android calculator in android studio. But, in my calculator when the result is a full number, the number appears with decimal 0.
For example, if i add 9 and 11 the result is appearing as 20.0

So, how do i remove .0 from the result for a full number(ex:- 10,24).

This is my MainActivity.java

```<code> package com.example.calculator;

import androidx.appcompat.app.AppCompatActivity;

import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;

import com.faendir.rhino_android.RhinoAndroidHelper;

import org.mozilla.javascript.Context;
import org.mozilla.javascript.Scriptable;
import org.mozilla.javascript.ast.Scope;

public class MainActivity extends AppCompatActivity {

    Button btn0,btn1,btn2,btn3,btn4,btn5,btn6,btn7,btn8,btn9,btnPercent,btnPlus,btnMinus,btnMultiply,btnDivision,btnEqual,btnClear,btnDot,btnBracket,btnBackspace;
    TextView tvInput,tvOutput;
    String process;
    boolean checkBracket = false;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        btn0 = findViewById(R.id.btn0);
        btn1 = findViewById(R.id.btn1);
        btn2 = findViewById(R.id.btn2);
        btn3 = findViewById(R.id.btn3);
        btn4 = findViewById(R.id.btn4);
        btn5 = findViewById(R.id.btn5);
        btn6 = findViewById(R.id.btn6);
        btn7 = findViewById(R.id.btn7);
        btn8 = findViewById(R.id.btn8);
        btn9 = findViewById(R.id.btn9);

        btnPlus = findViewById(R.id.btnPlus);
        btnMinus = findViewById(R.id.btnMinus);
        btnDivision = findViewById(R.id.btnDivision);
        btnMultiply = findViewById(R.id.btnMultiply);

        btnEqual = findViewById(R.id.btnEqual);

        btnClear = findViewById(R.id.btnClear);
        btnDot = findViewById(R.id.btnDot);
        btnPercent = findViewById(R.id.btnPercent);
        btnBracket = findViewById(R.id.btnBracket);
        btnBackspace = findViewById(R.id.btnBackspace);

        tvInput = findViewById(R.id.tvInput);
        tvOutput = findViewById(R.id.tvOutput);

        btnClear.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                tvInput.setText("");
                tvOutput.setText("");
            }
        });

        btn0.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                process = tvInput.getText().toString();
                tvInput.setText(process + "0");
            }
        });

        btn1.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                process = tvInput.getText().toString();
                tvInput.setText(process + "1");
            }
        });

        btn2.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                process = tvInput.getText().toString();
                tvInput.setText(process + "2");
            }
        });

        btn3.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                process = tvInput.getText().toString();
                tvInput.setText(process + "3");
            }
        });

        btn4.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                process = tvInput.getText().toString();
                tvInput.setText(process + "4");
            }
        });

        btn5.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                process = tvInput.getText().toString();
                tvInput.setText(process + "5");
            }
        });

        btn6.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                process = tvInput.getText().toString();
                tvInput.setText(process + "6");
            }
        });

        btn6.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                process = tvInput.getText().toString();
                tvInput.setText(process + "6");
            }
        });

        btn7.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                process = tvInput.getText().toString();
                tvInput.setText(process + "7");
            }
        });

        btn8.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                process = tvInput.getText().toString();
                tvInput.setText(process + "8");
            }
        });

        btn9.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                process = tvInput.getText().toString();
                tvInput.setText(process + "9");
            }
        });

        btnPlus.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                process = tvInput.getText().toString();
                tvInput.setText(process + "+");
            }
        });

        btnMinus.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                process = tvInput.getText().toString();
                tvInput.setText(process + "-");
            }
        });

        btnMultiply.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                process = tvInput.getText().toString();
                tvInput.setText(process + "×");
            }
        });

        btnDivision.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                process = tvInput.getText().toString();
                tvInput.setText(process + "÷");
            }
        });

        btnDot.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                process = tvInput.getText().toString();
                tvInput.setText(process + ".");
            }
        });

        btnPercent.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                process = tvInput.getText().toString();
                tvInput.setText(process + "%");
            }
        });

        btnBracket.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

                if (checkBracket){
                    process = tvInput.getText().toString();
                    tvInput.setText(process + ")");
                    checkBracket = false;
                }else{
                    process = tvInput.getText().toString();
                    tvInput.setText(process + "(");
                    checkBracket = true;
                }

            }
        });

        btnBackspace.setOnClickListener(new View.OnClickListener() {

            public void onClick(View v) {
                String str=tvInput.getText().toString();
                if (str.length() >=1 ) {
                    str = str.substring(0, str.length() - 1);
                    tvInput.setText(str);
                } else if (str.length() <=1 ) {
                    tvInput.setText("0");
                }
            }
        });

        btnEqual.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                process = tvInput.getText().toString();

                process = process.replaceAll("×","*");
                process = process.replaceAll("%","/100");
                process = process.replaceAll("÷","/");

                Context rhino = Context.enter();

                rhino.setOptimizationLevel(-1);

                String finalResult = "";

                try {
                    Scriptable scriptable = rhino.initStandardObjects();
                    finalResult = rhino.evaluateString(scriptable,process,"javascript",1,null).toString();
                }catch (Exception e){
                    finalResult="0";
                }

                tvOutput.setText(finalResult);
            }
        });

    }
}
</code>```

Any help would be appreciated.

Thank you.

答:
You can check if it is a whole number or not by simply doing this:</p>

```<code>if (finalResult % 1 == 0){

  //then the finalResult is a whole number.

}
</code>```

Body:
I am making an android calculator in android studio. But, in my calculator when the result is a full number, the number appears with decimal 0.
For example, if i add 9 and 11 the result is appearing as 20.0

So, how do i remove .0 from the result for a full number(ex:- 10,24).

This is my MainActivity.java

 package com.example.calculator;

import androidx.appcompat.app.AppCompatActivity;

import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;

import com.faendir.rhino_android.RhinoAndroidHelper;

import org.mozilla.javascript.Context;
import org.mozilla.javascript.Scriptable;
import org.mozilla.javascript.ast.Scope;

public class MainActivity extends AppCompatActivity {

    Button btn0,btn1,btn2,btn3,btn4,btn5,btn6,btn7,btn8,btn9,btnPercent,btnPlus,btnMinus,btnMultiply,btnDivision,btnEqual,btnClear,btnDot,btnBracket,btnBackspace;
    TextView tvInput,tvOutput;
    String process;
    boolean checkBracket = false;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        btn0 = findViewById(R.id.btn0);
        btn1 = findViewById(R.id.btn1);
        btn2 = findViewById(R.id.btn2);
        btn3 = findViewById(R.id.btn3);
        btn4 = findViewById(R.id.btn4);
        btn5 = findViewById(R.id.btn5);
        btn6 = findViewById(R.id.btn6);
        btn7 = findViewById(R.id.btn7);
        btn8 = findViewById(R.id.btn8);
        btn9 = findViewById(R.id.btn9);

        btnPlus = findViewById(R.id.btnPlus);
        btnMinus = findViewById(R.id.btnMinus);
        btnDivision = findViewById(R.id.btnDivision);
        btnMultiply = findViewById(R.id.btnMultiply);

        btnEqual = findViewById(R.id.btnEqual);

        btnClear = findViewById(R.id.btnClear);
        btnDot = findViewById(R.id.btnDot);
        btnPercent = findViewById(R.id.btnPercent);
        btnBracket = findViewById(R.id.btnBracket);
        btnBackspace = findViewById(R.id.btnBackspace);

        tvInput = findViewById(R.id.tvInput);
        tvOutput = findViewById(R.id.tvOutput);

        btnClear.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                tvInput.setText("");
                tvOutput.setText("");
            }
        });

        btn0.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                process = tvInput.getText().toString();
                tvInput.setText(process + "0");
            }
        });

        btn1.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                process = tvInput.getText().toString();
                tvInput.setText(process + "1");
            }
        });

        btn2.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                process = tvInput.getText().toString();
                tvInput.setText(process + "2");
            }
        });

        btn3.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                process = tvInput.getText().toString();
                tvInput.setText(process + "3");
            }
        });

        btn4.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                process = tvInput.getText().toString();
                tvInput.setText(process + "4");
            }
        });

        btn5.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                process = tvInput.getText().toString();
                tvInput.setText(process + "5");
            }
        });

        btn6.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                process = tvInput.getText().toString();
                tvInput.setText(process + "6");
            }
        });

        btn6.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                process = tvInput.getText().toString();
                tvInput.setText(process + "6");
            }
        });

        btn7.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                process = tvInput.getText().toString();
                tvInput.setText(process + "7");
            }
        });

        btn8.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                process = tvInput.getText().toString();
                tvInput.setText(process + "8");
            }
        });

        btn9.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                process = tvInput.getText().toString();
                tvInput.setText(process + "9");
            }
        });

        btnPlus.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                process = tvInput.getText().toString();
                tvInput.setText(process + "+");
            }
        });

        btnMinus.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                process = tvInput.getText().toString();
                tvInput.setText(process + "-");
            }
        });

        btnMultiply.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                process = tvInput.getText().toString();
                tvInput.setText(process + "×");
            }
        });

        btnDivision.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                process = tvInput.getText().toString();
                tvInput.setText(process + "÷");
            }
        });

        btnDot.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                process = tvInput.getText().toString();
                tvInput.setText(process + ".");
            }
        });

        btnPercent.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                process = tvInput.getText().toString();
                tvInput.setText(process + "%");
            }
        });

        btnBracket.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

                if (checkBracket){
                    process = tvInput.getText().toString();
                    tvInput.setText(process + ")");
                    checkBracket = false;
                }else{
                    process = tvInput.getText().toString();
                    tvInput.setText(process + "(");
                    checkBracket = true;
                }

            }
        });

        btnBackspace.setOnClickListener(new View.OnClickListener() {

            public void onClick(View v) {
                String str=tvInput.getText().toString();
                if (str.length() >=1 ) {
                    str = str.substring(0, str.length() - 1);
                    tvInput.setText(str);
                } else if (str.length() <=1 ) {
                    tvInput.setText("0");
                }
            }
        });

        btnEqual.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                process = tvInput.getText().toString();

                process = process.replaceAll("×","*");
                process = process.replaceAll("%","/100");
                process = process.replaceAll("÷","/");

                Context rhino = Context.enter();

                rhino.setOptimizationLevel(-1);

                String finalResult = "";

                try {
                    Scriptable scriptable = rhino.initStandardObjects();
                    finalResult = rhino.evaluateString(scriptable,process,"javascript",1,null).toString();
                }catch (Exception e){
                    finalResult="0";
                }

                tvOutput.setText(finalResult);
            }
        });

    }
}

Any help would be appreciated.

Thank you.

Body:
You can check if it is a whole number or not by simply doing this:

if (finalResult % 1 == 0){

  //then the finalResult is a whole number.

}