MVC4 Postal - Accessing User Email Address searching by UserId - asp.net-mvc-4

I have a site where user A can book a lesson with a teacher, I then want to have an email sent to the teachers saying user A wants to book a lesson with you etc.
I have postal up and running sending emails without issue,
however, I don't know how to access the email address of the teacher to send the email.
The email address is saved as part of the built in UserProfile table. I have the teacher's UserId (as it's stored in a separate teacher table).
So is there a way to access the teachers email ,searching by UserId?
In any other table I would use t in db.Teacher.find(id) but this doesn't work within the Account Controller.
This was built using the default MVC4 internet website template using the built in simple membership. Let me know if more information is needed.
I've added the following to the AccountController;
private UsersContext db = new UsersContext();
public ActionResult EmailNotification(int id)
{
var user = from l in db.UserProfiles.Find(id)
select l;
}
db.UserProfiles.Find(id) however gives the following error;
Could not find an implementation of the query pattern for source type 'LessonUp.Models.UserProfile'. 'Select' not found.
Which I assume is a result of it not being created through the entity framework?

I think your query needs to be something like the following:
var result = from q in context.UserProfiles
where q.UserId == id
select q;

Related

LDAP_MATCHING_RULE_IN_CHAIN not working with default AD groups - Domain Users

In my program, I need to fetch all the AD groups for a user.
The current version of my program uses System.DirectoryServices.AccountManagement.UserPrincipal.GetAuthorizationGroups.
This works good until we had a new customer with a much largeer AD. There it is really slow. (Up to 60 seconds)
Now I've been looking around, and saw the posts that the AccountManagement is easy to use, but slow.
I also found that LDAP_MATCHING_RULE_IN_CHAIN should also fetch all the nested groups that a user is member of. And is more performant.
From this link.
But I'm having an issue with the default groups that in AD exists.
For example the group "Domain Users" is not returned by the function.
They also have a group "BDOC" that as member have "Domain Users". That group is also not returned.
Trough the GetAuthorizationGroups it is returned correct.
I'm using following code to fetch the groups by user.
VB.NET:
Dim strFilter As String = String.Format("(member:1.2.840.113556.1.4.1941:={0})", oUserPrincipal.DistinguishedName)
Dim objSearcher As New DirectoryServices.DirectorySearcher("LDAP://" & oLDAPAuthenticationDetail.Domain & If(Not String.IsNullOrWhiteSpace(oLDAPAuthenticationDetail.Container), oLDAPAuthenticationDetail.Container, String.Empty))
objSearcher.PageSize = 1000
objSearcher.Filter = strFilter
objSearcher.SearchScope = DirectoryServices.SearchScope.Subtree
objSearcher.PropertiesToLoad.Add(sPropGuid)
objSearcher.PropertiesToLoad.Add(sPropDisplayName)
Dim colResults As DirectoryServices.SearchResultCollection = objSearcher.FindAll()
Afterwards I was testing with the script from the link, if it was possible to fetch all the users from the Domain Users group, by changing the "member" to "memberOf" in the filter.
When I put the Domain Admins group in the filter, it shows the admins correct.
When I put the Domain Users group in the filter, it returns nothing.
Powershell:
$userdn = 'CN=Domain Users,CN=Users,DC=acbenelux,DC=local'
$strFilter = "(memberOf:1.2.840.113556.1.4.1941:=$userdn)"
$objDomain = New-Object System.DirectoryServices.DirectoryEntry("LDAP://rootDSE")
$objSearcher = New-Object System.DirectoryServices.DirectorySearcher
$objSearcher.SearchRoot = "LDAP://$($objDomain.rootDomainNamingContext)"
$objSearcher.PageSize = 1000
$objSearcher.Filter = $strFilter
$objSearcher.SearchScope = "Base"
$colProplist = "name"
foreach ($i in $colPropList)
{
$objSearcher.PropertiesToLoad.Add($i) > $nul
}
$colResults = $objSearcher.FindAll()
foreach ($objResult in $colResults)
{
$objItem = $objResult.Properties
$objItem.name
}
I don't know what I'm doing wrong. Or is it maybe just not possible to fetch the "default groups" with that filter?
What is a good alternative then?
The default group is odd. It is not stored in memberOf, or even in the member attribute of the group. That's why your search won't find it. The default group is determined by the primaryGroupId of the user. That attribute stores the RID (the last part of the SID) of the group. It's kind of dumb, I know :)
I actually wrote an article about the 3 (yes 3) different ways someone can be a member of a group: What makes a member a member?
I also wrote an article about getting all of the groups a single user belongs to, and how to account for all 3 ways: Finding all of a user’s groups
For example, here is the C# code I put in that article about how to find the name of the primary group for a user (given a DirectoryEntry). It shouldn't be too hard to translate that to VB.NET:
private static string GetUserPrimaryGroup(DirectoryEntry de) {
de.RefreshCache(new[] {"primaryGroupID", "objectSid"});
//Get the user's SID as a string
var sid = new SecurityIdentifier((byte[])de.Properties["objectSid"].Value, 0).ToString();
//Replace the RID portion of the user's SID with the primaryGroupId
//so we're left with the group's SID
sid = sid.Remove(sid.LastIndexOf("-", StringComparison.Ordinal) + 1);
sid = sid + de.Properties["primaryGroupId"].Value;
//Find the group by its SID
var group = new DirectoryEntry($"LDAP://<SID={sid}>");
group.RefreshCache(new [] {"cn"});
return group.Properties["cn"].Value as string;
}
You are right that the AccountManagement namespace makes things easy, but it really does have terrible performance sometimes. I never use it anymore. I find that DirectoryEntry/DirectorySearcher gives you much more control of how often your code makes calls out to AD.
I have been meaning to write an article about writing high performance code with DirectoryEntry, but I haven't gotten around to it yet.
Update: So if you need the nested groups for the user, including membership through the primary group, then you can find the primary group first, then do an LDAP_MATCHING_RULE_IN_CHAIN search for groups that have both the user and the primary group as members:
(|(member:1.2.840.113556.1.4.1941:={userDN})(member:1.2.840.113556.1.4.1941:={primaryGroupDN}))
Update: If you want to include Authenticated Users in your search (edit the DC portion of the distinguishedName):
(|(member:1.2.840.113556.1.4.1941:=CN=S-1-5-11,CN=ForeignSecurityPrincipals,DC=domain,DC=com)(member:1.2.840.113556.1.4.1941:={userDN})(member:1.2.840.113556.1.4.1941:={primaryGroupDN})
Note that you can also use the tokenGroups attribute of a user to find out all of the authentication groups for a user. The tokenGroups attribute is a constructed attribute, so you only get it if you specifically ask for it (with DirectoryEntry.RefreshCache() or, in a search, add it to DirectorySearcher.PropertiesToLoad.
The caveat is that tokenGroups is a list of SIDs, not distinguishedName, but you can bind directly to an object using the SID with the LDAP://<SID={sid}> syntax.

How do I get the Id of a user given the email address in ASP.NET MVC Entity Framework

I have user information in my database. I wish to get the ID of a user given the email address. To get this in sql you would write the following query code:
SELECT Id FROM TableName WHERE email_address = "xyz#somename.com";
How do I write this using ASP.NET MVC Entity-Framework?
Well, it depends entirely on your public API, which we have no visibility into. Generally speaking, it would look something like:
var userId = db.Users
.Where(m => m.email_address == "xyz#somename.com")
.Select(m => m.Id)
.SingleOrDefault();
I suggest you take some time with the tutorials at https://www.asp.net/mvc/overview/models-data, to get your bearings.

SQL query to filter out users who already have recieved an email

Suppose:
You tried to send a mass mailing, but something went wrong, and only some users got the mail.
You sent a mass mailing recently, but now new users have signed up, and they need to receive the mail as well.
How do you filter those who have already received the news (via an Eloquent query or a select command from database .)
Actually I faced this problem in a project based on Laravel 4, I am searching for a query using Laravel Eloquent on a pivot table and keep track the sent emails to the users.
In my case there is two Model: Post and User
Its a many to many relationship: any user can receive many posts and any post can be sent to many users
You'll want to add a column to your users table eg a datetime field called mailed_at. Then in your email or signup method (wherever it is you're sending that first email) update the user with the datetime they were emailed.
From then on you can query based on mailed_at for any users who still need an email.
To check for multiple users that need a newsletter, let's say your users table schema is as follows (keeping it simple):
id | email | password | mailed_at (nullable)
We check here whether a user has received an email by querying based on the mailed_at column. To get all users that need to receive a mailout you would do the following:
$usersToMail = User::whereNull('mailed_at')->get();
There is two Model: Post and User
Its a many to many relationship: any user can receive many posts and any post can be sent to many users
I implemented it as the following:
class Post extends Eloquent {
public function recipients()
{
return $this->belongsToMany('User', 'posts_users', 'post_id', 'user_id');
}
}
class User extends Eloquent {
public function mails()
{
return $this->belongsToMany('Post', 'posts_users', 'user_id', 'post_id');
}
}
So, when I want to send a post to users I use
$usersToMail = User::whereNotExists(function($query) use ($post_id)
{
$query->select(DB::raw(1))
->from('posts_users')
->whereRaw('posts_users.user_id = users.id')
->whereRaw('posts_users.post_id = '.$post_id);
})->get();
foreach ($usersToMail as $user)
{
// send email
$user->mails()->save($post); // it records that this post has been sent to the user
}

Grails; how to refer to a domain property in native sql query

I have a domain class UserProfile which has one to one relationship with another domain class User.The Structure of the domain is provided.
сlass UserProfile {
String fio
String position
String phone
String email
static belongsTo = [user: User]
static constraints = {
// some constraints
}
static mapping = {
//some mapping; user property is not mapped
}
I need to write a native sql query in Grails for UserProfile domain and I don't know how to refer to user property(static belongsTo = [user: User]). I have tried USER_ID but it is not working.
I can't name the column directly using mapping section; I just need to find out how user column in UserProfile domain is named in database and how it can be called in native sql query.
Very Simple if i got your question ,Grails gorm convention for storing fileds in data base is:
Like
user_profile for UserProfile -Domain
and all fileds are speparedted by underscores and most of the time gorm adds _id after a foreign key reference /or a GORM relationship like above One to One and one to Many
[belongsTo=[user]] .
Inside SQL Table
mysql describe user_profile ;
----------------------------------------------------------------
User_Profile
----------------------------------------------------------------
id
version
foo varchar(50)
postion
email
user_instance_id int
-------------------------------------------------------------------
NATIVE SQL QUERY WILL BE :
'select up.user_instance_id from user_profile as up '
the Get all the userInstance objects by querying the user table
'select * from user where user.id = 'the id you get it from the above query'
I hope you have some idea on this please ,if i didnt get it let me know.
I believe if you define user inside UserProfile, then you can access it and will automatically be mapped? It works in my previous projects, I hope it will work with this.
сlass UserProfile {
String fio
String position
String phone
String email
static belongsTo = [user: User]
User userInstance;
static constraints = {
// some constraints
}
Then you can use it
UserProfile.executeQuery("select up.userInstance from UserProfile up")

RavenDB - retrieving part of document

I am playing with Raven DB for few days and I would like to use it as a storage for my Web chat application. I have document which contains some user data and chat history - which is big collection chat messages.
Each time I load user document chat history is also loaded, even if I need only few fields like: user name, password and email.
My question is: how to load only part of document from database ?
Tomek,
You can't load a partial document, but you can load a projection.
session.Query<User>()
.Where(x=>x.Name == name)
.Select( x=> new { x.Name, x.Email });
That will load only the appropriate fields
From what I've seen you can do this (based on the original "User" scenario above):
public class UserSummary
{
public string Name { get; set; }
public string Email { get; set; }
}
Then you can do this:
documentSession.Query<User>().AsProjection<UserSummary>();
Looking at the Raven server it spits this out as part of the query:
?query=&pageSize=128&fetch=Name&fetch=Email&fetch=Id
So it looks like it is querying and returning only a subset of the original object, which is good.
This also works:
documentSession.Query<User>().Select( x=> new User { Name = x.Name, Email= x.Email })
But I don't think that is as clean as returning a UserSummary object.
Some follow up questions to those who have posted responses:
The link to RaccoonBlog has this example:
https://github.com/ayende/RaccoonBlog/blob/master/RaccoonBlog.Web/Infrastructure/Indexes/PostComments_CreationDate.cs
Would that method be preferred over the .AsProjection()? What is the difference between the two approaches?
Tomek, you cannot load only a part of the document.
However, I understand the problem in your case. I recommend to use two seperate documents for each user: One that actually contains the users data (name, passwordhash, email, etc.) and one that contains all the users messages. That way, it is still very cheap to load all the messages of a user and also to load a list of user for general purposes.
This is actually quite similar to how one would model a blog-domain, where you have a post and the posts comments. Take a look at RaccoonBlog to see how this works.