I am using the following connection string within the <configuration> node. But somehow, it seems that it is not saving. Every time I use
System.Configuration.ConfigurationManager.ConnectionStrings["myDB"].ConnectionString
it has a null value, and when I check the index "0" it points to .\SQLEXPRESS.
<connectionStrings>
<clear/>
<add name="myDB"
providerName="System.Data.SqlClient"
connectionString="Server=Server\Instance;Database=anydb;User Id=***; Password=***;" />
</connectionStrings>
The projects is an ASP.NET MVC 2 project.
I really need this to work, since I am learning the code-first Entity Framework. Is there any suggestions?
Things to trouble-shoot on this :
Ensure that EF is configured to use your connection string. You can do this in you DbContext class by passing the connection string name into the base constructor :
public class YourContext : DbContext
{
public YourContext()
: base("myDB")
{
}
}
Ensure that the connection string is the correct web.config (ie in the main root not in Views)
Check that the connection string is not being overridden in the web.debug.config (or web.release.config) if it is being
Related
I am developing a WPF application that uses Entity Framework v.6 with the approach Code First to build and manage a local database which is created on the client computer itself.
When I install the application on a client computer and launch it, I receive the following error when the context tries to create the database:
Expansion of |DataDirectory| failed while processing the connection string. Ensure that |DataDirectory| is set to a valid fully-qualified path.
In app.config I have set the following configuration of Entity Framework:
<entityFramework>
<defaultConnectionFactory type="System.Data.Entity.Infrastructure.LocalDbConnectionFactory, EntityFramework">
<parameters>
<parameter value="mssqllocaldb"/>
</parameters>
</defaultConnectionFactory>
<providers>
<provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer"/>
</providers>
</entityFramework>
My context class contains the following code:
class EntityContext : DbContext
{
public DbSet<Car> Cars { get; set; }
public DbSet<Trip> Trips { get; set; }
public DbSet<Volunteer> Volunteers { get; set; }
public DbSet<Motivation> Motivations { get; set; }
public DbSet<PaymentType> PaymentTypes { get; set; }
public EntityContext() : base("StaccoDataBase")
{
System.Data.Entity.Database.SetInitializer(new CreateDatabaseIfNotExists<EntityContext>());
}
}
I have tried to fix the problem setting the |DataDirectory| in the App.xaml.cs as follows:
protected override void OnStartup(StartupEventArgs e)
{
base.OnStartup(e);
AppDomain currentDomain = AppDomain.CurrentDomain;
currentDomain.SetData("DataDirectory", Directories.DBDirectory);
}
But the issue still persists.
I would really appreciate if someone can help me.
Just a wild guess - what if you used this connection string:
Data Source=(LocalDb)\\MSSQLLocalDB; AttachDBFilename=|DataDirectory|StaccoDataBase.mdf; integrated security=SSPI
First of all, use the |DataDirectory| directly in your connection string (don't "inject" it via that string.Format() call), and secondly, add the .mdf extension to the database file you want to attach.
Also, I'd store this connection string in the app.config - don't create it at runtime, because the constructor call here:
public EntityContext() : base("StaccoDataBase")
will try to find StaccoDataBase as a connection string name in your config file.
So use this:
app.config:
<configuration>
.....
<connectionStrings>
<add name="StaccoDataBase"
connectionString="Data Source=(LocalDb)\\MSSQLLocalDB;AttachDBFilename=|DataDirectory|StaccoDataBase.mdf; integrated security=SSPI"
providerName="System.Data.SqlClient" />
<connectionStrings>
.....
</configuration>
Let say the Active Directory have Group A, B and C.
How to specified like only Group A sync to Sitecore?
Thanks for any help! :)
If you just want to get the members in a specific group, you can do this using a customFilter.
If for membership, you can add the following under your membership element in the web.config:
<add name="ad"
type="LightLDAP.SitecoreADMembershipProvider"
connectionStringName="ManagersConnString"
applicationName="sitecore"
minRequiredPasswordLength="1"
minRequiredNonalphanumericCharacters="0"
requiresQuestionAndAnswer="false"
requiresUniqueEmail="false"
connectionUsername="user"
connectionPassword="12345"
attributeMapUsername="sAMAccountName"
enableSearchMethods="true"
customFilter="(memberOf=cn=test role 1,OU=CRM,DC=VM)"
/>
Just ensure that you have a connection string configured for your AD, which would be something like: <add name="ManagersConnString" connectionString="LDAP://testsrv/OU=Managers,DC=testdomain,DC=sitecore,DC=net" />
And ensure that your custom filter gets to the specific group you're trying to allow access for. I used LDAP Browser to navigate to my groups using a simple GUI and then copied the path.
See more in the documentation about customFilters in section 4.1.
Try to specify your group in the connection string:
<connectionStrings>
<add name="ManagersConnString"
connectionString="LDAP://testsrv/OU=Managers,DC=testdomain,DC=sitecore,DC=net" />
</connectionStrings>
This example is copied from the Documentation (see chapter 2.1.3). In this example, Managers is just a sample organization unit. But this is a normal LDAP connection string, so you can insert and filter there whatever you want.
So I have been using Entity Framework for some time (on v5 for my main project). One question I have always had, but could never find a definitive answer to - does the name of my connection string have to match the name of my DbContext in order for EF to work correctly?
It appears so (and I have never done anything differently), but I would prefer not to have to provide a "magic string" in my Web.config in order for EF to work. It would be better, in my opinion, to keep DefaultConnection as the name and EF connects up some other way.
Here is the references from my Web.config (some names changed):
<connectionStrings>
<add name="MyContext" connectionString="Data Source=|DataDirectory|MyDatabase.sdf" providerName="System.Data.SqlServerCe.4.0" />
</connectionStrings>
...and...farther down...
<entityFramework>
<contexts>
<context type="MyProject.Path.To.MyContext, MyProject.Path.To, Version=1.0.0.0, Culture=neutral">
<databaseInitializer type="MyProject.Path.To.MyInitializer, MyProject" />
</context>
</contexts>
<defaultConnectionFactory type="System.Data.Entity.Infrastructure.LocalDbConnectionFactory, EntityFramework">
<parameters>
<parameter value="v11.0" />
</parameters>
</defaultConnectionFactory>
</entityFramework>
Any insight would be appreciated.
One question I have always had, but could never find a definitive
answer to - does the name of my connection string have to match the
name of my DbContext in order for EF to work correctly?
No. You can pass a connection string name into the base constructor for DbContext, i.e.
public class MyDbContext : DbContext
{
public MyDbContext()
: base("MyConnectionStringName")
{
}
}
There's also a constructor on DbContext that takes a DbConnection argument if you prefer to create the connection yourself.
Finally, you can provide your own implementation of IDbConnectionFactory and use it instead of the default LocalDbConnectionFactory one specified in the app.config. You change it in the config or you set it at runtime as follows:
Database.DefaultConnectionFactory = new MyCustomConnectionFactory();
So I have basic MVC 4 Internet application project with Entity Framework 5.
I have configured WebSecurity that uses my table for users.
WebSecurity.InitializeDatabaseConnection("DefaultConnection", "Users", "Id", "Email", autoCreateTables: true);
Then in my migration configuration class I seed DB with new roles and add users to them.
internal sealed class Configuration : DbMigrationsConfiguration<Infrastructure.KlepecV2Db>
{
public Configuration()
{
AutomaticMigrationsEnabled = true;
}
protected override void Seed(Infrastructure.KlepecV2Db context)
{
if(!Roles.RoleExists("Admin"))
{
Roles.CreateRole("Admin");
}
if (!Roles.RoleExists("Test1"))
{
Roles.CreateRole("Test1");
}
if(Membership.GetUser("user1") != null)
{
if(!Roles.IsUserInRole("user1","Admin"))
{
Roles.AddUserToRole("user1", "Admin");
}
}
if (Membership.GetUser("user2") != null)
{
if (!Roles.IsUserInRole("user2", "Admin"))
{
Roles.AddUserToRole("user2", "Admin");
}
}
}
}
So when I type "update-database" in NuGet console everything gets executed without errors. But if I look into webpages_Roles table its empty. Also webpages_UsersInRoles is empty.
For testing I have removed Role.RoleExists() calls and updating database fails, becouse roles already exists.
What am I missing here? Where are this roles stored?
I came across into an error The Role Manager feature has not been enabled mentioned by #Magnus. Hope this probably related to your roles issue in which the default role provider is unknown.
The error The Role Manager feature has not been enabled happened when I move the WebSecurity.InitializeDatabaseConnection method from MVC project into a class library (data access) for code first migration seed.
The point is App.config need to be configured for Package Manager Update-Database command to be run just like when Web.config exist.
Below is my App.config and Seed. Note that
I add "DefaultConnection" connection string *
Add system.web->roleManager to set the enable="true"
Add runtime->assemblyBinding->qualifyAssembly to give hint to compiler where is WebMatrix.WebData by giving the full assembly name.
App.config:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<configSections>
<!-- For more information on Entity Framework configuration, visit http://go.microsoft.com/fwlink/?LinkID=237468 -->
<section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=4.4.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
</configSections>
<connectionStrings>
<!--<add name="DefaultConnection" connectionString="Data Source=.\SQLEXPRESS;Initial Catalog=Db;Persist Security Info=True;User=user;Password=pass" providerName="System.Data.SqlClient" />-->
</connectionStrings>
<system.web>
<roleManager enabled="true" defaultProvider="simple">
<providers>
<clear />
<add name="simple" type="WebMatrix.WebData.SimpleRoleProvider, WebMatrix.WebData" />
</providers>
</roleManager>
<membership defaultProvider="simple">
<providers>
<clear />
<add name="simple" type="WebMatrix.WebData.SimpleMembershipProvider, WebMatrix.WebData" />
</providers>
</membership>
</system.web>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<qualifyAssembly partialName="WebMatrix.WebData" fullName="WebMatrix.WebData, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
</assemblyBinding>
</runtime>
<entityFramework>
<defaultConnectionFactory type="System.Data.Entity.Infrastructure.SqlConnectionFactory, EntityFramework" />
</entityFramework>
</configuration>
Seed Method:
protected override void Seed(DatabaseContext context)
{
WebSecurity.InitializeDatabaseConnection("DefaultConnection", "Users", "Id", "Email", autoCreateTables: true);
if(!Roles.RoleExists("Admin"))
{
Roles.CreateRole("Admin");
}
if (!Roles.RoleExists("Test1"))
{
Roles.CreateRole("Test1");
}
if(Membership.GetUser("user1") != null)
{
if(!Roles.IsUserInRole("user1","Admin"))
{
Roles.AddUserToRole("user1", "Admin");
}
}
if (Membership.GetUser("user2") != null)
{
if (!Roles.IsUserInRole("user2", "Admin"))
{
Roles.AddUserToRole("user2", "Admin");
}
}
}
Hope this will help anyone with The Role Manager feature has not been enabled issue when using code first migration seed in a class library.
Update
* EF5 will read the connection string in Web.config of Mvc project but not in the App.config of the project with EF Migrations. However the membership and roleManager settings is still required in the EF Migration project.
Wanted to add my $0.02 to the conversation. I have a similar setup to CallMeLaNN, but was still getting the error. My solution was to set my "Data" project to a StartUp project. After that, my app.config file started getting picked up, and I can now seed my users from the Update-Database command.
I have a task of dealing with security on my .Net web application, the way it is to work is that if the user is logged in to Active Directory and the users AD name is in a database then they will be let in.
On the same bases if the users AD name is not in the database then they will be asked to login, with a user name and password, held in the database.
So I need some kind of mix mode security login using the Membership and Role provider.
Where I am having trouble is where do you detect if a user can login using AD, so they get logged in automatically.
Sounds like you'll need to implement a custom MembershipProvider that inherits from ActiveDirectoryMembershipProvider.
At a minimum, you'll need to override ValidateUser so that if the base.ValidateUser returns false, you can attempt to validate the user in your SQL database. The following code sample works in my test application, however I did not implement the SQL method. That should be pretty straight forward for you.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web.Security;
using System.Configuration;
using System.Configuration.Provider;
namespace Research.Web.Security
{
public class MixedMembershipProvider : ActiveDirectoryMembershipProvider
{
protected String SqlConnectionString { get; private set; }
private String GetConnectionString(String connectionStringName)
{
if (string.IsNullOrEmpty(connectionStringName))
throw new ProviderException("ConnectionStringName must be specified.");
ConnectionStringSettings settings = ConfigurationManager.ConnectionStrings[connectionStringName];
if (settings == null)
{
throw new ProviderException(String.Format("Connection string {0} not found.", connectionStringName));
}
return settings.ConnectionString;
}
public override void Initialize(String name, System.Collections.Specialized.NameValueCollection config)
{
this.SqlConnectionString = GetConnectionString(config["sqlConnectionStringName"]);
config.Remove("sqlConnectionStringName");
base.Initialize(name, config);
}
public override Boolean ValidateUser(String username, String password)
{
if (!base.ValidateUser(username, password)) // validate using AD first
{
return ValidateUserSql(username, password); // if not in AD, check SQL
}
else
{
return true;
}
}
private Boolean ValidateUserSql(String username, String password)
{
// look up your account in SQL here
return true;
}
}
}
Your web config would look something like this:
<configuration>
<!-- usual config stuff omitted -->
<connectionStrings>
<add name="SqlDefault" connectionString="Server=localhost;database=mydatabase;Integrated Security=SSPI;" providerName="System.Data.SqlClient" />
<add name="ActiveDirectoryDefault" connectionString="LDAP://mydomain.com/DC=mydomain,DC=com" />
</connectionStrings>
<system.web>
<!-- usual config stuff omitted -->
<membership defaultProvider="Mixed">
<providers>
<clear/>
<add name="Mixed"
type="Research.Web.Security.MixedMembershipProvider, Research.Web"
applicationName="/"
connectionStringName="ActiveDirectoryDefault"
sqlConnectionStringName="SqlDefault"
connectionUsername="mydomain\myadmin"
connectionPassword="mypass"/>
</providers>
</membership>
<!--- usual config stuff omitted -->
</system.web>
</configuration>
The above code will work for basic authentication, but you may need to override some of the other methods to handle password resets, lookups, etc. for the eventuality that an account is in SQL and not AD.