I'm trying to do a messaging system where the inbox is a gridview of all the messages associated with a user's ID. I have a global get method in C# to get the user currently signed in. I'm wondering how to tie this back so that the database only shows the data I want it to.
In my .aspx.cs file, I have something like:
protected void Page_Load(object sender, EventArgs e)
{
int userInSess = getLoggedInUser();
Session["user"] = user;
}
In the source file, I have something like:
<asp:SqlDataSource ID="ProjectDB" runat="server"
ConnectionString="<%$ ConnectionStrings:ProjectConnectionString %>"
SelectCommand="SELECT [SentByUserName], [Subject], [CreateDate] FROM [Messages] WHERE (ReceivedByUserID = #user) ORDER BY [CreateDate] DESC">
<SelectParameters>
<asp:SessionParameter Name = "user" />
</SelectParameters>
</asp:SqlDataSource>
I know this is wrong but I can't seem to find clear answer on how to exactly do this. Any help would be greatly appreciated.
Thanks
You need to reference the value stored in the session with:
<asp:SessionParameter Name="User" SessionField="user" />
Note the addition of SessionField attribute.
SqlDataSource control only uses Name="User" of the Parameter object to match a #user placeholder in SQL query
Related
I have an asp.net program.
Here I want to keep Insert Facility of the Details view. But in the interface I want to keep the 'UserName' attribute of the new Record as fixed and same as the UserName of the Logged in user. I also want to check it on Server side whether it corresponds to the logged in user's username.
How can I achieve this functionality.
I have made the BoundField ReadOnly. But I can't find anything else suitable for this functionality.
In your .aspx do the following:
<asp:SqlDataSource ID="SqlDataSource1" runat="server" OnInserting="SqlDataSource1_Inserting">
<InsertParameters>
<asp:Parameter Type="String" Name="Username" />
//Place other parameters here
</InsertParameters>
</asp:SqlDataSource>
In your code behind:
protected void SqlDataSource1_Inserting(object sender, SqlDataSourceCommandEventArgs e)
{
SqlDataSource1.InsertParameters["Username"].DefaultValue = Context.User.Identity.Name;
}
I am not even sure how SessionParameters are meant to be used as opposed to a normal Parameters. What I am trying to do is Update or Insert records into my database based on a value from a Session variable "StaffID", which I know exists (based on debugging the PageLoad event). As it turns out my "StaffID" session is actually NULL (found after exhaustive debugging) and I get exceptions about trying to update a table with null values.
My SqlDataSource is thus ...
<asp:SqlDataSource ID="SqlDataProgmDetails" runat="server" ConnectionString="<%$ ConnectionStrings:ATCNTV1ConnectionString %>"
UpdateCommand="UPDATE tblStudentProgramReg SET StaffModified = #StaffModified, DateModified = GETDATE() WHERE (ProgramEnrolmentID = #ProgramEnrolmentID)">
<UpdateParameters>
<asp:Parameter Name="EnrolmentDate" Type="DateTime" />
<asp:Parameter Name="StudentProgramNotes" Type="String" />
<asp:Parameter Name="TerminationDate" Type="DateTime" />
<asp:Parameter Name="StudProgEnrolStatusID" />
<asp:Parameter Name="QualificationCode" />
<asp:ControlParameter ControlID="gvPrograms" Name="ProgramEnrolmentID" Type="Int32" PropertyName="SelectedValue" />
<asp:SessionParameter Name="StaffModified" SessionField="StaffID" />
</UpdateParameters>
rs>
</asp:SqlDataSource>
When I UPDATE my DetailsView I get the dreaded "String or binary data would be truncated.
The statement has been terminated." error.
I know this is happening because the "StaffID" session variable that I am sure existed at one point is NULL in the UPDATE phase of the above SqlDataSource.
The only way around it I found was to force load the value in CodeBehind ...
protected void SqlDataProgmDetails_Updating(object sender, SqlDataSourceCommandEventArgs e)
{
if (Session["StaffID"] != null)
{
e.Command.Parameters[5].Value = Session["StaffID"].ToString().Trim();
}
}
protected void SqlDataProgmDetails_Inserting1(object sender, SqlDataSourceCommandEventArgs e)
{
if (Session["StaffID"] != null)
{
e.Command.Parameters[8].Value = Session["StaffID"].ToString().Trim();
}
}
But why should I have to do this?
I would have thought the StaffID should have loaded automatically as per the SessionParameter request in my ASP page.
Like I said, I am not sure how SessionParameters (or Session variables work) in general, so if someone could please explain why I have to use codebehind to get this to work, that would be appreciated?
Thank you
The Session object is in fact an IDictionary<string, object>, which is persisted for you. It is persisted per-session. When a new session begins, the client receives a cookie from the server with a unique session identifier.
On each subsequent request the client sends the cookie to the server and in the global.asax the Session dictionary is repopulated. So let's say that in a code-behind you do Session[UserId] when the user authenticates, on each subsequent request you could do var UserId = Session[UserId] and as long as the session is "alive", you will receive the value you stored.
Restoring values from session as you have done is very logical. Since HTTP is state-less, Session is one of the mechanisms for simulating statefulness.
I have used an sql statement where I want to display the details of the current user that is logged in. But when I run this command it
ConnectionString = "<%$ ConnectionStrings:Details %>"
SelectCommand = "SELECT * FROM member WHERE username = 'User.Identity.Name'"
it does not show any details but when I run
SelectCommand = "SELECT * FROM member WHERE username = 'david'"
the username david exists in the database and displays the details of only david in the web form. I even did Response.Write on the User.Identity.Name and that statement displays the current user that is logged in the page.
The issue is you're passing the actual User.Identity.Name as string instead of its value.
SelectCommand = String.Format("SELECT * FROM member WHERE username = '{0}'", User.Identity.Name)
But the better (and safer) practice would be something like
SelectCommand = "SELECT * FROM member WHERE username = #UserName"
SelectCommand.Parameters.AddWithValue("#UserName", User.Identity.Name)
This will prevent SQL injection.
EDIT:
Since you are defining this in your page, you can use the following template:
<asp:SqlDataSource runat="server" ID="SqlDataSource1" ConnectionString="<%$ ConnectionStrings:Details %>" SelectCommand="SELECT * FROM members WHERE ([username] = #UserName)">
<SelectParameters>
<asp:Parameter Name="UserName" Type="String" DefaultValue="" />
</SelectParameters>
</asp:SqlDataSource>
Then set the default value to User.Identity.Name on the server side:
SqlDataSource1.SelectParameters.Item(0).DefaultValue = User.Identity.Name
The easier way to do this is by using the Configure Data Source wizard, which is available by clicking the right arrow beside the SqlDataSource object in design view.
I have a SQL query that will result in one string. Rather than bind a gridview, listview, etc to it and have a single lonely label inside, I just want to store the string (it'll eventually get used later elsewhere). For the life of me I cannot figure this out.
<asp:SqlDataSource ID="SqlDataSource3" runat="server" ConnectionString="<%$ ConnectionStrings:ConnectionString %>"
SelectCommand="select [title] from [books]
where([Genre]=#Genre)
OnSelected="SqlDataSource3_Selected">
<SelectParameters>
<asp:Parameter Name="Title" Direction="ReturnValue" Type="String" />
<asp:ControlParameter ControlID="DropDownList1" Name="genre"
PropertyName="SelectedValue" />
</SelectParameters>
</asp:SqlDataSource>
protected void SqlDataSource3_Selected(object sender, SqlDataSourceStatusEventArgs e)
{
string sqlreturnString = Convert.ToString(e.Command.Parameters["#Title"].Value);
Label3.Text = sqlreturnString;
}
All this does is spit out '0' when I want it to display the title. If I change ["#Title"] to [1], it'll display the Genre. Right now there are only four books, each with a unique genre.
Add a button and write this code in the handler of button's click.
DataSourceSelectArguments sr = new DataSourceSelectArguments();
DataView dv =(DataView) SqlDataSource3.Select(sr);
if(dv.Count!=0)
Label1.Text = dv[0][0].ToString();
I encountered this same issue also when doing C# and ASP.NET, it would be really nice to have a method that dumps out a string of the text results of the query in a SQLDataSource or an AccessDatasource. Until then, Here is an example of the solution I found that works very well:
AccessDataSource MyDataSource = new AccessDataSource("~/App_Data/MyDB.mdb",
"SELECT Name FROM Employees");
DataView MyView = (DataView) MyDataSource.Select(DataSourceSelectArguments.Empty);
lblResults.Text = MyView[0][1].ToString();
This example will also work with SqlDataSource objects.
I have a dropdownlist which is populated with data from an SQL db. This is what I might have in the aspx file. How do I move (as much as possible) the code from the aspx file to the aspx.cs file to implement the code behind technique?
I mean at least the SELECT portion.
Thanks.
<asp:DropDownList ID="DropDownList1" ... runat="server"/>
...
<asp:SqlDataSource ID="SqlDataSource1" runat="server"
ConnectionString="<%$ ConnectionStrings:Pubs %>"
SelectCommand="SELECT [au_id], [au_lname], [au_fname], [state] FROM [authors] WHERE [state] = #state">
<SelectParameters>
<asp:ControlParameter Name="state" ControlID="DropDownList1" PropertyName="SelectedValue" />
</SelectParameters>
</asp:SqlDataSource>
suppose you are binding a grid with data source SqlDataSource1 then you can catch SelectedIndexChanged event in codebehind and get data to bind the grid like this:
ASPX file:
<asp:DropDownList ID="DropDownList1" runat="server"
OnSelectedIndexChanged="ddlChanged" />
C# (codebehind):
protected void ddlChanged(object sender, EventArgs e)
{
var cs=..;//get connection string
using(var con=new SqlConnection(cs))
{
using(var com=new SqlCommand(con))
{
com.Open();
com.CommandType = CommandType.Text;
com.CommandText="SELECT [au_id], [au_lname], [au_fname], [state]
FROM [authors] WHERE [state] = #state";
var state=....;//GET VALUE OF STATE FROM DROPDOWN
var p = com.Parameters.Add("#state");//set other properties
p.Value = state;
using(var adptr=new SqlDataAdapter(com))
{
var dtb=new DataTable();
adptr.Fill(dtb);
grid.DataSource=dtb;
grid.DataBind();
}
}
}
}
The SelectCommand is a property of the datasource object you are using. These can be applied in the code behind as needed, but you may want to do it in an overridden Init page function as this might be used quite early on in the asp.net page life cycle. for eg, although I'm not sure exactly where.
protected override OnInit(object sender, EventArgs e)
{
dsMySource.SelectCommand = "SELECT [au_id], [au_lname], [au_fname], [state] FROM [authors] WHERE [state] = #state"
}
You are also going to have to make sure the #state parameter is used correctly in the code behind as well, this can be accessed also as a property (dsMySource.SelectParameters).