I have a webapp that calls on a SQL Query for a list of applications impacted by a project. I want my admins to be able to click edit and add remove applications to this list at will. Currently when they click edit they see every single Application that is Impacted by ANY project as part of the list box even though in the Gridview they only see the Applications Impacted by that specific project. When I hard code the value for the project it works, but I need it to be a variable depending on which project my admins click on to edit.
select
Applications.ApplicationName,
Projects.ProjectName
from ImpactedApplications
inner join Applications
on ImpactedApplications.AppId=Applications.AppId
inner join Projects
on ImpactedApplications.ProjectId=Projects.ProjectId
Where Projects.ProjectId=57 <--This is Hardcoded. I need this to be dynamic.
Adding Code
<asp:TemplateField HeaderText="ImpactedApplications">
<EditItemTemplate>
<asp:ListBox ID="ListBox1" runat="server" DataSourceID="ImpactedApps"
DataTextField="ApplicationName" DataValueField="ProjectName" Width="250px"></asp:ListBox>
<asp:Button ID="Button1" runat="server" Text="Add" />
<asp:Button ID="Button2" runat="server" Text="Remove" />
<asp:ListBox ID="ListBox3" runat="server" DataSourceID="Applications"
DataTextField="ApplicationName" DataValueField="AppId" Width="250px">
</asp:ListBox>
<br />
<asp:SqlDataSource ID="ImpactedApps" runat="server"
ConnectionString="<%$ ConnectionStrings:LandscapeServicesConnectionString %>"
SelectCommand="select Applications.ApplicationName, Projects.ProjectName
from ImpactedApplications
inner join Applications
on ImpactedApplications.AppId=Applications.AppId
inner join Projects
on ImpactedApplications.ProjectId=Projects.ProjectId
where Projects.ProjectName=#Projectname">
<SelectParameters>
<asp:FormParameter DefaultValue="PO Consolidation (EDW)"
FormField="Gridview1 - Column[2] - Project Name" Name="Project Name" />
</SelectParameters>
</asp:SqlDataSource>
Adding Background Code
public partial class Update : System.Web.UI.Page
{
public string query { get; set; }
SqlConnection con = new SqlConnection(ConfigurationManager.ConnectionStrings["LandscapeServicesConnectionString"].ConnectionString);
DataSet dt = new DataSet();
protected void Page_Load(object sender, EventArgs e)
{
con.Open();
}
protected void GridView1_RowEditing(object sender, GridViewEditEventArgs e)
{
GridView1.EditIndex = e.NewEditIndex;
}
}
Create a parameterized query:
select
Applications.ApplicationName,
Projects.ProjectName
from ImpactedApplications
inner join Applications
on ImpactedApplications.AppId=Applications.AppId
inner join Projects
on ImpactedApplications.ProjectId=Projects.ProjectId
where Projects.ProjectId=#projectId
Then when you create your SqlCommand add a parameter and give it the value from your form:
cmd.Parameters.AddWithValue("#projectId",projectId);
Related
I have just a simple message page which consists of From: Text: and a Submit button, then I have another page, which contains nothing, it's my "Message Board" the most recent posted message goes on top of the board, both are aspx pages with master page.
I have a SQL DB, I'm already assuming there will be a table with From: Message:(with varchar i think), but what i don't understand how it will get inserted into the messageboard page in a most recent to oldest list fashion.
Message.aspx - From: Text: Submit
MessageBoard.aspx - just a div , messages submitted will appear here in a drop down list
I want it to be super simple no cool features, only "Submit the message" -> "Appears on MessageBoard.aspx to everyone",
and that's it
Ok, there are seveal moving parts.
Assuming you have SQL server running. Assuming you have a valid conneciton?
Ok, then on the post a new message page, you have this markup:
<h3>Post a message</h3>
<h4>enter your name</h4>
<asp:TextBox ID="txtName" runat="server" Width="250px"></asp:TextBox>
<br />
<h4>Enter your message</h4>
<asp:TextBox ID="txtMsg" runat="server" Height="185px" Width="520px"
TextMode="MultiLine" Font-Size="Large" style="border-radius:20px;border:solid 2px"
></asp:TextBox>
<br />
<br />
<asp:Button ID="cmdNewMessage" runat="server" Text="Post Message" CssClass="btn"
OnClick="cmdNewMessage_Click" />
And code behind looks like this:
protected void Page_Load(object sender, EventArgs e)
{
}
protected void cmdNewMessage_Click(object sender, EventArgs e)
{
string strSQL =
#"INSERT INTO tblMessages (UName, Message, MessageDate)
VALUES (#UName, #Message, #MessageDate)";
using (SqlConnection conn = new SqlConnection(Properties.Settings.Default.TEST4))
{
using (SqlCommand cmdSQL = new SqlCommand(strSQL, conn))
{
conn.Open();
cmdSQL.Parameters.Add("#UName", SqlDbType.NVarChar).Value = txtName.Text;
cmdSQL.Parameters.Add("#Message",SqlDbType.NVarChar).Value = txtMsg.Text;
cmdSQL.Parameters.Add("#MessageDate", SqlDbType.NVarChar).Value = DateTime.Now;
cmdSQL.ExecuteNonQuery();
}
}
Response.Redirect("MessageBoard.aspx");
}
So, it looks like this:
when you hit post message, we jump to this page, and markup:
<asp:Button ID="cmdPost" runat="server"
Text="Post a new message"
CssClass="btn" OnClick="cmdPost_Click" />
<br />
<br />
<h2>Messages</h2>
<asp:GridView ID="GridView1" runat="server" Width="50%"
AutoGenerateColumns="False" DataKeyNames="ID" >
<Columns>
<asp:BoundField DataField="UName" HeaderText="Posted by" />
<asp:BoundField DataField="MessageDate" HeaderText="At" ItemStyle-Width="180px" />
<asp:TemplateField HeaderText="Message" >
<ItemTemplate>
<asp:Textbox ID="txtMsg" runat="server" TextMode="MultiLine" Width="100%"
Text='<%# Eval("Message") %>'
Height='<%# (Regex.Matches(Eval("Message").ToString() , System.Environment.NewLine).Count + 1) * 30 %>'
>
</asp:Textbox>
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
And code is:
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
LoadGrid();
}
void LoadGrid()
{
using (SqlConnection conn = new SqlConnection(Properties.Settings.Default.TEST4))
{
string strSQL = "SELECT * FROM tblMessages ORDER BY MessageDate DESC";
using (SqlCommand cmdSQL = new SqlCommand(strSQL, conn))
{
conn.Open();
GridView1.DataSource = cmdSQL.ExecuteReader();
GridView1.DataBind();
}
}
}
protected void cmdPost_Click(object sender, EventArgs e)
{
Response.Redirect("NewMessage.aspx");
}
And we now see/have this:
You don't explain what you mean by "what i don't understand how it will get inserted into the messageboard page in a most recent to oldest list fashion", so I can only guess.
When a new message is posted, you insert it into the database, including a DateTime column. Your message list page then just grabs the latest nn messages, ordered by newest first.
I'm assuming that you know how to do that. If not, do some reading about Entity Framework Core, as that provides a very good way of handling databases.
So, in princple, your question is no more complex than that. However, there are many variations on this, such as having the message list updated in real time, for which you should use SignalR, but without more specific explanation of what you want, it's hard to make any suggestions.
Hello all fellow programmers.
I wanna make a paging of a database each consisting of 5 items and using a query opening the page. When i click the button i wanna change the query of the database connection and refresh the datalist with the new data consisting to that query(new 5 items) that i made but somehow my code needs a bit of help. I am a basic c# programmer and every help welcomed.
ASP
<link rel="stylesheet" href="../Images/book-style.css" />
<link rel="stylesheet" href="../Images/form.css" />
<link rel="stylesheet" href="../Images/style.css" />
<span id="bookshead" />
<div style="margin-top:50px" >
<asp:DataList ID="DataList1" runat="server" DataKeyField="ID_AUTHOR" DataSourceID="SqlDataSource1" SeparatorStyle-Wrap="False">
<ItemTemplate>
<div class="books" style="width:530px;height:150px;margin-bottom:20px;border:1px dotted black;border-radius:5px;box-shadow:2px 2px 6px black;">
<p class="book" runat="server"><%# Eval("TITLE") %></p>
<p class="author"><%# Eval("NAME") %> <%# Eval("SURNAME") %></p>
<img class="book-image" runat="server" alt="book image" src='<%# Eval("imazhi") %>' style="width:85px;height:130px" />
<br />
<div class="addtowishlist" >
<a href="#" >Add to Wishlist</a>
</div>
</div>
</ItemTemplate>
</asp:DataList>
</div>
<asp:Label runat="server" ID="labe" Text="HELLLOO"></asp:Label>
<form id="ff" runat="server" >
<div id="Navigation" class="navigation">
<div id="leftnav">
<asp:Button ID="PreviousPageNav" runat="server" href="#bookshead" OnClick="updateBackward" Text="<< Librat e mëparshëm" />
<asp:Label ID="PagerLocation" runat="server" />
<asp:Button ID="NextPageNav" runat="server" href="#bookshead" OnClick="updateFoward" Text=" Librat e ardhshëm>>"/>
</div>
</div>
</form>
<asp:SqlDataSource ID="SqlDataSource1" runat="server" ConnectionString="<%$ ConnectionStrings:eLibraryPConnectionString %>" SelectCommand="Select *FROM (AUTHORS a JOIN BOOKS_AUTHORS ba ON a.ID_AUTHOR=ba.ID_AUTHOR) JOIN BOOKS b ON ba.ID_BOOK=b.ID_BOOK WHERE a.ID_AUTHOR>=1 AND a.ID_AUTHOR<=5"></asp:SqlDataSource>
</asp:Content>
AND The C#
private int firstItem=1;
private int lastItem=5;
public void updateFoward(object o, EventArgs e)
{
firstItem += 5;
lastItem += 5;
SqlDataSource sql = new SqlDataSource();
sql.ID = "SqlDataSource1";
sql.SelectCommand = "Select * FROM (AUTHORS a JOIN BOOKS_AUTHORS ba ON a.ID_AUTHOR=ba.ID_AUTHOR) JOIN BOOKS b ON ba.ID_BOOK=b.ID_BOOK WHERE a.ID_AUTHOR>=" + firstItem + "AND a.ID_AUTHOR<=" + lastItem;
labe.Text =sql.ID;
DataList1.DataBind();
}
public void updateBackward(object o,EventArgs e)
{
firstItem -= 5;
lastItem -= 5;
SqlDataSource sql = new SqlDataSource();
labe.Text = "Backward";
sql.ID = "SqlDataSource1";
sql.SelectCommand = "Select * FROM (AUTHORS a JOIN BOOKS_AUTHORS ba ON a.ID_AUTHOR=ba.ID_AUTHOR) JOIN BOOKS b ON ba.ID_BOOK=b.ID_BOOK WHERE a.ID_AUTHOR>=" + firstItem + "AND a.ID_AUTHOR<=" + lastItem;
DataList1.DataBind();
}
}
The first issue to address here is that the firstitem and lastitem variables are defined at the class level in your page. It's important to remember that every event in ASP.Net results in a completely new instance of the class, and runs the entire page lifecycle: not just the event code itself. Anything from a prior instance of the page class is gone. Therefore, you click the "updateForward" button, for example, and the existing code will always give results running from 6 to 10, regardless of how many times you click it.
The quick solution here is to store this data either in the Session or in ViewState, instead of in the class. I'll use the Session as an example going forward.
The second problem is code that looks like this:
sql.SelectCommand = "Select * FROM (AUTHORS a JOIN BOOKS_AUTHORS ba ON a.ID_AUTHOR=ba.ID_AUTHOR) JOIN BOOKS b ON ba.ID_BOOK=b.ID_BOOK WHERE a.ID_AUTHOR>=" + firstItem + "AND a.ID_AUTHOR<=" + lastItem;
There are actually two problems here. The first is easy enough to correct: there isn't any spacing before the word "AND" after your firstItem substitution. The second problem will take considerably more work: the "string concatenation to include parameters" technique leaves you open to sql injection, and should be avoided. The good news is that the solution for this major security issue will also have the nice side effect of making your datasource work again.
To get started, let's first look at some of the existing ASP markup:
<asp:SqlDataSource ID="SqlDataSource1" runat="server" ConnectionString="<%$ ConnectionStrings:eLibraryPConnectionString %>"
SelectCommand="Select * FROM (AUTHORS a JOIN BOOKS_AUTHORS ba ON a.ID_AUTHOR=ba.ID_AUTHOR) JOIN BOOKS b ON ba.ID_BOOK=b.ID_BOOK WHERE a.ID_AUTHOR>=1 AND a.ID_AUTHOR<=5">
</asp:SqlDataSource>
We want to change the markup to look like this:
<asp:SqlDataSource ID="SqlDataSource1" runat="server" ConnectionString="<%$ ConnectionStrings:eLibraryPConnectionString %>"
SelectCommand="Select * FROM (AUTHORS a JOIN BOOKS_AUTHORS ba ON a.ID_AUTHOR=ba.ID_AUTHOR) JOIN BOOKS b ON ba.ID_BOOK=b.ID_BOOK WHERE a.ID_AUTHOR>= #firstItem AND a.ID_AUTHOR<= #lastItem">
<SelectParameters>
<asp:SessionParameter name="firstItem" sessionfield="firstItem" type="Int32" />
<asp:SessionParameter name="lastItem" sessionfield="lastItem" type="Int32" />
</SelectParameters>
</asp:SqlDataSource>
If you wanted to use ViewState instead of the session, you could use an asp:ViewStateParameter instead. There are also asp:QueryStringParameters and some other options you can use.
The new markup tells the datasource about placeholders in the sql string, and also tells it where to find the data for those placeholders. The datasource will handle filling that data into the string itself... or rather, it won't. The great thing about query parameters done this way is that the parameter data is never substituted directly into the sql command, even on the database server, eliminating any possibility of sql injection attacks.
Now you can simplify your updateForward()/Backward() methods like this:
public void updateFoward(object o, EventArgs e)
{
Session["firstItem"] = (int)Session["firstItem"] + 5;
Session["lastItem"] = (int)Session["lastItem"] + 5;
DataList1.DataBind();
}
The udpateBackward() method will need a similar change. The switch to the long-form x = x + 5 instead of x += 5 is so that you can cast the Object Session value to an int at the proper point.
You'll also need code to seed the Session variables:
public void Page_Load(object o, EventArgs e)
{
if (!IsPostBack)
{
Session["firstItem"] = 1;
Session["lastItem"] = 5;
}
}
I want to pass the sql select query from the code behind and based on that query, data should be automatically fill in the grid view. The select query will be different i.e. it can select any tables or views. My code is as follows.
CodeBehind
Protected void ExecuteButton_Click(object sender, EventArgs e)
{
string sql = SqlQueryTextBox.Text;
SqlDataSource1.SelectCommand = sql;
GridView1.Databind();
}
Asp Markup
<asp:GridView ID="GridView1" runat="server"
DataSourceID="SqlDataSource1" AutoGenerateColumns="true">
</asp:GridView>
But nothing is loaded in grid view. Upto now I have used grid view only to bind single table and its columns. Is there any mistake in my logic? How can I fill the grid with dynamic data?
This works fine for me...
<asp:SqlDataSource ID="SqlDataSource1" runat="server" ConnectionString="Data Source=*******Initial Catalog=*******;Persist Security Info=True;User ID=*******;Password=*******" ></asp:SqlDataSource>
<div>
<asp:TextBox ID="SqlQueryTextBox" runat="server" ></asp:TextBox>
<asp:Button ID="ExecuteButton" OnClick="ExecuteButton_Click" runat="server" Text="Execute"/>
</div>
<div>
<asp:GridView ID="GridView1" runat="server" DataSourceID="SqlDataSource1" AutoGenerateColumns="true" />
</div>
..
protected void ExecuteButton_Click(object sender, EventArgs e)
{
SqlDataSource1.SelectCommand = SqlQueryTextBox.Text;
GridView1.DataBind();
}
Ps. I used "SELECT * FROM information_schema.tables" as my select statement
I think you need to check your connection string. and then get back to us.
string sql = SqlQry.Text;
SqlDataSource1.SelectCommand = sql;
SqlDataSource1 .Select (DataSourceSelectArguments .Empty );
Gv_1.DataBind();
I have a couple of DropDownLists in my GridView from customer table that binds the selected value from my db.
I noticed that if I only have one customer and would like to edit that customers gender it's not possible because I populate the DropDownLists with the SELECT DISTINCT Gender FROM Customer and my first customer is either Herr or Frau and I can only choose from that value.
I was thinking I could solve this Problem using a Union select select
Gender
from
( select Gender = 'Herr'
union
select Gender = 'Frau'
)as Gender
to bring both alternatives but then i get this error message 'DropDownList1'** has a SelectedValue which is invalid because it does not exist in the list of items**
So my question is how can I add some alternatives to DropDownListsthat's not already presented in DB and still bind the SelectedValue?
<EditItemTemplate>
<asp:DropDownList ID="DropDownList3" runat="server" DataSourceID="SqlDataSource1" DataTextField="Gender" DataValueField="Gender" SelectedValue='<%# Bind("Gender") %>'>
</asp:DropDownList>
<asp:SqlDataSource ID="SqlDataSource1" runat="server" ConnectionString="<%$ ConnectionStrings:EventConnectionString %>" SelectCommand="SELECT DISTINCT [Gender] FROM [Customer]"></asp:SqlDataSource>
</EditItemTemplate>
<ItemTemplate>
<asp:Label ID="Label2" runat="server" Text='<%# Bind("Gender") %>'></asp:Label>
</ItemTemplate>
Thanks for your answers, what do I Need to Change in code behind to make it work?
Here is my code behind.
protected void Page_Load(object sender, EventArgs e)
{
}
protected void lbInsert_Click(object sender, EventArgs e)
{
Event.InsertParameters["Gender"].DefaultValue = ((DropDownList)GridView1.FooterRow.FindControl("ddlGender")).SelectedValue;
Event.InsertParameters["LastName"].DefaultValue = ((TextBox)GridView1.FooterRow.FindControl("txtLastName")).Text;
Event.InsertParameters["FirstName"].DefaultValue = ((TextBox)GridView1.FooterRow.FindControl("txtFirstName")).Text;
Event.InsertParameters["Street"].DefaultValue = ((TextBox)GridView1.FooterRow.FindControl("txtStreet")).Text;
Event.InsertParameters["HouseNr"].DefaultValue = ((TextBox)GridView1.FooterRow.FindControl("txtHouseNr")).Text;
Event.InsertParameters["Zip"].DefaultValue = ((TextBox)GridView1.FooterRow.FindControl("txtZip")).Text;
Event.InsertParameters["City"].DefaultValue = ((TextBox)GridView1.FooterRow.FindControl("txtCity")).Text;
Event.InsertParameters["Phone"].DefaultValue = ((TextBox)GridView1.FooterRow.FindControl("txtPhone")).Text;
Event.InsertParameters["Email"].DefaultValue = ((TextBox)GridView1.FooterRow.FindControl("txtEmail")).Text;
Event.InsertParameters["Company"].DefaultValue = ((TextBox)GridView1.FooterRow.FindControl("txtCompany")).Text;
Event.InsertParameters["Active"].DefaultValue = ((DropDownList)GridView1.FooterRow.FindControl("ddlActive")).SelectedValue;
Event.Insert();
}
Recent problems I've had are making me question my whole philosophy and assumptions regarding GridViews.
Currently, I have used something along the lines of the following model.
In Markup:
<asp:UpdatePanel ID="pnlSearch" UpdateMode="Conditional" runat="server">
<ContentTemplate>
<asp:TextBox ID="txtSearch" runat="server"
ontextchanged="txtSearch_TextChanged"></asp:TextBox>
</ContentTemplate>
</asp:UpdatePanel>
<asp:UpdatePanel ID="pnlGridView" UpdateMode="Conditional" runat="server">
<ContentTemplate>
<asp:GridView ID="GridView1" EnableViewState="false" AllowPaging="true" PageSize="20" DataSourceID="MyDataSource" runat="server" AutoGenerateColumns="False">
<Columns>
<asp:BoundField DataField="COL_1" HeaderText="Happy Data" SortExpression="COL_1" />
<asp:BoundField DataField="COL_2" HeaderText="Happy Related Data" SortExpression="COL_2" DataFormatString="{0:M/dd/yyyy}" />
</Columns>
</asp:GridView>
</ContentTemplate>
<Triggers>
<asp:AsyncPostBackTrigger ControlID="txtSearch" EventName="TextChanged" />
</Triggers>
</asp:UpdatePanel>
<asp:SqlDataSource ID="MyDataSource" runat="server"></asp:SqlDataSource>
Pretty basic stuff. A GridView. A data source. A text box for searching results. I include the UpdatePanels only because I'm somewhat convinced they could be part of my problems.
Over in my code behind, I usually would do something like this:
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
MyDataSource.ConnectionString = ConfigurationManager.ConnectionStrings["OracleConnectionString"].ConnectionString;
MyDataSource.ProviderName = ConfigurationManager.ConnectionStrings["OracleConnectionString"].ProviderName;
GridView1.EmptyDataText = "No comments found.";
PopulateGridView();
}
}
protected void PopulateGridView()
{
string strQuery = #"SELECT COL_1,
COL_2
FROM some_table
WHERE COL_3 = :important_filter";
MyDataSource.SelectCommand = strQuery;
MyDataSource.SelectParameters.Clear();
MyDataSource.SelectParameters.Add(":important_filter", Request.QueryString["filter"]);
GridView1.DataBind();
GridView1.PageIndex = 0;
}
protected void txtSearch_TextChanged(object sender, EventArgs e)
{
string strQuery = #"SELECT COL_1,
COL_2
FROM some_table
WHERE COL_3 = :important_filter AND lower(COL_2) LIKE :search";
MyDataSource.SelectCommand = strQuery;
MyDataSource.SelectParameters.Clear();
MyDataSource.SelectParameters.Add(":important_filter", Request.QueryString["filter"]);
MyDataSource.SelectParameters.Add(":search", "%" + txtSearch.Text.Trim().ToLower() + "%");
GridView1.DataBind();
GridView1.PageIndex = 0;
}
Nothing too fancy. I initially connect up the data source to a connection string from the config file (as is necessary in a multi instance environment), wire up the query and databind. On searches, I change the query and rebind.
The only problem?
The above doesn't work. Why? The data source loses it's query, connection string, provider name, etc on post back. So the gridview commits suicide. The same thing happens when I try to change pages...either on initial load or with a search populated.
I "solved" this problem last week by manually adding the datasource to control state and repopulating the values from control state, but that seems hackish.
What am I not understanding?
You have the update mode set to conditional so you need to call update on 'pnlGridView'
GridView1.DataBind();
GridView1.PageIndex = 0;
pnlGridView.Update();
I would also revist how you are using your DataSource
<asp:SqlDataSource ID="ProductsDataSource" runat="server"
ConnectionString="<%$ ConnectionStrings:OracleConnectionString %>"
SelectCommand="SELECT COL_1, COL_2 FROM some_table WHERE COL_3 = #important_filter">
<SelectParameters>
<asp:ControlParameter ControlID="textBox?not sure where this is coming from" PropertyName="SelectedValue" Name="important_filter" Type="string" DefaultValue="" />
</SelectParameters>
</asp:SqlDataSource>
You could also use a server side event handler and set the important filter manually.
protected void SQLDataSource_Selecting(object sender, SQLDataSourceSelectingEventArgs e) {
e.InputParameters["important_filter"] = "whatever";
}
And add the event to your markup for your SQLDataSource.
<asp:SqlDataSource ID="MyDataSource" runat="server" OnSelecting="SQLDataSource_Selecting" />