webapi - db Migrations - mysql

I tried to run my code after adding two new classes to the ef using web api 2, and i got the following error :
The model backing the 'AuthContext' context has changed since the database was created.
When I tried to do "Enable-Migrations", i got the error :
No MigrationSqlGenerator found for provider 'MySql.Data.MySqlClient'.
I found a solution but it's a solution for MVC which is the following:
public Configuration()
{
AutomaticMigrationsEnabled = false;
// register mysql code generator
SetSqlGenerator("MySql.Data.MySqlClient", new MySql.Data.Entity.MySqlMigrationSqlGenerator());
}
The thing is I can't find where to put this piece of code in my web api project.

The solution to webapi is the same as a web MVC project.
First, you run command "enable-migrations" in the Package manage console. The the Migrations folder will be created in your project structure where you can find the Configuration.cs file.
Then inside the Configuration.cs file, add
// register mysql code generator
SetSqlGenerator("MySql.Data.MySqlClient", new MySql.Data.Entity.MySqlMigrationSqlGenerator());
into the constructor just below the line
AutomaticMigrationsEnabled = false;
That's all.

Related

ASP.NET Core 6 MVC + views: exception when switching from AddDefaultIdentity to AddIdentity

I have opened a test project (.NET 6, VS2022) based on ASP.NET Core MVC and views template (not Razor pages), with activated individual user accounts.
Program.cs looks like this (from the template):
builder.Services.AddDefaultIdentity<IdentityUser>(options ...
builder.Services.AddControllersWithViews();
...
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
app.MapRazorPages();
So far so good.
Now I added some example code to seed the user database, which needs access to the RoleManager:
var roleManager = services.GetRequiredService<RoleManager<IdentityRole>>();`
However, that throws an exception
No service for type Microsoft.AspNetCore.Identity.RoleManager`1[Microsoft.AspNetCore.Identity.IdentityRole]'
which could be fixed (thanks Stackoverflow) by changing the AddDefaultIdentity() to AddIdentity() which introduces IdentityRole:
builder.Services.AddIdentity<IdentityUser, IdentityRole>(options ...
However, now I get an exception further down with
app.MapRazorPages();
System.InvalidOperationException: 'Unable to find the required services. Please add all the required services by calling 'IServiceCollection.AddRazorPages' inside the call to 'ConfigureServices(...)' in the application startup code.'
Which services need to be configured and how?
When I remove app.MapRazorPages();, the user management pages (login, user registration) do no longer work (404 error).
When I instead add builder.Service.AddRazorPages() above, the routing is also broken: a route to "/account/login" is missing, probably because Razor pages are somewhat differently organized than MVC controllers. Obviously, I do not want Razor pages, just Razor logic in a few views, and basically MVC architecture.
I am, honestly, a bit confused, since the official documentation does not help much.
Follow your document, I fount that what you did is adding an initialization to create data in the database. So I created a new .net 6 MVC app and integrate default authentication. Pick up Authentication type field with Individual User Accounts when creating the project, then run Update-Database command in Package Manager Console window. Now I have a empty .net 6 MVC project with default asp.net core authentication.
Next, I followed the document and created a SeedData.cs file in the root folder:
using Microsoft.AspNetCore.Identity;
namespace WebAppDefIdentity
{
public static class SeedData
{
//public const string AdministratorRole = "Administrator";
public static async Task InitializeAsync(IServiceProvider services) {
var roleManager = services.GetRequiredService<RoleManager<IdentityRole>>();
await EnsureRolesAsync(roleManager);
}
private static async Task EnsureRolesAsync(RoleManager<IdentityRole> roleManager)
{
var alreadyExists = await roleManager.RoleExistsAsync("Administrator");
}
}
}
And the document is .net 5 oriented project, so need a little change. In the Program.cs file, adding following codes.
using (var scope = app.Services.CreateScope())
{
var aa = scope.ServiceProvider;
await SeedData.InitializeAsync(aa);
}
Then I reproduce your first exception
To solve this exception, I changed in Program.cs with code .AddRoles<IdentityRole>()
Then no exception.

ASP.NET 5: Configuring IdentityServer3 authentication

I've just started digging into the new ASP.NET 5 by creating a test single page application with the OAuth login. I already know that I can use IdentityServer3 for that purpose and it seems pretty nice. I've found a post by Dominick Baier which is explaining how to set up the IdentityServer3. However, the post seems to be out of date or the identity server itself isn't working with the latest version of the ASP.NET 5 (which is beta7 at the moment).
The problem is, when I try to configure the IdentityServer in the Startup.cs I got an error from VS telling me that IApplicationBuilder has no extension method called UseIdentityServer. And this seems to be true, since in the IdentityServer3 source code they have this extension method declared for IAppBuilder (not IApplicationBuilder).
Here is my code (Startup.cs):
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
// Add MVC to the request pipeline.
app.UseMvc();
var options = new IdentityServerOptions
{
Factory = new IdentityServerServiceFactory()
};
app.UseIdentityServer(options);
}
And the error (on the last line) is
'IApplicationBuilder' does not contain a definition for 'UseIdentityServer' and the best extension method overload 'UseIdentityServerExtension.UseIdentityServer(IAppBuilder, IdentityServerOptions)' requires a receiver of type 'IAppBuilder'
Obviously, if I change the parameter type in the Configure method to IAppBuiler, it'll throw a runtime error because the dependency injection will not be able to inject that type. Even if it would, I'd lose the UseMvc() extension method.
So could you point me in the right direction please?
Perhaps I'm just missing something tiny but crucial here.
Thanks in advance!

CloudFoundry MySQL Java configuration

I have a Spring MVC app that is running fine on local tomcat etc. Its a Spring 3.1 MVC/Hibernate app.
I am using (where possible) pure Java #Configuration for the app - and I am now trying to deploy the app to CloudFoundry (via STS), but I am struggling to get the MySql db configured (from memory, with xml config you dont need to do anything and Spring/CloudFoundry auto-injects the required user/password etc, but its been a while since I deployed anything to CF).
I have tried both of the following configurations:
#Bean
public BasicDataSource dataSource() throws PropertyVetoException {
//CloudFoundry config
final CloudEnvironment cloudEnvironment = new CloudEnvironment();
final List<MysqlServiceInfo> mysqlServices = cloudEnvironment.getServiceInfos(MysqlServiceInfo.class);
final MysqlServiceInfo serviceInfo = mysqlServices.get(0);
BasicDataSource bean = new BasicDataSource();
bean.setDriverClassName("com.mysql.jdbc.Driver");
bean.setUrl(serviceInfo.getUrl());
bean.setUsername(serviceInfo.getUserName());
bean.setPassword(serviceInfo.getPassword());
return bean;
}
The above failed on out of bounds on the .get(0) line of the mysqlServices. This was based on the answer suggested here.
I also tried leaving the datasource as what it runs on as local to see if the properties just get injected, but no luck there either. (the below was tried with the values as per the Spring sample code here, and also using property placeholders from my db.connection props file)
#Bean
public BasicDataSource dataSource() throws PropertyVetoException {
BasicDataSource bean = new BasicDataSource();
bean.setDriverClassName("com.mysql.jdbc.Driver");
bean.setUrl("");
bean.setUsername("spring");
bean.setPassword("spring");
return bean;
}
Edit
I have also used the getServiceInfo(String, Class) method passing in the name of the MySql service that I have created and bound to the application, but that just NPEs similar to the getServiceInfos(..) approach
Ok, this was just a stupid mistake - when I deployed the app via STS I had selected Java Web app rather than the "Spring" type. Not sure why that would make the CloudEnvironment properties not be available (I was under the impression that approach was the common method to inject the details in non-Spring apps) - but re-deploying it to the server as a Spring app resolved the probs!

Unable to apply code first migrations to mysql database

I am working on asp.net mvc with EF code first model. I am trying to apply migrations using EF code first to my project. I am using MySql database. currently i am using EF 4.3.1 version and mysql connector/.net of 6.6.4.0 version. I am successfully add migrations to my project that means i execute series of commands that gave no errors for me. I have followed these steps,
PM> Enable-Migrations
PM> Add-Migration InitialMigration
PM> update-database -verbose
these steps create Migration folder to my project and inside Migration folder it creates configuration and timestamp_Initialmigration files, in configuration file i have added following code.
SetSqlGenerator("MySql.Data.MySqlClient", new MySql.Data.Entity.MySqlMigrationSqlGenerator());
after that i have added one field to my class like,
public int newprop{get; set;}
after that i execute update-database -verbose command in PM console.
when i execute my application it throws an error like,
"Unknown column 'Extent1.newprop' in 'field list'"
please guide me why i am getting this error does i went to the wrong way please guide me.
If your not using automatic migrations
Database.SetInitializer(new MigrateDatabaseToLatestVersion());
public class MyMigrationConfiguration : DbMigrationsConfiguration<MyDbContext>
{
public MyMigrationConfiguration()
{
AutomaticMigrationsEnabled = true; // Are you using this ?????
AutomaticMigrationDataLossAllowed = true;
}
}
Then you need to tell EF using the PM Commandlet to add another migration and update the database.
PM> Enable-Migrations //already done this ?
PM> Add-Migration myLabel
PM> Update-Database
Search for "code based migrations" on web for help
This is a bit late to answer OP... But since it pops up as my first hit on google, ill go ahead anyways :)
The problem here is, that there are a number of restrictions on MySQL as compared to MSSQL.
* In particular with mysql on casesensitive filesystems (linux hosts), table names may not include capitalized letters.
* Also keys are restricted to 767 bytes and should/must be integer types.
* Then there is a problem in parts of the migration generators from Mysql.Data package. For instance when renaming, 'dbo' is not stripped away.
Have a look at this guide on insidemysql.com. It describes how to reconfigure the Aspnet.Identity stack for using int in the TKey typecast.
I have a project where i also have hooked into HistoryContext, allowing to alter structure of __MigrationHistory. It renames and resizes the table/columns. There's also the remake of IdentityConfig - so have a look at
https://github.com/mschr/ASP.NET-MVC5.MySql-Extended-Bootstrap/tree/master/my.ns.entities/DbContexts/MigrationConfig
https://github.com/mschr/ASP.NET-MVC5.MySql-Extended-Bootstrap/tree/master/my.ns.entities/IdentityConfig
Then hook it up with your context (see IdentityDbContext) and enable the mentioned MySqlMigrationScriptGenerator and HistoryContextFactory in your Migrations.Configuration class (see my IdentitiyMigrations.Configuration)

Castle Windsor Configuration Over Multiple Projects and unit testing

I have a solution with multiple projects and one of these projects is my service class which calls into the persistence manager.
I would like to write a unit test as follows:
[Test]
public void Create_HappyPath_Success()
{
// Arrange
UnitOfMeasure unitOfMeasure = new UnitOfMeasure();
unitOfMeasure.Code = "Some new unit of measure";
unitOfMeasure.DataOwner = 1;
// Act
this.UoMService.Create(unitOfMeasure); // Fails here as UoMService is null
// Assert something
}
Now, I'm getting a null reference exception on this line:
this.UoMService.Create(unitOfMeasure); // Fails here as UoMService is null
I believe that it's due to the fact that Castle Windsor is not getting called and hence the UoMService isn't getting instantiated. My Castle Windsor application installer is defined in another project i.e. my ASP.NET MVC project. So my first question is whether it's possible to reuse that installer to run my Unit Tests.
Now to get around this problem, I created a new installer in my unit test project by linking to the installer in my web project. Then I used the following code in my set up:
[SetUp]
public void ControllersInstallerTests()
{
this.containerWithControllers = new WindsorContainer();
IoC.Initialize(this.containerWithControllers);
this.containerWithControllers.Install(FromAssembly.This());
}
This time when I run the tests, I get the following error:
SetUp : Castle.Windsor.Configuration.Interpreters.XmlProcessor.ConfigurationProcessingException : Error processing node resource FileResource: [] []
----> Castle.Core.Resource.ResourceException : File C:\Projects\DavidPM\Services\MyProject.Services.ServiceImpl.Test.Unit\bin\Debug\Config\Windsor.config could not be found
The question is why is it looking in the bin\Debug folder?
As a newbie with Castle Windsor, I am not sure what I should be doing to hook into Castle Windsor for my unit tests.
You should not be hooking up your IoC container in your unit tests. During production, your IoC container will resolve dependencies. During unit tests, you create the dependencies as part of your tests -- usually using a mocking framework so you can test in isolation.
make your config file copy to output directory