asp.net list of users by profile property - asp.net

I have created some profile properties for when a new user is added to our system.
One property is called 'Client' and links this user to a particular client and stores a client id.
I am trying to create a page that shows a list of users for each client on the system such as:
Client 1
User 1
User 2
User 3
Client 2
User 4
User 5
User 6
Client 3
User 7
User 8
User 9
Is there a way to get a list of users that match a particular profile property?
Thanks for any help. J.

The code below is an old VB.Net method I wrote to filter users based on a profile value. It could be slightly modified to accomplish your task.
Function FindUsers(ByVal prop As String, ByVal val As String) As List(Of ProfileCommon)
' Use a generic list of people
Dim peeps As New List(Of ProfileCommon)()
ViewState("prop") = prop
ViewState("val") = val
' Get all profile objects
Dim profiles As ProfileInfoCollection = ProfileManager.GetAllProfiles(ProfileAuthenticationOption.All)
' Go through the profiles
For Each info As ProfileInfo In profiles
' We need to turn a ProfileInfo into a ProfileCommon
' to access the properties to do the search
Dim userProfile As ProfileCommon = ProfileCommon.Create(info.UserName)
If Roles.IsUserInRole(info.UserName, "Members Subscribers") Then
' If the birthday matches
If val <> "" Then
If prop <> "" AndAlso Left(userProfile.Item(prop), val.Length) = val Then
' Add them to our list
peeps.Add(userProfile)
End If
Else
peeps.Add(userProfile)
End If
End If
Next
If peeps.Count > 0 Then ShowUserDetails(peeps(0).UserName)
Return peeps
End Function

Found what i was looking for, ended up using this:
http://pretzelsteelersfan.blogspot.com/2007/03/get-aspnet-profile-properties-from-sql.html
Thanks for any help though.

Related

Visual basic and Json.net Web request

Basically what im trying to do is make a program that list game information for league of legends.. using there API to extract data. how this works is you Search there username and it returns an integer linked to that account, you then use that integer to search for all of the information for that account, EG account level, wins, losses, etc.
I've run into a problem i can't seem to figure out.. Please not that I'm very new to Json.net so have little experience about working with it.. Below is how the search for the user ID is found, The First section is the Username Minus Any spaces in the name the next is the ID which is the information i require.
{"chucknoland":{"id":273746,"name":"Chuck Noland","profileIconId":662,"summonerLevel":30,"revisionDate":1434821021000}}
I must be declaring the variables wrong in order to obtain the data as everything i do it returns as 0.
these are the following class i have to store the ID within
Public Class ID
Public Shared id As Integer
Public Shared name As String
End Class
Looking at a previous example seen here Simple working Example of json.net in VB.net
They where able to resolve there issue by making a container class with everything inside it.. My problem is that The data i seek i always changing.. The first set will always be different to the "Chucknoland" that's displayed in the example.. is someone able to explain how i could go about extracting this information?
Please note that the variables rRegion has the value of what server there on, Chuck Noland is on OCE, and sSearch is the Username.. Due to Problems with API keys i had to remove the API key from the code... But the URL returns the Json Provided.
'URL string used to grab Summoner ID
jUrlData = "https://oce.api.pvp.net/api/lol/" + rRegion + "/v1.4/summoner/by-name/" + sSearch +
' Create a request for URL Data.
Dim jsonRequest As WebRequest = WebRequest.Create(jUrlData)
'request a response from the webpage
Dim jsonResponse As HttpWebResponse = CType(jsonRequest.GetResponse(), HttpWebResponse)
'Get Data from requested URL
Dim jsonStream As Stream = jsonResponse.GetResponseStream()
'Read Steam for easy access
Dim jsonReader As New StreamReader(jsonStream)
'Read Content
Dim jsonResponseURL As String = jsonReader.ReadToEnd()
jUrlString = jsonResponseURL
this is the request i have to obtain the information, and this is the code i tried to use to display the ID for that json.
Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
Dim obj As ID
obj = JsonConvert.DeserializeObject(Of ID)(jUrlString)
MsgBox(obj.id)
End Sub
Is anyone able to explain how i can go about getting this to work?
One way to handle this would be to get the item into a Dictionary where the keys are the property names.
The class you have is not quite right unless you only want name and id and not the rest of the information. But using a Dictionary you wont need it anyway. The "trick" is to skip over the first part since you do not know the name. I can think of 2 ways to do this, but there are probably more/better ways.
Since json uses string keys pretty heavily, create a Dictionary, then get the data from it for the actual item:
jstr = ... from whereever
' create a dictionary
Dim jResp = JsonConvert.DeserializeObject(Of Dictionary(Of String, Object))(jstr)
' get the first/only value item
Dim jobj = jResp.Values(0) ' only 1 item
' if you end up needing the name/key:
'Dim key As String = jResp.Keys(0)
' deserialize first item to dictionary
Dim myItem = JsonConvert.DeserializeObject(Of Dictionary(Of String, Object))(jobj.ToString)
' view results
For Each kvp As KeyValuePair(Of String, Object) In myItem
Console.WriteLine("k: {0} v: {1}", kvp.Key, kvp.Value.ToString)
Next
Output:
k: id v: 273746
k: name v: Chuck Noland
k: profileIconId v: 662
k: summonerLevel v: 30
k: revisionDate v: 1434821021000
Using String, String may also work, but it would convert numerics to string (30 becomes "30") which is usually undesirable.
While poking around I found another way to get at the object data, but I am not sure if it is a good idea or not:
' parse to JObject
Dim js As JObject = JObject.Parse(jstr)
' 1 = first item; 2+ will be individual props
Dim jT As JToken = js.Descendants(1)
' parse the token to String/Object pairs
Dim myItem = JsonConvert.DeserializeObject(Of Dictionary(Of String, Object))(jT.ToString)
Same results.

Type-casting entity framework results in ItemDataBound

So I've trying to optimize performance of a page which generates the navigation menu for a website. Basically there is a table called T_product_cat which contains 4 fields I care about:
product_cat_name (the product category name)
product_cat_uid (the unique identifier of the row)
product_cat_thumbnail_path (the image that represents the category)
product_cat_parent_uid (the unique identifier of the product category
that we sit underneath - since these "product folders" can nest)
I need to create a top navigation bar which has just the names of the top level product categories and then for the dropdown navigation I need to output the sub product categories along with their images and links etc. I've got a basic ASP:Repeater control with a nested ASP:Repeater to handle the sub-product categories
Basically though I want to start using EF to start querying for my data. Initially I did a query to just pull the top level items and then in the ItemDataBound event of the repeater, I'd access the data and query the database again for the sub categories. But this was hitting the database 8x (since I've got 7 top level categories). To speed things up I've been trying different iterations of an initial query. Here's my final one for reference:
Using db As New RmpEntities
' query all the items and then all their subitems at the same time so that we don't have to repeatedly hit the database
Dim qry = (
From
productCat In db.T_product_cat
Where
productCat.company_uid = WmsSession.company_uid AndAlso
productCat.enabled = 1 AndAlso
productCat.product_cat_parent_uid = GUIDs.GlobalGuids.RootCategoryUid AndAlso
productCat.product_cat_hide <> 1
Order By
productCat.product_cat_sequence
Select
categoryName = productCat.product_cat_name,
categoryUid = productCat.product_cat_uid,
imagePath = productCat.product_cat_thumbnail_path,
subCategories = (
From
productSubCat In db.T_product_cat
Where
productSubCat.company_uid = WmsSession.company_uid AndAlso
productSubCat.enabled = 1 AndAlso
productSubCat.product_cat_parent_uid = productCat.product_cat_uid AndAlso
productSubCat.product_cat_hide <> 1
Order By
productSubCat.product_cat_sequence
Select
categoryName = productSubCat.product_cat_name,
categoryUid = productSubCat.product_cat_uid,
imagePath = productSubCat.product_cat_thumbnail_path
)
)
rptMainNav.DataSource = qry.ToList()
rptMainNav.DataBind()
End Using
When the repeater's ItemDataBound event fires I do have working code to pick apart the results and bind the data to the sub-repeater (this code works):
Protected Class CategoryInfo
Public Property categoryName As String
Public Property categoryUid As Guid
Public Property imagePath As String
End Class
Private Sub rptMainNav_ItemDataBound(sender As Object, e As RepeaterItemEventArgs) Handles rptMainNav.ItemDataBound
Dim rItem As RepeaterItem = e.Item
Select Case rItem.ItemType
Case ListItemType.Item, ListItemType.AlternatingItem
Dim dataItem = rItem.DataItem
Dim subRepeater As Repeater = rItem.FindControl("rptSubNav")
Dim parentUid As Guid = dataItem.categoryUid
Dim st = DateTime.Now
Dim x As New List(Of CategoryInfo)
For Each item In dataItem.subCategories
x.Add(New CategoryInfo With {.categoryName = item.categoryName, .categoryUid = item.categoryUid, .imagePath = item.imagePath})
Next
subRepeater.DataSource = x
dTime.Add(New MyTimes With {.g = parentUid, .ts = DateTime.Now - st})
subRepeater.DataBind()
End Select
End Sub
But how can I cast the Object type returned by accessing the repeater's DataItem to a more strongly-typed object so I can get intellisense?
Or is there some way I can give up on the worries about typing and just use the query results directly as a DataSource for the sub-repeater? That was my first goal but when I tried to take
dataItem.subCategories.ToList()
It failed with:
Public member 'ToList' on type 'CompensatingCollection(Of VB$AnonymousType_1(Of String,Guid,String))' not found.
When I tried to modify my CategoryInfo class to have another property to hold a list of CategoryInfo classes (subcategories) and have the main query return structured data (so I'd have a type to cast to in the ItemDataBound) things failed even worse. The original query's .ToList failed so I couldn't even do the initial bind.
What is the correct way to handle this? Continue working on properties of an Object which represents an anonymous type? Surely there must be something better.
EDIT:
Robert - Thanks for your suggestions. It turned out that I did NOT have a navigation property to SubCategories. The reason being that the people who came before me designed the database such that all top level categories end up with an artificial product_cat_parent_uid (just some random GUID). It doesn't point to a real product category in the database - it just acts as a placeholder. I question why they didn't just use NULL but it's too late to change it. At any rate since the item doesn't exist in the database, the database itself doesn't have the foreign key since it's faking the link. The databse won't create the link with product categories pointing to a product categorie that is not in the database. I did use your suggestion to find more information about what could be done and I used this article (Entity Framework - Add Navigation Property Manually) to add those links I need.
The question still remains though - can I get strong typing within the ItemDataBind event?

User details stored in separate table ASP.NET Identity

I am a complete beginner at ASP.net(and this forum) i am using Visual studio 2013 and have created created another table in the created database using the package manager console.
How do i go about placing the information into this new table? (I am looking to store firstname and last name in a separate table)
The create account button is below:
Protected Sub CreateUser_Click(sender As Object, e As EventArgs)
Dim userName As String = UserNameCtrl.Text
Dim Firstnane As String = firstnamectrl.Text
Dim manager = New UserManager
Dim User = New ApplicationUser() With {.UserName = userName}
Dim result = manager.Create(User, Password.Text)
If result.Succeeded Then
IdentityHelper.SignIn(manager, User, isPersistent:=False)
IdentityHelper.RedirectToReturnUrl(Request.QueryString("ReturnUrl"), Response)
Else
ErrorMessage.Text = result.Errors.FirstOrDefault()
End If
End Sub
Any pointers in the right direction, hints or suggested reading would be very helpful.
If I understand correctly, this link may be of some help:
http://www.codeguru.com/vb/gen/vb_database/adonet/article.php/c15033/A-Basic-VBNET-ADONET-Tutorial-Adding-Deleting-and-Updating.htm
It is for a windows form application, but it should translate pretty well if you're using web forms. Basically, you just want to make a connection to the database during the button click event (the simplest way I know of to make this connection is using ADO.NET), and pass the values of the first and last name in a SQL query to the sql server.
You would be building the sql query as a string, and concatenating your vb variables into that string. Something like; "Insert into table xxx(firstname, LastName) values " & Firstname & ", " & Lastname...

Different approaches for finding users within Active Directory

I'm a newbie to AD programming, but after a couple of weeks of research have found the following three ways to search for users in Active Directory using the account name as the search parameter:
Option 1 - FindByIdentity
Dim ctx As New PrincipalContext(ContextType.Domain, Environment.MachineName)
Dim u As UserPrincipal = UserPrincipal.FindByIdentity(ctx, IdentityType.SamAccountName, "MYDOMAIN\Administrator")
If u Is Nothing Then
Trace.Warn("No user found.")
Else
Trace.Warn("Name=" & u.Name)
Trace.Warn("DisplayName=" & u.DisplayName)
Trace.Warn("DistinguishedName=" & u.DistinguishedName)
Trace.Warn("EmployeeId=" & u.EmployeeId)
Trace.Warn("EmailAddress=" & u.EmailAddress)
End If
Option 2 - DirectorySearcher
Dim connPath As String = "LDAP://" & Environment.MachineName
Dim de As New DirectoryEntry(connPath)
Dim ds As New DirectorySearcher(de)
ds.Filter = String.Format("(&(objectClass=user)(anr={0}))", Split(User.Identity.Name, "\")(1))
ds.PropertiesToLoad.Add("name")
ds.PropertiesToLoad.Add("displayName")
ds.PropertiesToLoad.Add("distinguishedName")
ds.PropertiesToLoad.Add("employeeId")
ds.PropertiesToLoad.Add("mail")
Dim src As SearchResult = ds.FindOne()
If src Is Nothing Then
Trace.Warn("No user found.")
Else
For Each propertyKey As String In src.Properties.PropertyNames
Dim valueCollection As ResultPropertyValueCollection = src.Properties(propertyKey)
For Each propertyValue As Object In valueCollection
Trace.Warn(propertyKey & "=" & propertyValue.ToString)
Next
Next
End If
Option 3 - PrincipalSearcher
Dim ctx2 As New PrincipalContext(ContextType.Domain, Environment.MachineName)
Dim sp As New UserPrincipal(ctx2)
sp.SamAccountName = "MYDOMAIN\Administrator"
Dim s As New PrincipalSearcher
s.QueryFilter = sp
Dim p2 As UserPrincipal = s.FindOne()
If p2 Is Nothing Then
Trace.Warn("No user found.")
Else
Trace.Warn(p2.Name)
Trace.Warn(p2.DisplayName)
Trace.Warn(p2.DistinguishedName)
Trace.Warn(p2.EmployeeId)
Trace.Warn(p2.EmailAddress)
End If
All three of these methods return the same results, but I was wondering if any particular method is better or worse than the others?
Option 1 or 3 seem to be the best as they provide strongly-typed property names, but I might be wrong? My overall objective is to find a single user within AD based on the user principal value passed via the web browser when using Windows Authentication on a site (e.g. "MYDOMAIN\MyUserAccountName")
For me 1 and 3 are quite the same. In Querying an LDAP in C# answer, I introduce a third way using managed code which is low level (native LDAP) protocol with System.DirectoryServices.Protocols (S.DS.P).
I don't know if your purpose is just to authenticate a user or authenticate a user and retrieve some datas (profile) from Active-Directory, but keep in mind that a LDAP query is first a query, and the old fashion (your solution 2) let's you specify the properties you retrieve. Before choosing, make some test on a performance point of view.
If you just want to authenticate you can compare native LDAP and user Principal responses from another article

Detect what Domain User Group a Windows User is in with VB.NET

I know that using Dim currUser As String = Request.ServerVariables("LOGON_USER") returns the Domain\Username, but I want to know what Group that user is in say in Active Directory.
Do you want a list of the groups? Or do you want to check if the user is a member of a specific group?
If the latter, you can use WindowsPrincipal.IsInRole() to check if the user belongs to a specific group:
http://msdn.microsoft.com/en-us/library/fs485fwh.aspx
For example, if you want to check if the user is an Administrator you can use:
If Page.User.IsInRole("BUILTIN\Administrators") Then
' Do something
End If
You can use UserPrincipal.GetAuthorizationGroups Method
imports System.DirectoryServices.AccountManagement
dim name as string = Request.ServerVariables("LOGON_USER")
dim user As UserPrincipal = UserPrincipal.FindByIdentity( new PrincipalContext( ContextType.Domain ), name)
dim groups As PrincipalSearchResult(Of Principal)= user.GetAuthorizationGroups()

Resources