I am creating an mvc application in vb.net in which I am trying to map certain fields to certain users so that it is specific to individual users. I have four SQL tables connected that are involved in the mapping. They are UserTable, ClientTable, ProjectTypeTable and IssueTable.
What I am trying to do is this: A user with the ID of one will log on, I get this ID and match it with the userID in the ClientTable to get the correct user for that client. Once I get that I will get the ClientID and match it with the ProjectTypeTable to get the multiple correct projectTypes, eg a client can have 1-8 projects available to them. The IssueTable will have the selected projectType.
I have created a ViewModel which looks like this:
Public Class ClientViewModel
Public proTable As List(Of ProjectType)
Public cTable As ClientTable
Public uTable As UserTable
Public iTable As IssueTable
End Class
What I planned to do is retrieve the userID when the user logs on and pass it to other views in session state so that the correct userID is kept through out the project until they log out. Here is what I have tried:
Dim uTable As SQLDatabase = New SQLDatabase()
Dim getUserID = (From data In uTable.UserTables Where data.username = user.username AndAlso data.userPassword = user.userPassword Select data.userID)
If (getUserID .Count() > 0) Then
Session("userIDData") = getUserID.ToString()
Then in the submit controller I have this:
Dim getuserID = Session("userIDData")
Dim userModel = New IssueTracker.ClientViewModel()
userModel.cTable = dbServer.ClientTables.Where(Function(x) x.userID = "")
'the speech marks will be the userID retrieved from the session state
userModel.proTable = dbServer.ProjectTypes.Where(Function(x) x.client = "").ToList()
'the speech marks will be the clientID retrieved from the session state
The problem I am having is that I am not actually getting the ID, is this a good way to map the users to specific fields? The ID's do not have to be sent across via session state that was the last thing I tried. How can I do this correctly?
Related
using (PrincipalContext Context = new PrincipalContext(ContextType.Domain, DomainURL, UserName, Password))
{
UserPrincipal Account = new UserPrincipal(Context);
Account.GivenName = strFirstName;
Account.Surname = strLastName;
PrincipalSearcher srch = new PrincipalSearcher(Account);
foreach (var principal in srch.FindAll())
{
var p = (UserPrincipal)principal;
String FirstName = p.GivenName;
String LastName = p.Surname;
}
}
If i use the code above to query Active Directory and the UserName(account) passed in the PrincipalContext constructor is in a domain that has no trust with the target domain(domain to be queried), i get the below error.
System.DirectoryServices.AccountManagement.PrincipalServerDownException: The server could not be contacted. ---> System.DirectoryServices.Protocols.LdapException: The LDAP server is unavailable.
Would i be correct to assume that if the PrincipalContext construct was changed to,
using (PrincipalContext ctx = new PrincipalContext(ContextType.Machine))
the code would execute successfully as long as the client is in the target domain?
Lets assume the first code with UserName and Password was called by a client in domain A trying to search for user info in domain B, here establishing context failed because the account used is in domain A that has no trust with domain B.
am i correct to assume that if i change the ContextType to Machine, and the client calling the code is in domain B, the code would execute succefully?
No, that would not be a correct assumption. ContextType.Machine means that you want to work with local accounts.
Your PrincipalSearcher will end up searching the local SAM database rather than Active Directory
I am using Castle ActiveRecord in my Asp.net / MVC 2 / Multi-tenancy application with SQL Server as my backend.
For every user logging in, the app loads the corresponding DB, dynamically at run time like below:
IDictionary<string, string> properties = new Dictionary<string, string>();
properties.Add("connection.driver_class", "NHibernate.Driver.SqlClientDriver");
properties.Add("dialect", "NHibernate.Dialect.MsSql2005Dialect");
properties.Add("connection.provider", "NHibernate.Connection.DriverConnectionProvider");
properties.Add("proxyfactory.factory_class", "NHibernate.ByteCode.Castle.ProxyFactoryFactory, NHibernate.ByteCode.Castle");
properties.Add("connection.connection_string", strDBConnection);
InPlaceConfigurationSource source = new InPlaceConfigurationSource();
source.Add(typeof(ActiveRecordBase), properties);
ActiveRecordStarter.Initialize(new System.Reflection.Assembly[] { asm1 }, source);
The strDBConnection string comes from another small database that holds the user info, corresponding DB, etc.
Scenario:
When a user logs in, his DB gets loaded, he can do his CRUD jobs -- No Probs !
Another user logs in (from another remote machine) his DB gets loaded -- No Probs !
Now, when the first user reads from DB, he sees new data from the second user's DB
My little understanding for this behavious is : ActiveRecordStarter is a Static object.
Could someone help me with a solution for this situation ?
The expected behaviour:
each user should access his own DB only, securely, in parallel / at the same time.
Thanks a lot !
ActiveRecordStarter.Initialize should only be called once in your app (in Application_Start in Global.asax).
To achieve what you want, create a class that inherits from NHibernate.Connection.DriverConnectionProvider:
public class MyCustomConnectionProvider : DriverConnectionProvider
{
protected override string GetNamedConnectionString(IDictionary<string, string> settings)
{
return string.Empty;
}
public override IDbConnection GetConnection()
{
// Get your connection here, based on the request
// You can use HttpContext.Current to get information about the current request
var conn = Driver.CreateConnection();
conn.ConnectionString = ... // Retrieve the connection string here;
conn.Open();
return conn;
}
}
Then set the connection.provider property to the name of your class:
properties.Add("connection.provider", "MyCompany.Domain.MyCustomConnectionProvider, MyCompany.AssemblyName");
I'm working with Entity Framework and the structure for my DB is something like this:
An user have a collections of subscribers, so...
Subscriber:
Name
UserId
User (to navigate on user object)
if I get the subscriber without the user, I modify the "name" and commit the changes and all works fine, but if I get the subscriber with the user instanciated, in the CommitAndRefreshChanges, throws me:
Cannot insert duplicate key row in object 'dbo.User' with unique index 'PK_Email'.\r\nThe statement has been terminated
but I don't change anything for user... what I'm doing wrong?
To get the subscriber I run on the repository:
RegistrationModuleDataModelContainer context = UnitOfWork as RegistrationModuleDataModelContainer;
Subscriber subscriber = (from s in context.Subscribers.Include(it=>it.User)
where s.IdSubscriber == idSubscriber
select s).FirstOrDefault();
To modify the data use the next code:
Subscriber subscriber = this.GetSubscriberWithUser(idSubscriber);
subscriber.FirstName = FirstName;
subscriber.LastName = LastName;
//Condition with subscriber.User.x
subscriber.Email = Email;
_subscriberRepository.Modify(subscriber);
IUnitOfWork unitOfWork = _subscriberRepository.UnitOfWork;
unitOfWork.CommitAndRefreshChanges();
If I erase the condition, fails anyway, the problem is when I load the subscriber with the user, if I load the subscriber only, the commit works.
Thanks!
Is there a way to search profiles in MOSS from the object model? I need to search for profiles that have a certain value set on their profile and then perform some action for them.
I need to write some c# code that can search the profiles database and return the matching profiles. Basically,
List of Profiles = Select Profiles From Profile Store Where Profile Property Value = SomeValue
I'm trying to avoid the following:
private IEnumerable<UserProfile> SearchProfiles(string value) {
ServerContext serverContext = ServerContext.GetContext(SPContext.Current.Site);
UserProfileManager profileManager = new UserProfileManager(serverContext);
foreach (UserProfile profile in profileManager) {
if ((string)profile["MyProp"].Value == value) {
yield return profile;
}
}
}
This is possible using the FullTextSqlQuery class:
FullTextSqlQuery q = new FullTextSqlQuery(ServerContext.Current);
q.ResultTypes = ResultType.RelevantResults;
q.QueryText = "SELECT UserName, Email, PreferredName FROM SCOPE() WHERE \"scope\" = 'People' AND Department = 'IT'";
ResultTableCollection tables = q.Execute();
ResultTable results = tables[ResultType.RelevantResults];
This class allows you to query a specific scope (i.e. people) and filter them based on properties using the WHERE clause, which looks basically the same as a regular Sql Query.
To be able to search and filter on (custom) user profile properties, the profile property needs to have a mapping in the Shared Service Provider's metadata settings. Most out of the box user profile properties already have these, custom properties you have to add yourself.
More info on managed properties here.
Two things:
when running with elevated privileges we need to create a new SPSite object within the call and load the security context from there. DO NOT use the context obtained using SPContext.Current.Site.
Hence:
SPSecurity.RunWithElevatedPrivileges(delegate()
{
using (SPSite site = new SPSite("<your site url>"))
{
ServerContext context = ServerContext.GetContext(site);
UserProfileManager profileManager = new
UserProfileManager(context);
foreach (UserProfile profile in profileManager)
{
// your code
}
}
}
make sure that the app pool account has appropriate user permissions in SSP. i.e. (use personal features, manage user profiles)
I'm building ASP.Net MVC aplication based on UnitOfWorkApplication and I'd like to use Castle ATM facility. At the moment I've problem with flushing the session on request end. My service class (which is called in my controller action method) looks like this:
[Transactional]
public class UserAdminService : IUserAdminService
{
[Transaction(TransactionMode.Requires)]
public User CreateNewUser(string username, string password, string firstName, string lastName)
{
var u = new User(username)
{
PasswordHash = GetPasswordHash(password),
FirstName = firstName,
LastName = lastName
};
userRepo.Save(u);
//UnitOfWork.CurrentSession.Flush();
return u;
}
When I uncomment the "UnitOfWork.CurrentSession.Flush();" row everything works fine - new user is persisted in DB. But nothing is persisted if I don't flush the session explicitely.
The UnitOfWorkApplication + ATM should flush changes on request end AFAIK - is that right? Does anybody have an advice what should I try to make it work without the explicit session.Flush() call?
I just registered RhinoTransactionFacility instead of original Castle ATM facility + DefaultTransactionManager and everything started to work.