Bind a users role to dropdown? - asp.net

I'm trying to bind a selected user's role to a dropdown-list.
The purpose of this is to be able to change said user's role.
I'm attempting this inside a formview hooked up to a linqdatasource which contains a row from the aspnet_User table.
The dropdown list is hooked up to a linqdatasource of all the roles in the aspnet_Roles table (with DataValueField="RoleID", DataTextField="RoleName").
I figured it would be possible with something like:
SelectedValue='<%# Bind("aspnet_UsersInRole[0].aspnet_Role.RoleID") %>'
But this throws a parser exception, about the bind call not being correctly formatted.
The roles are there, they show up when I remove the SelectedValue
Can anyone point me in the right direction?

If you are binding aspnet_roles table to the drop down, then why does the code sample use aspnet_usersinrole? Instead, if you want to bind to aspnet_role object, do:
SelectedValue='<%# Bind("RoleID") %>'
Instead; that will hookup to the right property. If you want to bind aspnet_usersinrole, if possible in the LINQDataSource, from the resuling aspnet_usersinrole, do a select operation to select the aspnet_role object instead for this.

Solved - I ended up just making a method in the codebehind which returned the roleID, like so:
public Guid GetRoleID(Guid userID) {
DBDataContext db = new DBDataContext();
aspnet_User user = db.aspnet_Users.SingleOrDefault(o => o.UserId == userID);
return user.aspnet_UsersInRoles[0].aspnet_Role.RoleId;
}
and then in the markup do:
SelectedValue='<%# GetRoleID((Guid)Eval("UserID")) %>'

Related

gridview data binding itemptemplate field

I have a data gridview which gathers data from database. The grid has 4 columns. one of the columns is the city name. In the sql code, I select the city code rather than city name.
I have converted this column into template field. In the edit mode, i was able to place drop down list and provide data binding in order for the user to be able to select the city.
however in itemtemplate mode i have label field. how can i provide data binding in which can pick up the data from database?
You can achieve it in some sort of following way(s)
First approach
Declare your datasource such as SQL Data Source / Object Data Source including the required value fields using sub queries or joins and assign it to the label as other values are being assigned.
Second approach
Declare the ItemTemplate as
<ItemTemplate>
<asp:Label ID="lblCity" runat="server" Text='<%# LookupCity(DataBinder.Eval(Container.DataItem, "CityCode")) %>'></asp:Label>
</ItemTemplate>
In the code-behind declare the LookupCity function as
protected string LookupCity(object idObj)
{
string CityCode = idObj.ToString();
if (string.IsNullOrEmpty(CityCode))
// return if CityCode is not valid value
return null;
// find the corresponding name from SQL Data Source named SQLDS_City
IEnumerator CityEnum = SQLDS_City.Select(new DataSourceSelectArguments()).GetEnumerator();
// loop through enum until required value is not found
while (CityEnum.MoveNext())
{
DataRowView row = CityEnum.Current as DataRowView;
if ((string)row["CityCode"].ToString() == CityCode)
return string.Concat(row["CityName"].ToString());
}
// return code if it is not found in the enum
return CityCode;
}
Third approach
You may use the DropDownList control for ItemTemplate also. An example can be found here Bind-DropDownList-in-ItemTemplate-of-TemplateField-in-ASPNet-GridView. To restrict the user from changing the value in ItemTemplate you may keep it disabled for display purpose only.

Gridview edit from two tables

I am trying to do an update in the gridview and all worked good until I included the 'serviceArea' which is from another table.
here is my query.
var result = from u in _db.tbl_Users
where u.UserName.Contains(searchQuery)
&& searchQuery.Length > 0
&& u.Deleted == false
select new
{
u.UserName,
u.Email,
u.IsAdmin,
u.ServiceAreaId,
u.tbl_ServiceArea.ServiceArea,
u.UserId,
};
grd_User.DataSource = result;
grd_User.DataBind();
when i try an edit the databinding Error says no definition is found for serviceArea.
Can i do this somehow through the:
<EditItemTemplate>
<asp:TextBox ID="txt_Val_ServiceArea" runat="server" Text='<%# Eval("ServiceArea") %>'></asp:TextBox>
</EditItemTemplate>
Any help would be good thank you.
If you want to edit data in a gridview you can't use anonymous types, because they are immutable. When you sent plain Users to the gridview you could modify the data, but now you can't. You'll have to create a class (call it DTO or view model) to hold the data you show in the gridview, so you can edit them.
This means that you also have to write the modified results back the original users when you commit the changes.

Binding alias-named column to gridview in ASP.Net

I am using .Net 3.5. I have a site that I have been using gridview controls on. Basically, it is a standard gridview, but with AutoGenerateColumns turned off in favor of creating our own columns via ItemTemplate. Here is an example of one of our custom columns:
<asp:TemplateField HeaderText="Physician" ItemStyle-Width="70px" HeaderStyle-Width="70">
<ItemTemplate>
<asp:Label ID="lblPhysician" runat="server" Text='<%# Bind("LastName") %>' ></asp:Label>
</ItemTemplate>
</asp:TemplateField>
In code behind, I fill a datatable based on an SQL query, and set it as the gridview datasource, and the label is normally populated based on the Bind function seen above during Postback. However, I have a SQL query that utilizes Alias names now. The query is rather large but here is an example:
SELECT LastName, COUNT(Case WHEN <condition> THEN 1 END) AS ABC
FROM tablename WHERE <condition> Group By LastName
The problem is that I cannot use the Bind command on ABC as I use it for LastName. Nothing shows up in the gridview except LastName, even though data is returned for the alias columns. If I set AutoGenerateColumns to true, the gridview is binded with all the correct data, but this is not the way we need the page to work. What am I missing that is not allowing me to bind a column value manually to a control via it's alias name?
Thanks, and let me know if further clarification is needed!
You can grab it from the row on data bound; add an event handler, an in that handler do:
.. Grid_RowDataBound(..)
{
var abc = DataBinder.Eval(e.Item.DataItem, "ABC")
if (abc == null)
((Label)e.Item.FindControl("lblPhysician")).Visible = false;
}
There may be some syntaxes that are off but the gist is that you can extract the field from the data item, and do something with it programmably.
You could also bind it in the item template using a hidden field, or stick it in the DataKeys collection too.

How to get to the next level of Assocation in an EF4 EntityDataSource?

I've used EF4 EntityDataSources to do DataBinding with success, but here's a case where I'm stumped:
Table "CurrentComplaintsByUsers" has a foreign key over to a "Complaints" table. So in EF, I can access a CurrentComplaintByUser record, and navigate to its parent complaint like so:
var ccU = dataContext.CurrentComplaintsByUsers.First();
var parentComplaint = ccU.Complaint;
When I whip up an EntityDataSource based on CurrentComplaintsByUsers to bind a gridview, I want to get over from the "Complaint" object to an Assocation of Complaint called "Status". Here's a StatusID in my Complaint table, and so in code I can hit a complaint's status like so, including the Status properties:
string statusLabel = parentComplaint.Status.LabelText;
FAILURE: when I try to bake this all into an EntityDataSource, I can't get from my starting item "CurrentComplaintsByUsers" over to "Status". Here's my EDS:
<asp:EntityDataSource ID="edsCurrentCases" runat="server"
ConnectionString="name=EOCaseDataModel" DefaultContainerName="EOCaseDataModel"
EnableFlattening="False" EntitySetName="CurrentComplaintsByUsers"
Include="Complaint, Status">
</asp:EntityDataSource>
My error is this:
System.InvalidOperationException
"A specified Include path is not valid.
The EntityType 'EOCaseApp.CurrentComplaintsByUser' does not declare a navigation property with the name 'Status'."
I'm trying to get to the point where this works in my Gridview:
<%# ((CurrentComplaintsByUser)Container.DataItem).Complaint.Status.LabelText %>
So, using declaritive markup only, how do I get to a related objects associations from the EDS? (I can do it in code, just trying to use the EDS exclusively when I can)
Other notes: if I remove "Status" from the "Include" in the EDS, then I get a NULL ERROR when it hits ..Complaint.Status.LabelText in my Gridview, pretty much what you'd expect.
Try changing Include="Complaint, Status" to Include="Complaint, Complaint.Status" in your EntityDataSource

Sorting an asp:ListView bound to an EntityDataSource

I have an asp:ListView control on an ASP.NET page. It is bound to an EntityDataSource which is setup this way:
<asp:EntityDataSource ID="EntityDataSourceOrders" runat="server"
ConnectionString="name=EntitiesContext"
DefaultContainerName="EntitiesContext" EntitySetName="SOrder"
Include="Address"
EnableDelete="True" EnableInsert="True"
EnableUpdate="True">
</asp:EntityDataSource>
In SQL Server there are two tables, SOrder and Address. SOrder has a foreign key AddressID to the Address table ("an order has one address"). The address has an alphanumeric field "Name1".
In the LayoutTemplate of the ListView is a link button to sort the orders in the list by Name1 of the order's address:
<asp:LinkButton runat="server" ID="SortButtonName" Text="Name"
CommandName="Sort" CommandArgument="Address.Name1" />
If I click this button I get an EntitySqlException telling me that "'Address.Name1' could not be resolved in the current context".
Sorting by a "flat" field of the order table - for instance "OrderCode" - works:
<asp:LinkButton runat="server" ID="SortButtonOrderCode" Text="Order number"
CommandName="Sort" CommandArgument="OrderCode" />
So the exception occurs only when I try to sort by an related field in another table. I was expecting that with the Include="Address" property of the EntityDataSource sorting by fields of the related address should be possible, but it seems not.
I've made a test hack to check the query I expect the EntityDataSource to create internally:
With Linq to Entities:
using (EntitiesContext ctx = new EntitiesContext())
{
var result = from order in ctx.SOrder.Include("Address")
orderby order.Address.Name1
select order;
foreach (SOrder x in result)
{
string test=x.Address.Name1;
}
}
Or with Entity SQL:
string queryString = #"SELECT VALUE x FROM SOrder AS x
Order By x.Address.Name1";
using (EntitiesContext ctx = new EntitiesContext())
{
ObjectQuery<SOrder> query =
new ObjectQuery<SOrder>(queryString, ctx).Include("Address");
foreach (SOrder x in query.Execute(MergeOption.AppendOnly))
{
string test=x.Address.Name1;
}
}
Both works! I get a sorted result.
Now I am a bit lost how I get this sort operation working in the ListView. Does somebody have an idea what I am doing wrong here?
Thank you in advance!
I found the solution myself. It's all a matter of three missing characters: In my code above, this ...
<asp:LinkButton runat="server" ID="SortButtonName" Text="Name"
CommandName="Sort" CommandArgument="Address.Name1" />
...is WRONG and has to be replaced by:
<asp:LinkButton runat="server" ID="SortButtonName" Text="Name"
CommandName="Sort" CommandArgument="it.Address.Name1" />
Using "it." for properties of related objects seems to be necessary in contrast to flat fields. Therefore in the second example above both ways are possible:
CommandArgument="it.OrderCode" // works
CommandArgument="OrderCode" // works as well
The same for "object identities" (primary key fields) of related objects:
CommandArgument="it.Address.AddressID" // works
CommandArgument="Address.AddressID" // works as well
But again for related properties which are not identities:
CommandArgument="it.Address.Name1" // works
CommandArgument="Address.Name1" // does NOT work
Crazy, the only place where I could find (accidentally) an indication to this solution, is this video:
How Do I Use the Entity Data Source?
...especially at around 9:40 min of the video.
Associated classes may wont work CommandArguments or eg DropDownList's DataTextField value. You may use Data Transfer Objects for listing and sorting
public class OrderDTO
{
public string AddressName1 {get;set;}
}
using (EntitiesContext ctx = new EntitiesContext())
{
var result = from order in ctx.SOrder
let dto = new OrderDTO
{
AddressName1 = order.Address.Name1
//bla bla
};
orderby dto.AddressName1
select dto;
}

Resources