I have a table for messages and another table for messageviews. I'm looking to show unread messages to an individual user. With my message table, I've sent up a new field that looks to see if any messageviews exist for the current message. If they do, then my Viewed bool should return true otherwise false(if they haven't viewed the message). Everything works fine, except that I'm unable to find the currently logged in user with User.Identity.GetUser() as I normally would. I've added the correct usings as well. Is there some limitation within a model to restrict this type of call. If so, how can I find the current user within a model?
public bool Viewed
{
get
{
ApplicationDbContext db = new ApplicationDbContext();
//var _userId = User.Identity.GetUserId();
var _userId = Thread.CurrentPrincipal.Identity.GetUserId();
List<MessageView> m_List = db.MessageView.Where(u => u.UserId == _userId && u.MessageId == O_MessageId).ToList();
var count = m_List.Count();
if (count >= 1)
{
return true;
}
else
{
return false;
}
}
}
Resolved: Outside of a controller you can find the current user with this -
var _userId = System.Web.HttpContext.Current.User.Identity.GetUserId();
Outside of a controller you can find the current user with this:
var _userId = System.Web.HttpContext.Current.User.Identity.GetUserId();
Related
ModelState.AddModelError not working while posting the same user name to the database
Here if username not matching it will create a new user to the database
public ActionResult Signup(User user)
{
using (var context = new dbTournamentEntities())
{
bool check = context.Users.Any(m => m.UserName == user.UserName);
if (check)
{
ModelState.AddModelError("", "User Already Exist Try Different User Name");
}
else
{
var hashpass = HashPassword(user.Password);
user.Password = hashpass;
context.Users.Add(user);
context.SaveChanges();
}
}
return RedirectToAction("Login");
}
The only reason your ModelState.AddModelError is not working if the variable check has a false value.
There are two possible cases that you can look for
If your database context has no value in user.
If your database context has same name user present then it is case sensitivity issue, try to make both uppercase and lowercase and then check for equality.
bool check = context.Users.Any(m => m.UserName.ToUpper() == user.UserName.ToUpper());
So I've got the following lines of code:
else
{
//if not found, call Gateway Add()
user.Id = await C3SDbContext.UserGateway.NextIdAsync(context);
user.CreatedById = modifier.CreatedById;
user.CreatedBy = modifier.CreatedBy;
user.DateCreated = DateTime.Now;
user.UserType = "G";
System.Diagnostics.Debug.WriteLine(user.UserType);
user.Status = UserStatus.NEW;
System.Diagnostics.Debug.WriteLine(user.UserType);
user.Uic = await C3SDbContext.UicGateway.GetUicByIdAsync(context, user.UicId);
System.Diagnostics.Debug.WriteLine(user.UserType);
user.Role = await C3SDbContext.RoleGateway.GetRoleByIdAsync(context, user.RoleId);
System.Diagnostics.Debug.WriteLine(user.UserType);
if (ModelState.IsValid)
{
userCheck = await C3SDbContext.UserGateway.AddNewGovernmentUserAsync(context, user, modifier);
}
else
{
System.Diagnostics.Debug.WriteLine(user.UserType);
ICollection<ModelState> ListValues = ModelState.Values;
List<object> Errors = new List<object>();
foreach (var item in ModelState.Values)
{
if (item.Errors.Count() > 0)
{
Errors.Add(item.Errors);
}
}
}
}
user is an instance of GovernmentUser.cs, which inherits from User.cs. UserType is a string property of User. When I run this, all the instances of "System.Diagnostic.Debug.WriteLine(user.UserType);" return "G" in the Output window. Heowever, the Errors list returns one item, telling me that UserType is null.
My questions are: what is going on here? How can they both come to different results, when executed at the same type, and how can I get it so that ModelState.IsValid == true?
ModelState checks the data that was posted to you in MVC. I don't know if this is in your controller or not, but if it is, then my guess is that the UserType wouldn't be on the original data that was posted. I don't think you can use that check after setting it server-side. It is a check on the data received from the client. If UserType isn't required on the client side, just remove that rule from the Dto. However, if you are uploading the actual Entity directly here and it is using the Required attribute that EF uses, then I would just save it like normal and let EF handle the valdiation instead of using ModelState.
I am making a windows application that sync the source data to Active Directory.
This application works like this.
Choose Source Data(Department, User)
Mapping user or department attributes from source data
When Application service is run, it create groups and users in Active Directory
And also it sets the attributes to users and groups.
When I try to set group or user attributes(properties), it throws exception message like this.
in DirectoryEntry.CommitChanges(); block
The directory
service cannot perform the requested operation on the RDN attribute of an object.
I tried to solve it, but it's really hard to me because I`m not good at Active directory...
Code is below, Please share your knowledge.
//ppk: department key column, pk:user key column, row : Source DataTable's row
void CreateADUser(string ppk,string pk,DataRow row)
{
//password
string pass = GetPass(pk,row,LogSections.AD);
//OU
DirectoryEntry addept = adm.FindOU(ppk);
//principal path
string sOU = adm.GetPrincipalPath(addept);
var aduser = adm.CreateNewUser(sOU, pk, pass, pk, null, null, adm.sDomain);
SetAdUserProperties(pk, pass, row);
MoveUser(ppk,pk);
}
void SetAdUserProperties(string pk,string pass,DataRow row)
{
if (row == null) return;
//list of mapped column(AD User attributes)
List<ADMapping> MappingPatterns = GetAdMappings(Words.User,false);
//Columns name of Source Data table's row
var colnames = Tool.GetColNames(row);
//get user proterties
var aduser = adm.GetUser(pk);
//directory entry of users
var de=aduser.GetUnderlyingObject() as DirectoryEntry;
//looping mapped column of user attributes
foreach (var ADMap in MappingPatterns)
{
string val = ADMap.Mapping;
//mapped columns value
val=Util.ReplaceColPattern(val, row);
SetProperty(de, ADMap.CN, val);
}
if (!string.IsNullOrWhiteSpace(pass))
{
var UserPkColumn = AppConfigHelper.GetAppString(Words.SourceUserPKColumn);
UserPkColumn = Util.GetActualColName(UserPkColumn);
aduser.SetPassword(pass);
QueryHelper.Update(QueryHelper.ConnectionString, Words.ShadowUserTable
,new SqlParameter[] { new SqlParameter("#passwd", pass) }
, new SqlParameter("#"+UserPkColumn,pk));
}
aduser.Save();
}
public void SetProperty(DirectoryEntry oDE, string sPropertyName, object sPropertyValue)
{
if (sPropertyValue != null && !string.IsNullOrWhiteSpace(sPropertyValue.ToString()))
{
if (oDE.Properties.Contains(sPropertyName))
{
oDE.Properties[sPropertyName].Value = sPropertyValue;
}
else
{
oDE.Properties[sPropertyName].Add(sPropertyValue);
}
try
{
oDE.CommitChanges(); //exception here.
oDE.Close();
}
catch (Exception)
{
}
}
}
I also asked this question to other forums, and finally got it.
Before DirectoryEntry.CommitChanges(); set UserPropertyCache property to true
and call the RefreshCache method.
It's hard to see what's the cause of the issue here as we're not seeing what attributes you are trying to set.
That said, you can't just add an attribute if it doesn't exist on your AD object so this part of your code definitely has an issue :
if (oDE.Properties.Contains(sPropertyName))
{
oDE.Properties[sPropertyName].Value = sPropertyValue;
}
else
{
//The following line will never work in this context
oDE.Properties[sPropertyName].Add(sPropertyValue);
}
If I had to make an educated guess, I'd say you're either trying to set an attribute that can't be set, or the User you're adding doesn't have all it's mandatory attributes set.
I built a query to find a user by the username. When I run the program I get:
InvalidOperationException: Sequence contains more than one element
I checked the test database, and there's with only 4 users and no double names. Where can the exception come from? Here is the query:
public void setUser(String userName)
{
AzaraUser = DatabaseConnection.DataContext.GetTable<AzaraUser>()
.SingleOrDefault(a => a.ProgramUserName == userName || a.UserName == userName);
}
With the tips below I tried debugging and found that the method becomes an empty string. So in this case it's normal that I get several responses because the ProgramUserName is only in a few rows not null because it is for user who log in with an active directory account.
But why do I get this empty string? Could it be that the WebSecurity is also empty on that moment? At which point will it get the information about the current user?
Here is my log in method:
[HttpPost]
public ActionResult Login(FormCollection logInForm)
{
// try the default membership auth
if (Membership.ValidateUser(logInForm["name"], logInForm["password"]))
{
FormsAuthentication.SetAuthCookie(logInForm["name"], false);
user.setUser(WebSecurity.CurrentUserName);
string returnUrl = Request.QueryString["ReturnUrl"];
if (returnUrl == null)
{
Response.Redirect("~/home/index");
}
else
{
Response.Redirect(returnUrl);
}
}
else
{
ModelState.AddModelError("", "Login failed");
}
// try to auth user via AD
using (PrincipalContext pc = new PrincipalContext(ContextType.Domain))
{
if (pc.ValidateCredentials(logInForm["name"], logInForm["password"]))
{
FormsAuthentication.SetAuthCookie(logInForm["name"], false);
user.setUser(WebSecurity.CurrentUserName);
return RedirectToAction("Index", "Home");
}
}
return View("LogOn");
}
This exception only occur if there are more than one records.
Try to run the query in Sql Server management studio or whatever you have or try to debug the code and see what is value of userName.
e.g
SELECT * FROM AzaraUser WHERE ProgramUserName = 'ABC' OR UserName = 'ABC'
or try:
public List<AzaraUser> setUser(String userName)
{
AzaraUser = DatabaseConnection.DataContext.GetTable<AzaraUser>().WHERE(a => a.ProgramUserName == userName || a.UserName == userName).ToList<AzaraUser>();
}
The error is pretty explicit. Try changing SingleOrDefault to a Where and add ToList to the end, then place a breakpoint on the next line so you can see the actual rows being returned.
AzaraUser = DatabaseConnection.DataContext.GetTable<AzaraUser>()
.Where(a => a.ProgramUserName == userName || a.UserName == userName)
.ToList();
Also, make doubly sure you're connecting to your test database and not some other database where records are duplicated.
I have an issue, where by each user in my user list is showing as on-line when I know they're not.
When the page is loaded, they show as offline, but if I refresh the page, they all show as on-line. I'm assuming this is because I'm programmatically accessing their profile information (CommonProfile) to get the data to show on the gridview?
Is there any way to get the profile information without triggering the IsOnline property to be true?
Update:
Sorry, code is here. Please be gentle, I'm relatively new to c# & asp.net and I'm still learning.
The code is collecting information from Membership user and the common profiles and adding the fields to a datatable so that i can display the results in a gridview.
MembershipUserCollection usersList = Membership.GetAllUsers();
MembershipUserCollection filteredUsers = new MembershipUserCollection();
foreach (MembershipUser user in usersList)
{
if (!Roles.IsUserInRole(user.UserName, "Admin") && !Roles.IsUserInRole(user.UserName, "Engineering"))
{
if (txtFilterCustomerNo.Text.Length > 0)
{
ProfileCommon PC = Profile.GetProfile(user.UserName);
if (PC.CompanyAccountNo == txtFilterCustomerNo.Text.ToUpper())
{
filteredUsers.Add(user);
}
}
else
{
filteredUsers.Add(user);
}
}
}
txtFilterCustomerNo.Text = null;
foreach (MembershipUser user in filteredUsers)
{
userProfile = Profile.GetProfile(user.UserName);
string[] userRoles = Roles.GetRolesForUser(user.UserName);
DataRow orderLine = dataSet.Tables["UserAccounts"].NewRow();
orderLine["USER_NAME"] = user.UserName;
orderLine["CREATED"] = user.CreationDate;
orderLine["LAST_LOGIN"] = user.LastLoginDate;
orderLine["PASSWORD_CHANGED"] = user.LastLoginDate;
orderLine["ACTIVE"] = user.IsApproved;
orderLine["ONLINE"] = user.IsOnline;
orderLine["LOCKED"] = user.IsLockedOut;
orderLine["CUSTOMER_NO"] = userProfile.CompanyAccountNo;
orderLine["HAS_INVENTORY"] = userProfile.HasOwnInventory;
orderLine["ORDER"] = userRoles.Contains("Order");
orderLine["REPAIR"] = userRoles.Contains("Repair");
orderLine["WARRANTY"] = userRoles.Contains("Warranty");
orderLine["COMMISSIONING"] = userRoles.Contains("Commissioning");
orderLine["ACCOUNT"] = userRoles.Contains("Account");
dataSet.Tables["UserAccounts"].Rows.Add(orderLine);
}
if (dataSet.Tables.Contains("UserAccounts"))
{
GridView1.DataSource = dataSet.Tables["UserAccounts"];
}
If you simply looked at the different overloads of GetUser, you would see that some of them take a Boolean called userIsOnline. If you specify this as false, it will not update the last online timestamp, and will not list them as online.
var user = Membership.GetUser(userid, false);
EDIT:
I see you are using GetAllUsers() rather than GetUser(). There are some problems with GetAllUsers() and you cannot rely on the IsOnline property. Instead, you need to check the LastActivityDate field and figure out the difference between that and the current DateTime. If the amount of time is greater than what you consider "Online" to be, then they are offline, otherwise online.