Can't access SQL Server via IIS - sql-server

I want to run my ASP.NET MVC application on the local IIS 8 server but I can't get access to SQL Server 2014. Both IIS and SQL Server run on the same host and I am using Windows 8. This is what I have done so far:
In the application I created a model called Employee:
public class Employee
{
public int Id { get; set; }
public string Name { get; set; }
}
I want to connect to the database with using Entity Framework so I created another class called EmployeeDbContext:
public class EmployeeDbContext : DbContext
{
public DbSet<Employee> Employees { get; set; }
}
I have only one Home controller:
public string Index()
{
EmployeeDbContext employeeDbContext = new EmployeeDbContext();
return "Hello world";
}
I am using SQL Server 2014 Express engine with Windows Authentication and the name of my computer is ZSÓTÉ. Here is the connection string from the web.config:
<add name="EmployeeDbContext"
connectionString="Server=ZSÓTÉ\SQLEXPRESS;Initial Catalog=Test;Integrated Security=SSPI"
providerName="System.Data.SqlClient" />
In the Global.asax I didn't set any initializer strategy so by default if the Test database doesn't exist, then the application should create it automatically.
After that I set on the properties window to use IIS Local Server and I create a virtual directory for the application. So far everything is ok, I can see the application in the IIS manager and I set to run under the DefaultAppPool. After that I set all the permissions of the project folder for the IIS APPPOOL\DefaultAppPool object. The settings are fine I can access the application from the IIS server perfectly.
Finally I created a login for IIS APPPOOL\DefaultAppPool in SQL Server Management Studio and I set these two roles: public and dbcreator. But even after all these setups the application doesn't work correctly via IIS.
Though I get the "Hello world" message on the browser, but the Test database is never created. The strangest thing is if I make some malicious change in the connection string, I don't even get any compilation error, just the "Hello world" message in the browser.
What am I doing wrong? Thank you in advance!

The database is created the first time you access to entities.
Try to do this:
public string Index()
{
EmployeeDbContext employeeDbContext = new EmployeeDbContext();
employeeDbContext.Employees.ToList();
return "Hello world";
}
At this point you will receive an error if db creation does not work.
Next steps if something still does not work:
In the connection string use .\SQLEXPRESS because could happen everything to accents.
Assign to the user in SQL Server system administration role. If it work you then start to reduce rights (or, better, change approach).

Related

Specified username in connection string gets replaced at runtime

I have a web site project as an entry point and defined the connection string there:
"ConnectionStrings": {
"DataPlaygroundConnection": "Server=DataPlayhouse;Database=BusinessHandshake;User ID=bhuser1;Password=bh#12345;MultipleActiveResultSets=True;Connect Timeout=360;App=Company - Portal - Staging"
}
I started facing issues just recently that when running, I'd get Login failed for user 'bhuser1' error. But the credentials are working as I can connect to DB with any DB Manager (SSMS). Then I added Serilog to understand whats happening as the exception was thrown from Program.cs
After adding Serilog, I find this exception block:
10/20/2020 07:54:49 +04:00 Application Starting.
10/20/2020 07:54:49 +04:00 Using an in-memory repository. Keys will not be persisted to storage.
10/20/2020 07:54:49 +04:00 Neither user profile nor HKLM registry available. Using an ephemeral key repository. Protected data will be unavailable when application exits.
10/20/2020 07:54:49 +04:00 No XML encryptor configured. Key {a012bed6-42e0-475d-a11d-44ae3a5599a9} may be persisted to storage in unencrypted form.
10/20/2020 07:54:58 +04:00 An error occurred using the connection to database '"BusinessHandshake"' on server '"DataPlayhouse"'.
10/20/2020 07:54:58 +04:00 An exception occurred while iterating over the results of a query for context type '"Folio.Infrastructure.Data.Contexts.PlaygroundBiContext"'."
""Microsoft.Data.SqlClient.SqlException (0x80131904): Login failed for user 'bhuser1'.
The credentials in the json file are correct and I am able to use the same credentials in Azure Studio to connect to the database.
I do not have any customization code in context:
public partial class PlayHouseContext : DbContext
{
public PlayHouseContext()
{
}
public PlayHouseContext(DbContextOptions<PlayHouseContext> options)
: base(options)
{
}
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
if (!optionsBuilder.IsConfigured)
{
optionsBuilder.UseSqlServer("");
}
}
}
I have a similar error on my local dev machine: SqlException: Login failed for user 'bhuser1'.
On my dev machine, the credentials are correct and I can use SSMS to easily access the said DB and all the elements within.
I'm unable to understand this one.
Thanks #DaleK.
Trusted_Connection means windows authentication. I had to remove that and do the same in the appsettings.Development.json as well.

Bluemix connecting to external SQL Server Database

I have an application built using the ASP.NET 5 runtime - I would like to connect it to an on-premise SQL Server Database.
After some research I've already created the user-provided service with the relevant credentials, however I am unsure what to do next (i.e. writing the necessary code connecting it in ASP.NET).
Some further googling suggests to use Secure Gateway? but is this the only way? the cloud I am working on is dedicated and does not have the Secure Gateway service. Is there a workaround for this?
(Note: The application I'm working on is based on the ASP.NET-Cloudant example on IBM Github, if that helps).
https://github.com/IBM-Bluemix/asp.net5-cloudant
The Secure Gateway service isn't required as long as the Bluemix environment can connect to the server running SQL Server. This might require your firewall rules to be a little more relaxed on the SQL Server, or you can contact IBM to create a secure tunnel as Hobert suggested in his answer.
Aside from that issue, if you're planning to use Entity Framework to connect to your SQL Server, it should work similar to the existing tutorials on the asp.net site. The only difference will be in how you access the environment variables to create your connection string.
Assuming that you created your user-provided service with a command similar to this:
cf cups my-sql-server -p '{"server":"127.0.0.1","database":"MyDB","user":"sa","password":"my-password"}'
Your connection string in your Startup.cs file's ConfigureServices method would then look something like this:
string vcapServices = Environment.GetEnvironmentVariable("VCAP_SERVICES");
string connection = "";
if (vcapServices != null)
{
string myServiceName = "my-sql-server";
JArray userServices = (JArray)JObject.Parse(vcapServices)?["user-provided"];
dynamic creds = ((dynamic)userServices
.FirstOrDefault(m => ((dynamic)m).name == myServiceName))?.credentials;
connection = string.Format(#"Server={0};Database={1};User Id={2}; Password={3};",
creds.server, creds.database, creds.user, creds.password);
}
Update
The cloudant boilerplate that you're modifying doesn't use Entity Framework because cloudant is a NoSQL database, so it's a bit different than connecting to SQL Server. The reason that the boilerplate calls .Configure to register the creds class is that it needs to use that class from another location, but when using Entity Framework you simply need to use the credentials when adding EF to the services in the Startup.cs file so you don't need to use .Configure<creds>.
If you follow the guide here, the only part you'll need to change is the line var connection = #"Server=(localdb)\mssqllocaldb;Database=EFGetStarted.AspNet5.NewDb;Trusted_Connection=True;"; replacing it with the code above to create the connection string instead of hard-coding it like they did in the example tutorial.
Eventually, your ConfigureServices method should look something like this, assuming your DbContext class is named BloggingContext like in the example:
public void ConfigureServices(IServiceCollection services)
{
string vcapServices = Environment.GetEnvironmentVariable("VCAP_SERVICES");
string connection = "";
if (vcapServices != null)
{
string myServiceName = "my-sql-server";
JArray userServices = (JArray)JObject.Parse(vcapServices)?["user-provided"];
dynamic creds = ((dynamic)userServices
.FirstOrDefault(m => ((dynamic)m).name == myServiceName))?.credentials;
connection = string.Format(#"Server={0};Database={1};User Id={2}; Password={3};",
creds.server, creds.database, creds.user, creds.password);
}
services.AddEntityFramework()
.AddSqlServer()
.AddDbContext<BloggingContext>(options => options.UseSqlServer(connection));
services.AddMvc();
}
And then your Startup method would be simplified to:
public Startup(IHostingEnvironment env)
{
var configBuilder = new ConfigurationBuilder()
.AddJsonFile("config.json", optional: true);
Configuration = configBuilder.Build();
}
Excellent!
In Public Bluemix Regions, you would create and use the Secure Gateway Service to access the On-Premise MS SQL Server DB.
In your case, as a Bluemix Dedicated client, you should engage your IBM Bluemix Administration Team so they can work with your Network Team to create a tunnel between the Dedicated Bluemix Region and your On-Premise MS SQL DB Server.
If you want to connect directly from your Asp.Net Core application to a SQL Server you actually don't need a Secure Gateway.
For example, if you want to use a SQL Azure as your Database you can simply add the given connection string in your application.
But, for pratical and security reasons, you should create a User-Provided Service to store your credentials (and not use statically in your code), and pull your credentials from you VCAP_SERVICES simply adding SteelToe to your Cconfiguration Builder. (Instead of use parse the configuration manually with JObjects and JArrays)
Step-by-step:
In your CloudFoundry console create a User-Provided Service using a Json:
cf cups MySqlServerCredentials -p '{"server":"tcp:example.database.windows.net,1433", "database":"MyExampleDatabase", "user":"admin", "password":"password"}'
Obs.: If you use Windows console/Powershell you should escape you double quotes in Json like:
'{\"server\":\"myserver\",\"database\":\"mydatabase\",\"user\":\"admin\",\"password\":\"password\"}'
After you have created your User-Provided Service you should Connect this Service with your application in Bluemix Console.
Then, In your application add the reference to SteelToe CloudFoundry Steeltoe.Extensions.Configuration.CloudFoundry
In your Startup class add:
using Steeltoe.Extensions.Configuration;
...
var builder = new ConfigurationBuilder()
.SetBasePath(basePath)
.AddJsonFile("appsettings.json")
.AddCloudFoundry();
var config = builder.Build();
Finally, to access your configurations just use:
var mySqlName = config["vcap:services:user-provided:0:name"];
var database = config["vcap:services:user-provided:0:credentials:database"];
var server = config["vcap:services:user-provided:0:credentials:server"];
var password = config["vcap:services:user-provided:0:credentials:password"];
var user = config["vcap:services:user-provided:0:credentials:user"];
OBS.: If you're using Azure, remember to configure your Database firewall to accept the IP of your Bluemis application, but as default Bluemix don't give a static IP address you have some options:
Buy a Bluemix Statica service to you application (expensive)
Update firewall rules with REST put with the current IP of application (workaroud)
Open your Azure Database Firewall to a broad range of IPs. (Just DON'T)
More info about SteelToe CloudFoundry in :
https://github.com/SteeltoeOSS/Configuration/tree/master/src/Steeltoe.Extensions.Configuration.CloudFoundry

Code-first MVC 4 using Entity Framework and SQL Server 2012

This question is not about SQL Server "3xpr355" (the obfuscation
in quotes is by design; it should prevent future searches from hitting
dead-ends, as mine have done).
I am using code-first and Entity Framework to develop an MVC 4 application. The SQL Server, IIS, and Visual Studio are all running on the same machine.
I was originally using SQL Server "3xpr355" but the requirement to put it on an exposed-to-the-Internet-via-ISS machine made hooking it up to a full-featured SQL Server necessary. I have the application set up to drop and re-create the database whenever the models change:
public class XyzDBContext : DbContext
{
public XyzDBContext()
: base("XyzDBContext")
{
Database.SetInitializer<XyzDBContext>(new DropCreateDatabaseIfModelChanges<XyzDBContext>());
}
public DbSet<XyzModel> XyzModels{ get; set; }
}
Here are my connection strings:
<connectionStrings>
<add
name="DefaultConnection"
connectionString="Data Source=.;Initial Catalog=aspnet-Xyz-20150131102119;Integrated Security=SSPI"
providerName="System.Data.SqlClient" />
<add
name="XyzDBContext"
connectionString="Data Source=.;Initial Catalog=XyzDatabase;Integrated Security=True"
providerName="System.Data.SqlClient"/>
</connectionStrings>
Expectations:
Execution of the portions of the application that use XyzDBContext should cause the database "XyzDatabase" to be created (if necessary).
Execution of the portions of the application that use the Membership Provider should cause the database "aspnet-Xyz-20150131102119" to be created (if necessary).
Actual Results:
Exception is thrown: System.Data.ProviderIncompatibleException "An
error occurred while getting provider information from the database.
This can be caused by Entity Framework using an incorrect connection
string. Check the inner exceptions for details and ensure that the
connection string is correct."
Inner Exception:
System.Data.ProviderIncompatibleException "The provider did not
return a ProviderManifestToken string."
Inner Exception:
System.Data.SqlClient.SqlException "Login failed for user
'DOMAIN\SERVER$'."
Measures:
I have tried using SQL Server Management Studio to add a login for the "DOMAIN\SERVER$" user, but the login always fails.
I have researched and tried many permutations of the connection strings, all but a few of the examples I have found were for use with SQL Server "3xpr355".
Well if you map each connection string (database) to it's own DbContext the you could reach your expectations but you still have to work with two contexts (which is painful).
Your third actual result is due to IIS that can't connect to the database. You have to go to IIS manager and change the identity of the application pool under which your application runs (You can change it to LocalSystem)
Finally, try this if you have already the databases created:
public class DefaultConnectionContext : DbContext, IDisposable
{
public DefaultConnectionContext()
: base("name=DefaultConnection")
{
Database.SetInitializer<DefaultConnectionContext>(null);
}
// Some dbsets
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
}
}
public class XyzDBContext : DbContext, IDisposable
{
public XyzDBContext()
: base("name=XyzDBContext")
{
Database.SetInitializer<XyzDBContext>(null);
}
// Some dbsets
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
}
}
Hope That helps
The solution to this problem is multifaceted:
Create an Application Pool
In IIS Manager, visit the "Application Pools" node and select the "Add Application Pool..." Action:
Select the new Application Pool and select the "Advanced Settings..." Action, then select the "..." button (on the "Identity" field):
Set the Application Pool identity to "LocalSystem"
Grant Permission
In SQL Server Management Studio (when connected to the database service), visit the "NT AUTHORITY\SYSTEM" node under "Logins" and bring up the "Properties" view, then select the "Server Roles" page, and grant all of the privileges by selecting the check-boxes:
In IIS Manager, Right-click on your site and select "Manage Application/Advanced Settings..." and Set the "Application Pool" property value to "CodeFirstMVC".
Run the Application
Run the application and visit the areas that would require a new database to be created; you should now see a new database on your SQL Server instance.

ELMAH for ASP.NET MVC 4 using SQL SERVER 2008 R2

I ran ELMAH sql scripts in test DB(It created ELmah_Error table and 3 stored procedures) and configured ELMAH in MVC application using Nuget.
I modified web.config as specified and I'm able to log exceptions into
http://mysite/elmah.axd
But, instead i want to log the exceptions into Sql Server.
I added below class to achieve that
public class ElmahHandleErrorAttribute : System.Web.Mvc.HandleErrorAttribute
{
public override void OnException(System.Web.Mvc.ExceptionContext context)
{
LogException(e);
}
private static void LogException(Exception e)
{
// Call to Database and insert the exception info
}
}
Final step was to:
public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
filters.Add(new ElmahHandleErrorAttribute ());
}
Is it the correct way to use ELMAH to log all exceptions or AM I missing something?
Once you have the database setup, all you need to do is add the following to the <elmah> section your web.config to setup the Elmah to log to the SQL Database:
<elmah>
<errorLog type="Elmah.SqlErrorLog, Elmah" connectionStringName="<DBConnString>"
applicationName="<YourApp>"
</elmah>
Replace <DBConnString> and <YourApp> with appropriate values for your configuration.
Once you have done this you will not need to use your custom ElmahHandleErrorAttribute class.
I am not sure which NuGet package you installed, but I would recommend using the Elmah.MVC package as it integrates Elmah into MVC exceptionally well by setting up all of the ErrorHandlers and ErrorFilters for you.

asp mvc 3 noobie: CREATE DATABASE permission denied in database 'master'

I'm an asp mvc 3 noobie. I've done a few tutorials and am now ready to keep learning by trying to build a site.
In all the tutorials, you connect to a SQL CE or SQL Express DB. But I want my site to build a DB on sql server.
I created a database on my networked server that I'll call MyDB. Then I set my connection string in my web config file like this:
add name="ApplicationServices"
connectionString="Data Source=Server\ServerInstance;Initial Catalog=MyDB;Integrated Security=True"
providerName="System.Data.SqlClient"
I created models and a scaffolding controller.
I created a simple DataBaseContext like this:
Imports System.Data.Entity
Public Class DatabaseContext
Inherits DbContext
Public Property Employee As DbSet(Of Employee)
Public Property AnnualLeave As DbSet(Of AnnualLeave)
End Class
But when I hit the following line in the scaffolding controller, i get the error:
Function Index() As ViewResult
Return View(db.Employee.ToList()) //CREATE DATABASE permission denied in database 'master'`.
End Function
Should I fix this by changing the permissions on the MyDB database? Is this a permissions issue on the SQL server side? I am confused why I am getting a Create database error because the DB already exists.
Am I getting this error b/c I have already created the database? Does the scaffolding want to create the database somehow?
Sounds like it is trying to create a new DB by the error message. I'm guessing that you are using EF code first with your project and using it's migration capability to build your DB. Check the setup of the EF context to make sure it's using your connection string.
The connection string or its name can be passed to constructor of DbContext. If you are using default constructor it searches for the connection string with the same name as the name of your derived context class. Basically, make sure your connection string has the same name as your derived dbcontext class and it should find it.
See this post for additional information
1.You need to set IIS app pool identity to be ASP.NET integration mode.
2.Add a login in SQL Server for IIS APPPOOL\ASP.NET.
3.In SQL Server, set IIS APP POOL login to have dbcreator role.
USE master;
EXECUTE sp_addsrvrolemember #loginame = N'YourAppUserLogin', #rolename = N'dbcreator';
<add name="Default" connectionString="Data Source=.\SQLEXPRESS;Initial Catalog=test2;user id=sa;password=123456"
providerName="System.Data.SqlClient" />
Use this connection string for your application

Resources