I've been working on a project to move all of our applications to use external .config files to store connection strings so they are no longer kept in source control. As part of this, we are now encrypting these connection strings on deployment.
web.config
<connectionStrings configSource="ConnectionStrings.config"/>
ConnectionStrings.config
<connectionStrings>
<add name="MyDatabase" connectionString="MyConnectionString" providerName="System.Data.SqlClient">
</connectionStrings>
This is an application that I had to update from .NetFramework 4.0 to .NetFramwork 4.7.2 due to restrictions on our build server.
To encrypt the connection strings I have been running the following command (on the web server) for all of our applications thus far with no issue. Several of these were framework upgrades as well. Note: we give each of our web apps their own app pool.
"C:\Windows\Microsoft.NET\Framework\v4.0.30319\aspnet_regiis.exe" -pe "connectionStrings" -app "/MyApplication" -site "Default Web Site"
Every site so far has worked without issue in all of our environments. Now this most recent one, when encrypted, causes an infinite redirect loop with the same error each loop of
Failed to decrypt using provider 'RsaProtectedConfigurationProvider'. Error message from the provider: The RSA key container could not be opened.
If I go to the server and run the command line to decrypt, it succeeds and the app functions properly. I'm baffled and non of my coworkers have any idea either. I know it has to be something specific to this one application but I don't know where to begin. It is an old app that I didn't even work on and know nothing about. I've looked through numerous pages of similar RSA complaints but none of them seem to be this specific issue. And yes I am able to replicate this on multiple servers and even on my own machine.
I bought a Windows hosting from GoDaddy. I have configured the configuration settings(Adding database and publishing project's files to host)
I can access the database while running the project on the local server.
But when I transfer the project to the server, the project on the server can't do it.
I wrote my connection string to web.config file, here it is:
<add name="xyz" connectionString="Data Source=IP ADDRESS;Initial Catalog=DBNAME;User ID=USERNAME;Password=PASS;Integrated Security=False" providerName="System.Data.SqlClient" />
I used MVC and Entity Framework, I also used layered structure
Thank You.
try to check more details about the connection string that should be used with your database provider. Here you can find several examples about how to create your connection string properly in SQL SERVER.
please notice that if you are working in your host machine, you have not to specify the IP ADDRES of your SQL SERVER but the SERVER NAME just like:
Data Source=(SERVER_NAME) \ DB_INSTANCE_NAME
I hope that it's gonna be useful.
First, this is related to another question here on SO:
I've read and debugged my issue with the following SO article & blog:
MetadataException: Unable to load the specified metadata resource
and
http://blogs.teamb.com/craigstuntz/2010/08/13/38628/
BUT...I'm still having questions beyond just this 'fix'
I have a WebAPI (2.1), the connection string in my WebAPI is as so:
<connectionStrings>
<add name="ProjectEntities" connectionString="
metadata=res://*/ProjectModel.csdl|
res://*/ProjectModel.ssdl|
res://*/ProjectModel.msl;
provider=System.Data.SqlClient;
provider connection string="
data source=192.168.0.1;
initial catalog=Project;
persist security info=True;
user id=***;
password=***;
multipleactiveresultsets=True;
App=EntityFramework""
providerName="System.Data.EntityClient" />
When I call ToList() on a DbSet in my WebAPI (pseudo code):
DbContext _DbContext = new ProjectEntities();
DbSet<TEntity> _dbSet = _DbContext.Set<TEntity>();
_dbSet.ToList();
It works great!
When I call the same from within a WINDOWS SERVICE, I get the following error:
The app.config entry for the connection string is exactly the same as the web.config:
<connectionStrings>
<add name="ProjectEntities" connectionString="
metadata=res://*/ProjectModel.csdl|
res://*/ProjectModel.ssdl|
res://*/ProjectModel.msl;
provider=System.Data.SqlClient;
provider connection string="
data source=192.168.0.1;
initial catalog=Project;
persist security info=True;
user id=***;
password=***;
multipleactiveresultsets=True;
App=EntityFramework""
providerName="System.Data.EntityClient" />
Now, the blog shows to reference the dll manually as so:
<connectionStrings>
<add name="ProjectEntities" connectionString="
metadata=res://Project.Data.dll/ProjectModel.csdl|
res://Project.Data.dll/ProjectModel.ssdl|
res://Project.Data.dll/ProjectModel.msl;
provider=System.Data.SqlClient;
provider connection string="
data source=192.168.0.1;
initial catalog=Project;
persist security info=True;
user id=***;
password=***;
multipleactiveresultsets=True;
App=EntityFramework""
providerName="System.Data.EntityClient" />
</connectionStrings>
This does NOT work/fix the issue
The only way I've been able to fix it, is to use the fully qualified name:
<connectionStrings>
<add name="ProjectEntities" connectionString="
metadata=res://Project.Data, Version=1.6.0.0, Culture=neutral, PublicKeyToken=null/ProjectModel.csdl|
res://Project.Data, Version=1.6.0.0, Culture=neutral, PublicKeyToken=null/ProjectModel.ssdl|
res://Project.Data, Version=1.6.0.0, Culture=neutral, PublicKeyToken=null/ProjectModel.msl;
provider=System.Data.SqlClient;
provider connection string="
data source=192.168.250.125\sqlexpress;
initial catalog=Project;
persist security info=True;
user id=***;
password=***;
multipleactiveresultsets=True;
App=EntityFramework""
providerName="System.Data.EntityClient" />
</connectionStrings>
Why does this work like this? Why would this work in a web project, but not a windows service project?? I recently changed from EF5 to EF6, and this error has popped up - all this code worked previous to upgrading EF. Does anyone have any insight as to why and how/if I can just use * for the dll name in my connection string?
I thought it was an issue of where the service .exe was running and a file wasn't copied locally, but nope, the Project.Data.dll is there and it's the right version.
I used FusionLog to try and find the error, and no luck there. I'm pretty confused.
Why this happens?
The issue you are having is just a result of extra security measures to prevent binary planting or DLL hi-jacking attack (read more) when running your application as as windows service.
Why should I care?
As you probably know, there is a specific, well documented order in what every referenced DLL file is looked up. Usually it starts to search DLL in current application directory and then goes away to more "public" locations like PATH folders, GAC, etc.
Main idea of binary planting is to plant malicious DLL file in a folder which is checked before folder of the legit DLL. Loading such malicious DLL would allow attacker to gain control over the system.
Usually windows services run under elevated account (LocalSystem, LocalService, NetworkService, etc) therefore windows services are good target for binary planting attacks.
What can I do?
Microsoft have taken extra precaution steps to reduce security risks and there is a good reason for that. But you can try to work around you issues.
1) Current directory is not what you expect
Windows service starts in system folder (usually something like C:\Windows\System32)
Good news are that it is very easy to fix. You just have to change current directory on services startup.
System.IO.Directory.SetCurrentDirectory(System.AppDomain.CurrentDomain.BaseDirectory);
See blog post from Phil Haack;
2) Read documentation thoroughtly
According to EF documentation, wildcard character has special meaning and it limits places where runtime will look for DLL files:
If you specify a wildcard (*) for assemblyFullName, the Entity
Framework runtime will search for resources in the following
locations, in this order:
1) The calling assembly.
2) The referenced assemblies.
3) The assemblies in the bin directory of an application.
As your working folder is set to system folder and you references probably are not there, EF might end up looking in wrong places and your assemblies containing resources might not be loaded.
3) Stay safe with fully qualified assembly names
Although I am not completely sure about this and haven't tested, but Microsoft just might have disallowed Windows services to load DLL without providing fully qualified assembly name to reduce risk of injecting malicious DLL files;
Good read on securing your Windows services here (specially chapter 5).
4) Debug it!
EF6 happens to be open source project. This means that you can get full source of it and debug it. You can find project on CodePlex here.
Copy the dll containing ProjectEntities to different path and then reference the same in your service project.
I'm afraid I wasn't able to reproduce the error that you received, or answer why you needed to change the metadata.
That said, I did learn that, for the EF connection string, the Windows Service required a different provider connection string than the WebApi did.
The following are the steps to reproduce your error. The only difference is that I'm using localdb not SQLExpress.
The resultant code from my steps-to-reproduce is online at GitHub here: https://github.com/bigfont/EntityFrameworkWindowsServiceWebApi.
Here are those steps:
Create Web API Project
Create ASP.NET Web API 2 Empty Project (MyWebApi)
With NuGet, Install-Package EntityFramework -ProjectName MyWebApi
Add a new ADO.NET Entity Data Model called MyProjectModel.
Add an Entity called Entity1.
Generate the database from the model, calling it MyProject and using localdb.
Run the db creation script on (localdb)\v11.0
Add a new WebApi Controller named ValuesController with a Get method that queries the database.
Test by running in Visual Studio and going to localhost:123456/api/get
See: https://msdn.microsoft.com/en-us/data/jj205424.aspx
Create Windows Service Project
Create Windows Service (MyWindowsService)
Use NuGet, Install-Package EntityFramework -ProjectName MyWindowsService
Add a new ADO.NET Entity Data Model called MyProjectModel.
Add an Entity called Entity1.
Generate the database from the model, calling it MyService, using localdb.
Run the db creation script on (localdb)\v11.0
Add to the OnStart method some code that queries the database.
Add NT AUTHORITY\SYSTEM as a localdb Login and as a MyService db User.
Test by installing, starting, and writing to file:
PowerShell Installation, Startup, and Uninstall
Release> installutil .\MyWindowsService.exe
Release> Start-Service MyService
Release> installutil .\MyWindowsService.exe /u
localdb connection string in the Windows Service
In the connection string for the Windows Service, I wasn't able to use (localdb)\v11.0. Instead, I needed to use the named pipe. I found the named pipe with this command line:
> SqlLocalDB.exe info v11.0
Name: v11.0
Version: 11.0.2100.60
Shared name:
Owner: MY_COMPUTER\Shaun.Luttin
Auto-create: Yes
State: Running
Last start time: 2015-04-09 5:54:34 PM
Instance pipe name: np:\\.\pipe\LOCALDB#1010101\tsql\query
The resultant connection string, using the Instance pipe name, looked like this.
<connectionStrings>
<add name="MyProjectModelContainer"
connectionString="
metadata=
res://*/MyProjectModel.csdl|
res://*/MyProjectModel.ssdl|
res://*/MyProjectModel.msl;
provider=System.Data.SqlClient;
provider connection string="
data source=np:\\.\pipe\LOCALDB#4BCE6D95\tsql\query;
initial catalog=MyService;
Integrated Security=True;
MultipleActiveResultSets=True;
App=EntityFramework""
providerName="System.Data.EntityClient" />
</connectionStrings>
Whereas the WebApi connection string looked like this:
<add name="MyProjectModelContainer"
connectionString="
metadata=
res://*/MyProjectModel.csdl|
res://*/MyProjectModel.ssdl|
res://*/MyProjectModel.msl;
provider=System.Data.SqlClient;
provider connection string="
data source=(localdb)\v11.0;
initial catalog=MyProject;
integrated security=True;
MultipleActiveResultSets=True;
App=EntityFramework""
providerName="System.Data.EntityClient" />
</connectionStrings>
See also: http://www.connectionstrings.com/sql-server-2012/
Needing to use a different connection string with a Windows Service that we do with a WebApi project is a similar problem to what you found. From Sql Server Management Studio, from Visual Studio, and from the WebApi, we can connect by calling the data source (localdb)\v.11 whereas from a Web Service we need to call it by it's instance named pipe.
Here's a suspicion: It might be that there are multiple instance of localdb on the computer, and that we needed to absolutely specify which one we want to use. Unfortunately, this doesn't help answer why you needed to change the metadata.
This is a similar though different problem than what you faced, because you needed to change the Entity Framework metadata whereas I needed to change the provider connection string. Coincidence?
Please follow the steps bellow:
1.Write click on edmx file and then click open with of the related entity.
2.Select xml editor and click open.
3.Scroll from top to bottom of the .edmx xml file and look for any error marks.
4.If you mind errors then fix that.
5.Rebuild the solution and if no errors found then congratulations :)
We have a wcf service that runs as an application in a separate application pool on our webserver in a subfolder. We upgraded to .NET 4.5 in Dec. and EF5 in January. We did our standard web deploy yesterday which does not touch this code, and the WCF service stopped working.
We can move the old code to a different production server and it works. When using the old code on the production site we get a code produced error that indicate connectivity issues to the database (Unable to LogIn).
We tried deploying the WCF with upgraded 4.5 and EF5, but get runtime errors: "The type initializer for 'System.Data.Entity.Internal.AppConfig' threw an exception." We have done all the config changes indicated, such as defaultConnectionFactory, for EF5. When doing so, the WCF starts giving a 301 redirection to the service endpoint when calling any service method. We are stumped as why a normal web deploy would cause these issues, and why we can't deploy upgraded EF versions to get us out of this hole.
This is a live and very active service used by our business partners.
Resolved. Event log says nothing. It looked to be a binding issue between IIS and the interface. Turned out to be conflicting web.config's keeping the IIS from loading the web.config fully/causing duplicate entries. The only config item that caused the break was an EntityFramework connect string. We run EF5.0 on .NET 4.5. Here is the offending connection string:
String in root Web.Config:
<add name="MyConfigurationEntities" connectionString="metadata=res://*/MyConfigurationModel.csdl|res://*/MyConfigurationModel.ssdl|res://*/MyConfigurationModel.msl;provider=System.Data.SqlClient;provider connection string="Data Source=SERVER1;Initial Catalog=MyConfiguration;User ID=sa;Password=XXXX;MultipleActiveResultSets=True"" providerName="System.Data.EntityClient" />
String in web service Web.Config:
<add name="MyConfigurationEntities" connectionString="metadata=res://*/MyConfigurationModel.csdl|res://*/MyConfigurationModel.ssdl|res://*/MyConfigurationModel.msl;provider=System.Data.SqlClient;provider connection string="Data Source=Server1;Initial Catalog=MyConfiguration;User ID=sa;Password=XXXX;MultipleActiveResultSets=True"" providerName="System.Data.EntityClient" />
Our folder structure is:
/web.config
/webservices/webservice/web.config
I have a WCF web service website, Web service library, and a and I have a Domain project which uses Fluent nHibernate.
When I run the WCF project and run a invoke a web service it works fine, as long it's not a service that accesses the database.
If I invoke a web service that accesses the DB, I always get an error here:
_sessionFactory = Fluently.Configure()
.Database(MsSqlConfiguration.MsSql2008.ConnectionString(#"Server=MYSERVER;database=MYDATABASE;Trusted_Connection=true;")
.ShowSql()
)
.Mappings(m => m.FluentMappings
.AddFromAssemblyOf<WhygoDomain.Location>())
.ExposeConfiguration(cfg => new SchemaExport(cfg)
/* .Create(true, true)*/)
.BuildSessionFactory();
Which says:
An invalid or incomplete configuration was used while creating a SessionFactory. Check PotentialReasons collection, and InnerException for more detail.
Inner Exception says:
A network-related or instance-specific error occurred while establishing a connection to SQL Server. The server was not found or was not accessible. Verify that the instance name is correct and that SQL Server is configured to allow remote connections. (provider: TCP Provider, error: 0 - No connection could be made because the target machine actively refused it.)
I do not get this message if I do the following:
1) Right click on the webservice.svc and copy the "view in browser" link.
2) (in the WCF test client) right click on "my service projects"-> "add service" and paste in the URL from 1) above
I have been working like this for a while, but it's a bit slower and it means I can't debug, which isn't really acceptable.
What's happening here?
It seems like a permission problem connecting to the database, but I'm new to most of this so it may be something else.
I have tried giving permission to any user I can think of to the database, but no change. What user does the WCF test client use, does anyone know?
The result of this issue is that I can't debug my web service which is a problem for me. I guess I could try attach to process or something, but this wouldn't be ideal as I have plenty of web service work on the horizon.
check that your service in running in IIS with full trust. OLEDB or ODBC works only in full trust under IIS even though, if you can modify the file web_mediumtrust.config in C:\Windows\Microsoft.NET\Framework\v4.0.30319\Config, you can add in the SecurityClasses section:
<SecurityClass Name="OleDbPermission" Description="System.Data.OleDb.OleDbPermission, System.Data, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"/>
<SecurityClass Name="OdbcPermission" Description="System.Data.OleDb.OdbcPermission, System.Data, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"/>
Is the connection string set to windows authentication? If so set it to SQL Server Authentication and see if it still works testing it locally. Also check that the database is setup to use both Windows Authentication and SQL Server Authentication.