How can I get the logged in user's UserId? I'm using the standard system generated AccountModel. I can get the username using:
User.Identity.Name
but I don't see the UserId field. I want to use the UserId as a foreign key for another table.
Try this:
using Microsoft.AspNet.Identity;
User.Identity.GetUserId();
That's how its done in the partial views for current MVC (MVC5/EF6/VS2013) templates.
Correct me if I'm wrong, because I've seen Aviatrix's answers a lot, but what happens if more than one user has the same name in the database?
I think you're looking for ProviderUserKey - Gets the user identifier from the membership data source for the user.
object id = Membership.GetUser().ProviderUserKey
Membership.GetUser() - Gets the information from the data source and updates the last-activity date/time stamp for the current logged-on membership user.
The best way to do so is to use the WebSecurty class
var memberId = WebSecurity.GetUserId(User.Identity.Name);
and don't forget to add [InitializeSimpleMembership] on top of your controller :)
Their are already very good answer but what i understood from your question is that you want to fetch data from database using id.so here is what you can do.
public List<ForeignkeyTable> RV()
{
var email = User.Identity.Name;
Usertable m = db.Uusertables.Where(x => x.user_Email == email).SingleOrDefault();
var id = m.user_Id;
var p = db.ForeignkeyTable.Where(x => x.user_fk_id == id).ToList();
return p;
}
This way you can return all the data from database of that id in foreignkey.
Related
I need to create an item with Person/People field.
I am able to populate fields like Title, DateTime, TextField as seen below, but I am not able to populate Person field at all.
I have tried sending Display Name, User ID and UPN.
var fieldValueSet = new FieldValueSet();
fieldValueSet.AdditionalData = new Dictionary<string, object>();
fieldValueSet.AdditionalData.Add("Title#odata.type", "Edm.String");
fieldValueSet.AdditionalData.Add("Title", task.Title);
fieldValueSet.AdditionalData.Add("Plan#odata.type", "Edm.String");
fieldValueSet.AdditionalData.Add("Plan", plan.Title);
fieldValueSet.AdditionalData.Add("Assigned#odata.type", "Edm.String");
fieldValueSet.AdditionalData.Add("Assigned", assignee.UserPrincipalName);
fieldValueSet.AdditionalData.Add("DueDate#odata.type", "Edm.String");
fieldValueSet.AdditionalData.Add("DueDate", task.DueDateTime);
var listItem = new ListItem
{
Fields = fieldValueSet
};
await graphServiceClient.Sites["SPURL:/sites/ITOddeleni:"].Lists["ListName"].Items
.Request()
.AddAsync(listItem)
Does your user principal name look like an email? (e.g. some.person#yourtenant.onmicrosoft.com). If that is the case then you should probably try to convert it to a sharepoint-claim version: i:0#.f|membership|some.dude#yourtenant.onmicrosoft.com.
If you have an authenticated ClientContext in your app, then you could resolve the username by calling the SharePoint utility:
Utility.ResolvePrincipal(context, context.Web, userEmail, PrincipalType.User, PrincipalSource.All, null, true);
If you don't have a context then you can try and combine strings (not as robust, but should work as well).
This answer suggests that you should try and set the LookupId value for the field (sorta the same way you set user values using the SharePoint's REST api):
var assigneeLookupId = // Get the assignee's user id on the site (wssid)
fieldValueSet.AdditionalData.Add("AssignedLookupId#odata.type", "Edm.Int32");
fieldValueSet.AdditionalData.Add("AssignedLookupId", assigneeLookupId);
The following schema would allow you to insert multiple person values:
SOLUTION
After help from comments i got this answer which worked
{
"AssignedLookupId#odata.type" : "Collection(Edm.Int32)"
"AssignedLookupId": [1,2,3]
}
This approach is in line with the way MS Graph returns values for Lookup fields.
I have done a fair amount of research on how to limit amount of users that can login into an application. Now I've seen people mentioning cookie-based checkups to see how many users are logged into the account but I haven't seen any implementation where I could see how that works exactly.
Besides that I'm wondering if there is already implemented solution of this in .NET MVC 5?
My final goal is following:
Only two users can login on one account
If third user logs in, the first one that logged in should be kicked out of the system automatically
Can someone help me out with this one ?
Best regards
This check sounds similar to Netflix check - you can login using only 5 devices.
But there is limitation on devices - hence different sessions in same login ID can be identified using IP addresses and device information in HTTP packet.
This is very nice code sample.
IsUserLoggedInElsewhere will check the logins from other places.
Instead of log everyone else out you will have to log out the first user based on login time whenever third user logs in using same account.
Please refer this article for more details about this.
public static bool IsYourLoginStillTrue(string userId, string sid)
{
CapWorxQuikCapContext context = new CapWorxQuikCapContext();
IEnumerable<Logins> logins = (from i in context.Logins
where i.LoggedIn == true &&
i.UserId == userId && i.SessionId == sid
select i).AsEnumerable();
return logins.Any();
}
public static bool IsUserLoggedOnElsewhere(string userId, string sid)
{
CapWorxQuikCapContext context = new CapWorxQuikCapContext();
IEnumerable<Logins> logins = (from i in context.Logins
where i.LoggedIn == true &&
i.UserId == userId && i.SessionId != sid
select i).AsEnumerable();
return logins.Any();
}
public static void LogEveryoneElseOut(string userId, string sid)
{
CapWorxQuikCapContext context = new CapWorxQuikCapContext();
IEnumerable<Logins> logins = (from i in context.Logins
where i.LoggedIn == true &&
i.UserId == userId &&
i.SessionId != sid // need to filter by user ID
select i).AsEnumerable();
foreach (Logins item in logins)
{
item.LoggedIn = false;
}
context.SaveChanges();
}
I think it can be done by one of two ways:
1 : by data base
-- Add a field in users table refer to login_status (Bool)- and Last_login_Time (Date)
-- Change login_status to (True) and Last_login_Time to dateTime.now
-- Before login get from Users table number of users with login_status true
-- if count less than two ..normal login
-- if count more than = 2 end session for user with earlier login time and set current user is logged..
2 - Also it can be done by using global variables in Global.asax and
I have users table with generated LINQ-class with followed structure:
class User {
int Id;
string Login;
string Password;
string Mail;
...
Now I need to update specified columns (for ex. only Login and Password) and because I don't want to overwrite other fields, my code looks like this:
public User UpdateUser(int userId, User newUser)
{
User user = (from u in _context.Users
where u.Id == userId
select u).FirstOrDefault();
if (newUser.Login != default(string)) user.Login = newUser.Login;
if (newUser.Mail != default(string)) user.Mail = newUser.Mail;
if (newUser.Password != default(string)) user.Password = newUser.Password;
...
_context.SubmitChanges();
return user;
}
And call it like this:
var user = new User { Password = "123" };
UpdateUser(123, user);
For each field I need to write IF statement and I thinking that I doing something wrong. Also because I am using comparsion with default(string) I cannot set empty values to rows.
Please, tell me, what is right way to do this?
P.S.: Please, sorry for my bad English.
You are misusing LINQ 2 SQL. You shouldn't even have a generic UpdateUser method because you don't need it. If you want to write a certain field of an entity, just do it:
var user = GetUser(userId);
user.Password = "123";
And you're done. When you have made all changes to the object model, call SubmitChanges at the end. It is not necessary to call it after each mutation.
You are using LINQ 2 SQL as a CRUD repository but it is not meant to be one. It is meant to give you a live object model that you can treat like normal C# objects. In the end you synchronize with the database by calling SubmitChanges.
This is possible just with SubmitChanges:
This gets the user:
var user=context.User.Where(m=>m.id == "xyz").FirstOrDefault();
This updates the above user:
user.Password = "xyz";
context.User.SubmitChanges();
I think you are looking into the wrong way for optimization. An update command on single column isn't much different than on every other column than PK. Your validation logics might take more time to process than your optimized update command.
However if it is always the password that needs to be updated, you can do it this way :
public User ChangePassword(int userId, string password)
{
var user = new User() { Id = userId };
_context.Users.Attach(user);
user.Password = password;
_context.SaveChanges();
return user;
}
I'm using a code-first approach to display data from multiple tables using SQL Server. For my C# semester project, I'm building a social networking website. In my index view I want to display data from two tables, that is, from Posts and Comments.
I'm trying a lot but nothing below is in my Index action.
First, I was using this but later I think it performs only a simple join between tables.
public ActionResult Index()
{
var myobj = DB.Comments.Include("Post").ToList();
return View(myobj);
}
If I use the SQL query below instead of above inside my Index action and pass them to the view, it generates an exception. How do I avoid that?
public ActionResult Index()
{
var myobj = from u in DB.Posts
join b in DB.Comments
on u.UserID equals b.UserID
into obj
from ua in obj.DefaultIfEmpty()
select new { userComments = (ua == null) ? "" : ua.UserComments, UserPosts = u.UserPosts };
return View(myobj);
}
where inside Index.cshtml I'm using a strongly typed View:
#model IEnumerable<myApp.Models.DB.Comment>
and then display all posts and comments using a foreach loop.
But it displays only those posts which postID is present in the Comments table (foreign key from post is in the comment table).
How would I display all posts along with their comments (if any)?
I'm using an .edmx file for the backend while for retrieving/adding data from the database I'm using a code-first approach.
Here's a code example:
private SocialNetworkingEntities net = new SocialNetworkingEntities();
public void Add(RegisterView user)
{
DB.UserInfo User = new DB.UserInfo();
User.Name = user.UserName;
User.Password = user.UserPassword;
User.Email = user.UserEmail;
User.Birthday = user.UserDOB;
User.Sex = user.UserSex;
net.UserInfoes.Add(User);
net.SaveChanges();
}
If you want to display the posts with optional comments, then Post and not Comment is your main model type. Also, you don't have to manually join tables like you do in your second approach - that is done by EF automatically.
So first use the pattern of your first approch and change it to return the posts. The comments are accessible by your navigation property (Posts):
public ActionResult Index()
{
var allPosts = DB.Posts.Include("Comments").ToList();
return View(allPosts);
}
Second, change the modeltype in your view to Post:
#model IEnumerable<myApp.Models.DB.Post>
Now you should be able to enumerate all Posts and optional the Comments:
#foreach (Post post in Model) {
// display post
foreach (Comment comment in post.Comments) {
// display comment
}
}
The problem with your second approach is that your View is expecting a ViewModel of type Comment. But if you look at the query you return an anonymous type instead of a comment.
In your first query you start with Comments and load all the Posts for the comments. This way you wouldn't get posts that don't have any comments.
I think the easiest way is to define an association from Posts to Comments and change your query to:
var myobj = DB.Posts.Include("Comments").ToList();
If you then modify your View to accept a Model of type Post everything should work.
I use EF 4 and Membership Provider Shipped with ASP.Net 4.0.
I need find all Users in a Specific Role and Populate a DropDownList using List<ListItem>.
DataBase Tables involved are:
aspnet_Roles
aspnet_Users
aspnet_UsersInRoles
Navigation Property from aspnet_Users to aspnet_Roles (using junction table aspnet_UsersInRoles) is:
myUser.aspnet_Roles
Matching RoleID (Guid) "CE44ED48-E9F9-49C6-9E15-E40EEFDC7479")
My Script:
using (CmsConnectionStringEntityDataModel context = new CmsConnectionStringEntityDataModel())
{
IQueryable<aspnet_Users> userQuery = from aspnet_Users in context.aspnet_Users select aspnet_Users;
IQueryable<aspnet_Roles> roleQuery = from aspnet_Roles in context.aspnet_Roles select aspnet_Roles;
List<ListItem> myListUsersInRoles = new List<ListItem>();
foreach (aspnet_Users myUser in userQuery)
{
// PROBLEM HERE
if (myUser.aspnet_Roles.ToString() == "CE44ED48-E9F9-49C6-9E15-E40EEFDC7479")
myListUsersInRoles.Add(new ListItem(myUser.UserName.ToString(), myUser.UserId.ToString()));
uxListUsers.DataSource = myListUsersInRoles;
uxListUsers.DataBind();
}`
Problems:
IF return FALSE always, so I am not able to populate List<>.
I suppose I am doing wrong in if an some Properties.
Do you have any ideas? Thanks for your time.
myUser.aspnet_Roles is an EntitySet<aspnet_Roles> (in other words, a collection of roles, so it's highly unlikely that it's string representation happens to match the string representation of the role you're after's ID.
There are several ways you could fix it. One is:
// ...
if (myUser.aspnet_Roles.Any(r => r.RoleId.ToString() == "CE44ED48-E9F9-49C6-9E15-E40EEFDC7479"))
// ...
Also note that from y in x select y is just the same as x, so you could write
foreach (aspnet_User myUser in context.aspnet_Users)
// ...
And not bother declaring userQuery or roleQuery. (You don't actually seem to be using roleQuery anywhere anyway...)
Also, you could look at using the membership/roles API to fetch users in a role:
using System.Web.Security; // at the top of your file
var usersInRole = Roles.GetUsersInRole("name of role here, NOT the guid");
Note that this returns an array of usernames, not user objects, so you'd have to do a little extra work to get the User ID, but it is something you could think about...