MySQL EF6 with MVC5 and DNX - mysql

I have a MVC5 Project, using MySQL.Data.Entity.EF6, that I am attempting to load using Kestrel (DNX).
However, I continue to get this error on Page Load:
MetadataException: Schema specified is not valid. Errors:
CMaxModel.ssdl(2,2) : error 0152: No Entity Framework provider found for the ADO.NET
provider with invariant name 'MySql.Data.MySqlClient'. Make sure the provider is
registered in the 'entityFramework' section of the application config file. See
http://go.microsoft.com/fwlink/?LinkId=260882 for more information.
I have created my DbContext using this configuration:
public class MyDbConfiguration : DbConfiguration
{
public MyDbConfiguration()
{
// Register ADO.NET provider
var dataSet = (DataSet)ConfigurationManager.GetSection("system.data");
dataSet.Tables[0].Rows.Add(
"MySQL Data Provider",
".Net Framework Data Provider for MySQL",
"MySql.Data.MySqlClient",
typeof(MySqlClientFactory).AssemblyQualifiedName
);
// Register Entity Framework provider
SetProviderServices("MySql.Data.MySqlClient", new MySqlProviderServices());
SetDefaultConnectionFactory(new MySqlConnectionFactory());
}
}
[DbConfigurationType(typeof(MyDbConfiguration))]
public partial class CMax : DbContext
{
public CMax(string connectionString)
: base(connectionString)
{
}
Even tho from what I've read that MVC doesn't use web.config, in the wwwroot, I have even entered into the Web.Config file:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<configSections>
<section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false"/>
<!-- For more information on Entity Framework configuration, visit http://go.microsoft.com/fwlink/?LinkID=237468 -->
</configSections>
<entityFramework>
<defaultConnectionFactory type="System.Data.Entity.Infrastructure.LocalDbConnectionFactory, EntityFramework">
<parameters>
<parameter value="v12.0"/>
</parameters>
</defaultConnectionFactory>
<providers>
<provider invariantName="MySql.Data.MySqlClient" type="MySql.Data.MySqlClient.MySqlProviderServices, MySql.Data.Entity.EF6, Version=6.9.6.0, Culture=neutral, PublicKeyToken=c5687fc88969c44d">
</provider>
</providers>
</entityFramework>
<system.data>
<DbProviderFactories>
<remove invariant="MySql.Data.MySqlClient"/>
<add name="MySQL Data Provider" invariant="MySql.Data.MySqlClient" description=".Net Framework Data Provider for MySQL" type="MySql.Data.MySqlClient.MySqlClientFactory, MySql.Data, Version=6.9.6.0, Culture=neutral, PublicKeyToken=c5687fc88969c44d"/>
</DbProviderFactories>
</system.data>
<system.webServer>
<handlers>
<add name="httpPlatformHandler" path="*" verb="*" modules="httpPlatformHandler" resourceType="Unspecified"/>
</handlers>
<httpPlatform processPath="%DNX_PATH%" arguments="%DNX_ARGS%" stdoutLogEnabled="false" startupTimeLimit="3600"/>
</system.webServer>
</configuration>
I am at a complete loss, any help would be appreciated.

Related

Using a Class Library for ASP.NET Membership Provider with MySQL

I am attempting to use the ASP.NET Membership Provider with a MySQL database with mixed success. My solution currently contains an ASP.NET MVC project that has been configured to use MySQL and another project that handles all calls to the database in which I also want to handle membership functions such as creating and validating users.
Both projects have MS .NET EnityFramework v6.1.3, Microsoft.AspNet.Identity.EntityFramework v2.2.1 and MySql.Data.Entity v6.9.7 installed.
I configured the ASP.NET project as per the instructions at http://k16c.eu/2014/10/12/asp-net-identity-2-0-mariadb/. My "web.config" is configured as follows;
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<configSections>
<section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
</configSections>
<connectionStrings>
<remove name="LocalMySqlServer" />
<add name="LocalMySqlServer"
connectionString="Server=localhost; Database=rb-web; Uid=root; Pwd=password; Convert Zero Datetime=True; Allow User Variables=True;"
providerName="MySql.Data.MySqlClient" />
</connectionStrings>
<system.web>
<compilation debug="true" targetFramework="4.5" />
<httpRuntime targetFramework="4.5" />
</system.web>
<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" />
<provider invariantName="MySql.Data.MySqlClient" type="MySql.Data.MySqlClient.MySqlProviderServices, MySql.Data.Entity.EF6, Version=6.9.7.0, Culture=neutral, PublicKeyToken=c5687fc88969c44d" />
</providers>
</entityFramework>
<system.data>
<DbProviderFactories>
<remove invariant="MySql.Data.MySqlClient" />
<add name="MySQL Data Provider"
invariant="MySql.Data.MySqlClient"
description=".Net Framework Data Provider for MySQL"
type="MySql.Data.MySqlClient.MySqlClientFactory, MySql.Data, Version=6.9.7.0, Culture=neutral, PublicKeyToken=c5687fc88969c44d" />
</DbProviderFactories>
</system.data>
</configuration>
The instructions at http://k16c.eu/2014/10/12/asp-net-identity-2-0-mariadb/ required creating two new classes, ApplicationUser.cs and ApplicationContext.cs however these were basically replicating the code in IdentityModels.cs which was already included in my project. The identity model code is;
using System.Data.Entity;
using System.Security.Claims;
using System.Threading.Tasks;
using Microsoft.AspNet.Identity;
using Microsoft.AspNet.Identity.EntityFramework;
using MySql.Data.Entity;
namespace RB.Client.Models
{
public class ApplicationUser : IdentityUser
{
public async Task<ClaimsIdentity> GenerateUserIdentityAsync(UserManager<ApplicationUser> manager)
{
var userIdentity = await manager.CreateIdentityAsync(this, DefaultAuthenticationTypes.ApplicationCookie);
return userIdentity;
}
}
[DbConfigurationType(typeof(MySqlEFConfiguration))]
public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
{
public ApplicationDbContext() : base("LocalMySqlServer", throwIfV1Schema: false) { }
public ApplicationDbContext(string connStringName) : base(connStringName, throwIfV1Schema: false) { }
public static ApplicationDbContext Create()
{
return new ApplicationDbContext();
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
// Primary keys can easily get too long for MySQL's (InnoDB's) stupid 767 bytes limit.
// The following lines rewrite the generation to keep those columns "short" enough.
modelBuilder.Entity<IdentityRole>()
.Property(c => c.Name)
.HasMaxLength(128)
.IsRequired();
// Declare the table name here, otherwise IdentityUser will be created.
modelBuilder.Entity<ApplicationUser>()
.ToTable("AspNetUsers")
.Property(c => c.UserName)
.HasMaxLength(128)
.IsRequired();
}
}
}
Once these changes were made I ran the Enable-Migrations from Package Manager Console and modified the Configuration.cs class as follows;
namespace RB.Client.Migrations
{
using System;
using System.Data.Entity;
using System.Data.Entity.Migrations;
using System.Linq;
internal sealed class Configuration : DbMigrationsConfiguration<RB.Client.Models.ApplicationDbContext>
{
public Configuration()
{
AutomaticMigrationsEnabled = false;
SetSqlGenerator("MySql.Data.MySqlClient", new MySql.Data.Entity.MySqlMigrationSqlGenerator());
}
protected override void Seed(RB.Client.Models.ApplicationDbContext context)
{
}
}
}
I then ran the Add-Migration "Initial" and Update-Database command from the Package Manager Console which created the aspnetroles, aspnetuserclaims, aspnetuiserlogins, aspnetuserroles and aspnetusers tables in MySQL.
I then use the following code in my persistence project;
public UserDto RegisterUser(UserDto user)
{
var appUser = Membership.CreateUser(user.Email, user.Password);
}
Which raises the exception;
"Unable to initialize provider. Missing or incorrect schema."
"MySql.Web at MySql.Web.Common.SchemaManager.CheckSchema(String connectionString, NameValueCollection config)
at MySql.Web.Security.MySQLMembershipProvider.Initialize(String name, NameValueCollection config)
at System.Web.Configuration.ProvidersHelper.InstantiateProvider(ProviderSettings providerSettings, Type providerType)"
However, if I add the following entries to the "web.config";
<system.web>
<roleManager defaultProvider="MySQLRoleProvider">
<providers>
<remove name="MySQLRoleProvider" />
<add name="MySQLRoleProvider"
type="MySql.Web.Security.MySQLRoleProvider, MySql.Web, Version=6.9.7.0, Culture=neutral, PublicKeyToken=c5687fc88969c44d"
applicationName="/RBWeb"
description="RB Role Provider"
connectionStringName="LocalMySqlServer"
writeExceptionsToEventLog="True"
autogenerateschema="True"
enableExpireCallback="False" />
</providers>
</roleManager>
<membership defaultProvider="MySQLMembershipProvider">
<providers>
<remove name="MySQLMembershipProvider" />
<add name="MySQLMembershipProvider"
type="MySql.Web.Security.MySQLMembershipProvider, MySql.Web, Version=6.9.7.0, Culture=neutral, PublicKeyToken=c5687fc88969c44d"
applicationName="/RbWeb"
description="RB Membership Provider"
connectionStringName="LocalMySqlServer"
writeExceptionsToEventLog="True"
autogenerateschema="True"
enableExpireCallback="False"
enablePasswordRetrieval="False"
enablePasswordReset="True"
requiresQuestionAndAnswer="False"
requiresUniqueEmail="True"
passwordFormat="Hashed"
maxInvalidPasswordAttempts="5"
minRequiredPasswordLength="6"
minRequiredNonalphanumericCharacters="1"
passwordAttemptWindow="10"
passwordStrengthRegularExpression="" />
</providers>
</membership>
<compilation debug="true" targetFramework="4.5" />
<httpRuntime targetFramework="4.5" />
</system.web>
The user is successfully created and a System.Web.Security.MembershipUser object is returned. However the call has now generated a number of new tables in the database, my_aspnet_users, my_aspnet_roles, etc along with all of the tables for profiles, personalisation, and session management even though these options weren't included in the web.config settings and the user record was created in these tables. There seems to be a disconnect between my web and persistence projects.
I have reviewed all of the articles I could find in MySQL however these all appear to be out of date and were of no help. At this point I am now writing a custom membership provider to try and get around these problems but to be honest I'm also considering ditching MySQL due to the problems I have faced trying to get this to work.

Entity Framework + MySql + Guid error

I am using Entity Framework with MySql.
I have problems inserting items in Database using Guid properties.
The error i get is: Incorrect string value: '\x9D?Z\xC2\x1C\xB2...' for column 'Id' at row 1
If i change the property Id from Guid to string, it works fine.
The Collation of the table is set to utf8 - default collation. I have changed it to uft8mb4 - default collation with no effect at all.
The Id property Datatype is VARCHAR(64) PK NN UQ
Here is the simplified code
public class AppFormAppUnitOfWork : DbContext
{
public DbSet<MenuItem> MenuItems { get; set; }
}
static void MySqlGuid(AppFormAppUnitOfWork unitOfWork)
{
MenuItem menuItem = new MenuItem();
menuItem.Id = Guid.NewGuid();
menuItem.MenuItem_Name = "Hello World";
unitOfWork.MenuItems.Add(menuItem);
using (var trans = new TransactionScope())
{
// throws
// Incorrect string value: '\x9D?Z\xC2\x1C\xB2...' for column 'Id' at row 1
unitOfWork.SaveChanges();
trans.Complete();
}
}
static void MySqlString(AppFormAppUnitOfWork unitOfWork)
{
MenuItem menuItem = new MenuItem();
menuItem.Id = Guid.NewGuid().ToString();
menuItem.MenuItem_Name = "Hello World";
unitOfWork.MenuItems.Add(menuItem);
using (var trans = new TransactionScope())
{
// works ok
unitOfWork.SaveChanges();
trans.Complete();
}
}
Here are the web.config settings
<?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=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
</configSections>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
</startup>
<connectionStrings>
<add name="AppFormAppUnitOfWork" providerName="MySql.Data.MySqlClient" connectionString="server=localhost;port=3306;database=appformapp;uid=root;password=microsoft;Old Guids=true;Charset=utf8;" />
</connectionStrings>
<system.data>
<DbProviderFactories>
<remove invariant="MySql.Data.MySqlClient" />
<add name="MySQL Data Provider" invariant="MySql.Data.MySqlClient" description=".Net Framework Data Provider for MySQL" type="MySql.Data.MySqlClient.MySqlClientFactory, MySql.Data, Version=6.9.6.0, Culture=neutral, PublicKeyToken=c5687fc88969c44d" />
</DbProviderFactories>
</system.data>
<entityFramework>
<defaultConnectionFactory type="System.Data.Entity.Infrastructure.LocalDbConnectionFactory, EntityFramework">
<parameters>
<parameter value="v11.0" />
</parameters>
</defaultConnectionFactory>
<providers>
<provider invariantName="MySql.Data.MySqlClient" type="MySql.Data.MySqlClient.MySqlProviderServices, MySql.Data.Entity.EF6, Version=6.9.6.0, Culture=neutral, PublicKeyToken=c5687fc88969c44d">
</provider>
</providers>
</entityFramework>
</configuration>
The packages (Entity Framework MySql provider) i am using for this are:
<packages>
<package id="EntityFramework" version="6.0.0" targetFramework="net45" />
<package id="MySql.Data" version="6.9.6" targetFramework="net45" />
<package id="MySql.Data.Entity" version="6.9.6" targetFramework="net45" />
</packages>
How can i fix this problem without changing all the Guid properties to string?
GUID is not supported directly in MySql. The right structure to store it is BINARY(16) (you can store the GUID using Guid.ToByteArray). If you want to keep a varchar (I've never used binary to store Ids) you could use
menuItem.Id = String.Format("{0:N}", Guid.NewGuid());
Use CHAR(36) instead of VARCHAR(64). EF will then auto map it correctly. The same goes for Dapper by the way. I've used both and experimented with BINARY(16) and various VARCHAR() combinations, but CHAR(36) has always worked best with an ORM. Also with BINARY(16) you lose the human readability, which can make debugging difficult. I don't know why the MySQL docs recommend VARCHAR(64); it's overkill, and uniqueidentifiers are always exactly 36 bytes long, so the var byte is a waste of space.

Can't connect to MySql database with Entity Framework 6

Installed via NuGet: MySql.Data, MySql.Data.Entities, MySql.Data.Entity.
Web.config:
<connectionStrings>
<add name="WhateverEntities" providerName="MySql.Data.MySqlClient" connectionString="server=127.0.0.1;port=3306;database=dbname;uid=root;password=pass" />
<connectionStrings>
...
<entityFramework>
<defaultConnectionFactory type="MySql.Data.Entity.MySqlConnectionFactory, MySql.Data.Entity.EF6" />
<providers>
<provider invariantName="MySql.Data.MySqlClient" type="MySql.Data.MySqlClient.MySqlProviderServices, MySql.Data.Entity.EF6, Version=6.9.6.0, Culture=neutral, PublicKeyToken=c5687fc88969c44d" />
</providers>
<entityFramework>
ApplicationDbContext.cs:
public ApplicationDbContext() : base(nameOrConnectionString: "WhateverEntities") {}
tried to add:
[DbConfigurationType(typeof(MySql.Data.Entity.MySqlEFConfiguration))]
and:
[DbConfigurationType(typeof(MySqlEFConfiguration))]
got this error:
An exception of type
'System.Data.Entity.Core.ProviderIncompatibleException' occurred in
EntityFramework.dll but was not handled in user code
Additional information: The provider did not return a
ProviderManifestToken string.
What's wrong?
It was a matter of password as vdwijngaert suggested. Changed it in PhpMyAdmin.

Using Visual Studio 2013 with Entity Framework 6 how to use code first with a mySql database

I've been working on a WPF application. I'm trying to include a MySql database. Outside of using MySql for Visual Studio I've not seen a good tutorial for using Entity Framework 6 with MySql database's. Anyone have a good tutorial for WPF that I can use or what I need next. Most of what I have seen doesn't have code first.
So far what I have is a connection to a empty mysql db in the Server Explorer. Secondly I've got my packages.config file :
<packages>
<package id="CommonServiceLocator" version="1.2" targetFramework="net45" />
<package id="EntityFramework" version="6.1.1" targetFramework="net45" />
<package id="ModernUI.WPF" version="1.0.5" targetFramework="net45" />
<package id="MvvmLight" version="4.2.30.0" targetFramework="net45" />
<package id="MvvmLightLibs" version="4.3.31.1" targetFramework="net45" />
<package id="MySql.Data" version="6.9.2-rc1" targetFramework="net45" />
<package id="MySql.Data.Entity" version="6.9.2-rc1" targetFramework="net45" />
</packages>
Then I've got my App.config file... Haven't done anything with this as I am not sure what to do :
<?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=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
<!-- For more information on Entity Framework configuration, visit http://go.microsoft.com/fwlink/?LinkID=237468 --></configSections>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
</startup>
<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>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="Microsoft.Practices.ServiceLocation" p ublicKeyToken="31bf3856ad364e35" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-1.2.0.0" newVersion="1.2.0.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>
<connectionStrings><add name="Model1" connectionString="data source=(LocalDb)\v11.0;initial catalog=_12_RSE_002.Model1;integrated security=True;MultipleActiveResultSets=True;App=EntityFramework" providerName="System.Data.SqlClient" /></connectionStrings></configuration>
First you need to add a reference to Mysql.Data.Entity to your project.
As a first tutorial i would recommend this one.
In this tutorial you don't need to specify a connection string because visual studio will do it for you when you create ADO.NET Entity Data Model.
EDIT :
In the connectionStrings section: you need to add the connectionString to your MYSQL database, you can replace the one called Model1 or add another one like this :
<add name="Model1" connectionString="server=127.0.0.1;Uid=root;Database=mysqlentityframework" providerName="MySql.Data.MySqlClient" />
Also in the Providers section you need to add a provider for Mysql.Data.MysqlClient :
<provider invariantName="MySql.Data.MySqlClient" type="MySql.Data.MySqlClient.MySqlProviderServices, MySql.Data.Entity.EF6"></provider>
this provider is used by the connection string to specify which database to use, you can delet the System.Data.SqlClient, you have nothing to do with it now, so your final app.config file should look something like this:
<?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=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
</configSections>
<entityFramework>
<providers>
<provider invariantName="MySql.Data.MySqlClient" type="MySql.Data.MySqlClient.MySqlProviderServices, MySql.Data.Entity.EF6"></provider>
</providers>
</entityFramework>
<connectionStrings>
<add name="Model1" connectionString="server=127.0.0.1;Uid=root;Database=mysqlentityframework" providerName="MySql.Data.MySqlClient" />
</connectionStrings>
this is working for me, all you need to do is add an ADO.NET entity data Model and create your Entities.
EDIT2: this is the code first example:Model.cs FILE
namespace TestsAndTests
{
using System;
using System.Data.Entity;
using System.Linq;
public class Model1 : DbContext
{
public Model1()
: base("name=Model1")
{
}
public DbSet<students> Students { get; set; }
}
public class students
{
[Key]
public int StudentI { get; set; }
public string StudentName { get; set; }
}
}
Program.cs Main function:
students student = new students
{
StudentI = 3,
StudentName = "test1"
};
Model1 model = new Model1();
model.Students.Add(student);
model.SaveChanges();
Console.WriteLine("object Added");
Hope this helps.

Windsor IHandlerSelector in RIA Services Visual Studio 2010 Beta2

I want to implement multi tenancy using Windsor and i don't know how to handle this situation:
i succesfully used this technique in plain ASP.NET MVC projects and thought incorporating in a RIA Services project would be similar.
So i used IHandlerSelector, registered some components and wrote an ASP.NET MVC view to verify it works in a plain ASP.NET MVC environment. And it did!
Next step was to create a DomainService which got an IRepository injected in the constructor. This service is hosted in the ASP.NET MVC application. And it actually ... works:i can get data out of it to a Silverlight application.
Sample snippet:
public OrganizationDomainService(IRepository<Culture> cultureRepository)
{
this.cultureRepository = cultureRepository;
}
Last step is to see if it works multi-tenant-like: it does not! The weird thing is this:
using some line of code and writing debug messages in a log file i verified that the correct handler is selected! BUT this handler seems not to be injected in the DomainService. I ALWAYS get the first handler (that's the logic in my SelectHandler)
Can anybody verify this behavior? Is injection not working in RIA Services? Or am i missing something basic??
Development environment: Visual Studio 2010 Beta2
Thanks in advance
So it seems i did a very weird thing in my OrganizationDomainServiceFactory.
The code which did NOT work is this:
public DomainService CreateDomainService(Type domainServiceType, DomainServiceContext context )
{
WindsorContainer container = new WindsorContainer(new XmlInterpreter(new ConfigResource("castle")));
IRepository<Culture> cultureRepository = container.Resolve<IRepository<Culture>>();
IRepository<Currency> currencyRepository = container.Resolve<IRepository<Currency>>();
DomainService ds = (DomainService)Activator.CreateInstance(domainServiceType, new object[] { cultureRepository,currencyRepository });
ds.Initialize(context);
return ds;
}
This is apparently not working, because of the creation of a new Container (which should not take place).
OK! So i thought i try to use ServiceLocator to get a reference to the Windsor Container (used in the WindsorControllerFactory - that's how i call it ... in the boot up of the ASP.NET MVC application), and changed the code to this:
public DomainService CreateDomainService(Type domainServiceType, DomainServiceContext context )
{
IRepository<Culture> cultureRepository = ServiceLocator.Current.GetInstance<IRepository<Culture>>();
IRepository<Currency> currencyRepository = ServiceLocator.Current.GetInstance<IRepository<Currency>>();
DomainService ds = (DomainService)Activator.CreateInstance(domainServiceType, new object[] { cultureRepository,currencyRepository });
ds.Initialize(context);
return ds;
}
and guess what: it works(!!!) multi-tenancy as it should be!
The only thing i don't know is: is there another way to "inject" the container (constructor injection seems not to work here , the compiler complains)
BTW: moved the project from VS2010Beta2 to VS2010RC (with RIA Services support), but this should not affect the outcome!
Yes i have seen this thread and i already have implemented this.
Firstly have in mind that i have used this line in Global.asax.cs to get the RIA services properly behave (hosted in an ASP.NET MVC view)
routes.IgnoreRoute("{*allsvc}", new { allsvc = #".*\.svc(/.*)?" });
Here is some code:
public class HostBasedComponentSelector : IHandlerSelector
{
private readonly Type[] selectableTypes;
public HostBasedComponentSelector(params Type[] selectableTypes)
{
this.selectableTypes = selectableTypes;
}
public bool HasOpinionAbout(string key, Type service)
{
foreach (var type in selectableTypes)
{
if (service == type) return true;
}
return false;
}
public IHandler SelectHandler(string key, Type service, IHandler[] handlers)
{
//only for debug
StreamWriter sw = new StreamWriter(#"c:\temp\Debug.log",true);
sw.WriteLine(DateTime.Now + " " + service.Name + " " + GetHostname() );
sw.WriteLine("Available handlers");
foreach(IHandler h in handlers )
{
sw.WriteLine ("Handler "+h.ComponentModel.Name);
}
var id = string.Format("{0}:{1}", service.Name, GetHostname());
var selectedHandler = handlers.Where(h => h.ComponentModel.Name == id).FirstOrDefault() ??
GetDefaultHandler(service, handlers);
sw.WriteLine("Selected handler " + selectedHandler.ComponentModel.Name);
sw.WriteLine("----------- END ----------");
sw.Flush();
sw.Close();
return selectedHandler;
}
private IHandler GetDefaultHandler(Type service, IHandler[] handlers)
{
if (handlers.Length == 0)
{
throw new ApplicationException("No components registered for service {0} With service.Name" + service.Name);
}
return handlers[0];
}
protected string GetHostname()
{
return HttpContext.Current.Request.ServerVariables["SERVER_NAME"];
}
}
Here is the complete web.config. Notice registering the OrganizationDomainServiceFactory (it is the implementation of the article you mentioned)
<?xml version="1.0"?>
<!--
For more information on how to configure your ASP.NET application, please visit
http://go.microsoft.com/fwlink/?LinkId=152368
-->
<configuration>
<configSections>
<section name="castle" type="Castle.Windsor.Configuration.AppDomain.CastleSectionHandler,Castle.Windsor"/>
</configSections>
<connectionStrings>
<add name="ApplicationServices" connectionString="data source=.\SQLEXPRESS;Integrated Security=SSPI;AttachDBFilename=|DataDirectory|aspnetdb.mdf;User Instance=true" providerName="System.Data.SqlClient"/>
</connectionStrings>
<castle>
<properties>
<sqlConnStr>
<!--metadata=res://*/WebShop.csdl|res://*/WebShop.ssdl|res://*/WebShop.msl;provider=System.Data.SqlClient;provider connection string="Data Source=.\SQLEXPRESS;Initial Catalog=iWebShop;User ID=sa;Password=xxx;MultipleActiveResultSets=True"-->
</sqlConnStr>
</properties>
<components>
<component id="CommonObjectContext" service="TestRIA1.Abstract.IObjectContext, TestRIA1" type="TestRIA1.Concrete.ObjectContextAdapter, TestRIA1" lifestyle="PerWebRequest">
</component>
<component id="IConnectionStringProvider:test.gammasys.gr" service="TestRIA1.Abstract.IConnectionStringProvider, TestRIA1" type="TestRIA1.Concrete.ConnectionStringProvider, TestRIA1" lifestyle="transient">
<parameters>
<ConnectionString>
metadata=res://*/WebShop.csdl|res://*/WebShop.ssdl|res://*/WebShop.msl;provider=System.Data.SqlClient;provider connection string="Data Source=.\SQLEXPRESS;Initial Catalog=iWebShop;User ID=sa;Password=xxx;MultipleActiveResultSets=True"
</ConnectionString>
</parameters>
</component>
<component id="IConnectionStringProvider:test.deltasys.gr" service="TestRIA1.Abstract.IConnectionStringProvider, TestRIA1" type="TestRIA1.Concrete.ConnectionStringProvider, TestRIA1" lifestyle="transient">
<parameters>
<ConnectionString>
metadata=res://*/WebShop.csdl|res://*/WebShop.ssdl|res://*/WebShop.msl;provider=System.Data.SqlClient;provider connection string="Data Source=.\SQLEXPRESS;Initial Catalog=iWebShop2;User ID=sa;Password=xxx;MultipleActiveResultSets=True"
</ConnectionString>
</parameters>
</component>
<component id="Commonrepository" service="TestRIA1.Abstract.IRepository`1, TestRIA1" type="TestRIA1.Concrete.Repository`1, TestRIA1" lifestyle="PerWebRequest"/>
<component id="urlbased.handlerselector" service="Castle.MicroKernel.IHandlerSelector, Castle.MicroKernel" type="TestRIA1.HostBasedComponentSelector, TestRIA1" lifestyle="transient">
<parameters>
<selectableTypes>
<array>
<item>TestRIA1.Abstract.IConnectionStringProvider, TestRIA1</item>
</array>
</selectableTypes>
</parameters>
</component>
</components>
</castle>
<system.web>
<compilation debug="true" targetFramework="4.0">
<assemblies>
<add assembly="System.Web.Abstractions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
<add assembly="System.Web.Routing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
<add assembly="System.Web.Mvc, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
</assemblies>
</compilation>
<authentication mode="Forms">
<forms loginUrl="~/Account/LogOn" timeout="2880"/>
</authentication>
<membership>
<providers>
<clear/>
<add name="AspNetSqlMembershipProvider" type="System.Web.Security.SqlMembershipProvider" connectionStringName="ApplicationServices" enablePasswordRetrieval="false" enablePasswordReset="true" requiresQuestionAndAnswer="false" requiresUniqueEmail="false" maxInvalidPasswordAttempts="5" minRequiredPasswordLength="6" minRequiredNonalphanumericCharacters="0" passwordAttemptWindow="10" applicationName="/"/>
</providers>
</membership>
<profile>
<providers>
<clear/>
<add name="AspNetSqlProfileProvider" type="System.Web.Profile.SqlProfileProvider" connectionStringName="ApplicationServices" applicationName="/"/>
</providers>
</profile>
<roleManager enabled="false">
<providers>
<clear/>
<add name="AspNetSqlRoleProvider" type="System.Web.Security.SqlRoleProvider" connectionStringName="ApplicationServices" applicationName="/"/>
<add name="AspNetWindowsTokenRoleProvider" type="System.Web.Security.WindowsTokenRoleProvider" applicationName="/"/>
</providers>
</roleManager>
<pages>
<namespaces>
<add namespace="System.Web.Mvc"/>
<add namespace="System.Web.Mvc.Ajax"/>
<add namespace="System.Web.Mvc.Html"/>
<add namespace="System.Web.Routing"/>
</namespaces>
</pages>
<httpHandlers>
<add verb="*" path="*.mvc" validate="false" type="System.Web.Mvc.MvcHttpHandler"/>
</httpHandlers>
<httpModules>
<add name="PerRequestLifestyle" type="Castle.MicroKernel.Lifestyle.PerWebRequestLifestyleModule,Castle.MicroKernel " />
<add name="DomainServiceModule" type="System.Web.Ria.Services.DomainServiceHttpModule, System.Web.Ria, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
</httpModules>
</system.web>
<system.webServer>
<validation validateIntegratedModeConfiguration="false" />
<modules runAllManagedModulesForAllRequests="true">
<add name="DomainServiceModule" preCondition="managedHandler"
type="System.Web.Ria.Services.DomainServiceHttpModule, System.Web.Ria, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
<remove name="PerRequestLifestyle"/>
<add name="PerRequestLifestyle" preCondition="managedHandler" type="Castle.MicroKernel.Lifestyle.PerWebRequestLifestyleModule,Castle.MicroKernel" />
<!--to get IoC initialization of DomainService -->
<add name="ScriptModule" type="System.Web.Handlers.ScriptModule, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
<add name="OrganizationDomainServiceFactory" type="TestRIA1.OrganizationDomainServiceFactory"/>
<!-- End of IoC initial..... -->
</modules>
<handlers>
<remove name="MvcHttpHandler" />
<add name="MvcHttpHandler" preCondition="integratedMode" verb="*"
path="*.mvc" type="System.Web.Mvc.MvcHttpHandler" />
</handlers>
</system.webServer>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.Web.Mvc" publicKeyToken="31bf3856ad364e35"/>
<bindingRedirect oldVersion="1.0.0.0" newVersion="2.0.0.0"/>
</dependentAssembly>
</assemblyBinding>
</runtime>
<system.serviceModel>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" />
</system.serviceModel>
</configuration>
Hope this is enough. In case you would like to have the complete project i can send you a copy (this is a pre-production test project).
Thank you very much for the time you spend!