Note: This question while similar to this one however it's about different issues.
It seems for whatever reason ServiceStack is not running/compiling Razor views and seems like a config issue however RazorRockstarts runs fine.
I'm using ServiceStack 4.0.11 and have compared against RazorRockstars runnning ServiceStack 4.0.8
In VS2013 I have created a new ASP.NET Website (Empty)
Install-Package ServiceStack
Install-Package ServiceStack.Razor
Added httpHandlers to web.config
Created AppHost and .Init() in Global.asax Application_Start.
AppHost.LoadPlugin(new RazorFormat());
Created /Services/HomeService.cs (inherited from ServiceStack.Service)
Created Home route in HomeService
Created /Views/Home/Home.cshtml
I run in debug on VS 2013 and all I get is the ServiceStack snapshot when going to /home. What am I missing?
/AppHost.cs
using Funq;
using ServiceStack;
using ServiceStack.Razor;
namespace SSTest
{
public class AppHost : AppHostBase
{
public AppHost() : base("SSTest", typeof(AppHost).Assembly) { }
public override void Configure(Container container)
{
LoadPlugin(new RazorFormat());
}
public static void Start()
{
new AppHost().Init();
}
}
}
/Global.asax
protected void Application_Start(object sender, EventArgs e)
{
AppHost.Start();
}
/Services/HomeService.cs
using ServiceStack;
namespace SSTest.Services
{
[Route("/home")]
public class Home
{
public string Name { get; set; }
}
[DefaultView("Home")]
public class HomeServices : Service
{
public object Get(Home request)
{
return new Home(){Name = "Here's home!"};
}
}
}
/Views/Home/Home.cshtml
#{
Layout = null;
}
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width" />
<title>Home</title>
</head>
<body>
<div>
<h1>This is home!!</h1>
</div>
</body>
</html>
/Web.config
<?xml version="1.0" encoding="utf-8"?>
<!--
For more information on how to configure your ASP.NET application, please visit
http://go.microsoft.com/fwlink/?LinkId=169433
-->
<configuration>
<configSections>
<sectionGroup name="system.web.webPages.razor" type="System.Web.WebPages.Razor.Configuration.RazorWebSectionGroup, System.Web.WebPages.Razor, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35">
<section name="host" type="System.Web.WebPages.Razor.Configuration.HostSection, System.Web.WebPages.Razor, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission="false" />
<section name="pages" type="System.Web.WebPages.Razor.Configuration.RazorPagesSection, System.Web.WebPages.Razor, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission="false" />
</sectionGroup>
</configSections>
<system.web>
<httpHandlers>
<add path="*" type="ServiceStack.HttpHandlerFactory, ServiceStack" verb="*" />
</httpHandlers>
<compilation debug="true" targetFramework="4.5">
<assemblies>
<add assembly="System.Web.WebPages.Razor, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
</assemblies>
<buildProviders>
<add extension=".cshtml" type="ServiceStack.Razor.CSharpRazorBuildProvider, ServiceStack.Razor" />
</buildProviders>
</compilation>
<httpRuntime targetFramework="4.5" />
</system.web>
<!-- Required for IIS 7.0 -->
<system.webServer>
<validation validateIntegratedModeConfiguration="false" />
<handlers>
<add path="*" name="ServiceStack.Factory" type="ServiceStack.HttpHandlerFactory, ServiceStack" verb="*" preCondition="integratedMode" resourceType="Unspecified" allowPathInfo="true" />
</handlers>
</system.webServer>
<appSettings>
<add key="webPages:Enabled" value="false" />
</appSettings>
<system.web.webPages.razor>
<host factoryType="System.Web.Mvc.MvcWebRazorHostFactory, System.Web.Mvc, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
<pages pageBaseType="ServiceStack.Razor.ViewPage">
<namespaces>
<add namespace="ServiceStack" />
<add namespace="ServiceStack.Html" />
<add namespace="ServiceStack.Razor" />
<add namespace="ServiceStack.Text" />
<add namespace="ServiceStack.OrmLite" />
<add namespace="SSTest" />
<add namespace="SSTest.Services" />
</namespaces>
</pages>
</system.web.webPages.razor>
</configuration>
I know mythz has solved your problem, but something else to check for future readers with the same problem:
Make sure your *.cshtml files are copied to the output directory. For whatever reason, mine weren't, thus ServiceStack couldn't find them and all I got was the snapshot like yourself.
I'm not sure if this is related to using a self-hosted console application instead of a web project.
Inside Configure() plugins should be loaded with:
Plugins.Add(new RazorFormat());
In ServiceStack.Razor Layout = null, suggests to use the default layout template Views\_Layout.cshtml, you can choose not use any template with Layout="" instead.
If you don't have OrmLite installed then you want to remove the ServiceStack.OrmLite namespace from being included in all Razor pages by removing it from your Web.config:
<add namespace="ServiceStack.OrmLite" />
Your view should be located in /Views/Home.cshtml instead of /Views/Home/Home.cshtml.
I was having the exact same issue! With the current ServiceStack VS template (as of April 1, 2015 and no this isn't an April Fools joke!), the following line will mess things up if you're running a self-hosted service:
WebHostPhysicalPath = Path.GetFullPath(Path.Combine("~".MapServerPath(), "..", "..")),
This is within your AppHost.cs file inside of the Configure(Container) function within the SetConfig(new HostConfig { /* ... here ... */ } ); block.
Comment out the entire WebHostPhysicalPath = ... line and re-run your application.
A better fix than simply commenting it out is to set the correct directory which is either your actual bin directory via:
WebHostPhysicalPath = Path.GetFullPath("~".MapServerPath()),
Or, if you have a specific build architecture (ie. x86 or x64 instead of AnyCPU), you likely have a third layer of folders. So change the WebHostPhysicalPath to this:
WebHostPhysicalPath = Path.GetFullPath(Path.Combine("~".MapServerPath(), "..", "..", "..")),
Related
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.
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.
i'm new to this and i get an error and don't know how to slove.
I create a new mvc4 project(c#),empty template.
then i add a controller(empty mvc template), and i put his code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
namespace Testing.Controllers
{
public class Testing2Controller : Controller
{
//
//GET: /Testing2/
public string Index()
{
return "01111000100011";
}
}
}
and i get this:
Server Error in '/' Application.
The resource cannot be found.
Description: HTTP 404. The resource you are looking for (or one of its dependencies) could have been removed, had its name changed, or is temporarily unavailable. Please review the following URL and make sure that it is spelled correctly.
Requested URL: /
Version Information: Microsoft .NET Framework Version:4.0.30319; ASP.NET Version:4.0.30319.17929
my web.config file is this:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<appSettings>
<add key="webpages:Version" value="2.0.0.0" />
<add key="webpages:Enabled" value="false" />
<add key="PreserveLoginUrl" value="true" />
<add key="ClientValidationEnabled" value="true" />
<add key="UnobtrusiveJavaScriptEnabled" value="true" />
</appSettings>
<system.web>
<httpRuntime targetFramework="4.5" />
<compilation debug="true" targetFramework="4.5" />
<pages>
<namespaces>
<add namespace="System.Web.Helpers" />
<add namespace="System.Web.Mvc" />
<add namespace="System.Web.Mvc.Ajax" />
<add namespace="System.Web.Mvc.Html" />
<add namespace="System.Web.Routing" />
<add namespace="System.Web.WebPages" />
</namespaces>
</pages>
</system.web>
<system.webServer>
<validation validateIntegratedModeConfiguration="false" />
<handlers>
<remove name="ExtensionlessUrlHandler-ISAPI-4.0_32bit" />
<remove name="ExtensionlessUrlHandler-ISAPI-4.0_64bit" />
<remove name="ExtensionlessUrlHandler-Integrated-4.0" />
<add name="ExtensionlessUrlHandler-ISAPI-4.0_32bit" path="*." verb="GET,HEAD,POST,DEBUG,PUT,DELETE,PATCH,OPTIONS" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework\v4.0.30319\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv4.0,bitness32" responseBufferLimit="0" />
<add name="ExtensionlessUrlHandler-ISAPI-4.0_64bit" path="*." verb="GET,HEAD,POST,DEBUG,PUT,DELETE,PATCH,OPTIONS" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework64\v4.0.30319\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv4.0,bitness64" responseBufferLimit="0" />
<add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="GET,HEAD,POST,DEBUG,PUT,DELETE,PATCH,OPTIONS" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />
</handlers>
</system.webServer>
</configuration>
Thank you very much, i have no idea of what to do
Your controller method needs to return an ActionResult. you need to do something like this:
public ActionResult Index()
{
return Content("01111000100011");
}
Update
I just noticed that the error mentions the URL /. To get to the controller action in your question you'll have to go to /Testing2.
Now I have next and it works
#foreach (TestLogs.Repository.DatabaseModel.Platforms CurrentPlatform in Model.ApplicationPlatforms)
{
...
}
I want to include TestLogs.Repository.DatabaseModel namespace to Razor's view. I open web.config at views folder and add line there
<system.web.webPages.razor>
<host factoryType="System.Web.Mvc.MvcWebRazorHostFactory, System.Web.Mvc, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
<pages pageBaseType="System.Web.Mvc.WebViewPage">
<namespaces>
<add namespace="System.Web.Mvc" />
<add namespace="System.Web.Mvc.Ajax" />
<add namespace="System.Web.Mvc.Html" />
<add namespace="System.Web.Routing" />
<add namespace="TestLogs.Repository.DatabaseModel" />
</namespaces>
</pages>
But after that next construction doesn't work
#foreach (Platforms CurrentPlatform in Model.ApplicationPlatforms)
{
...
}
What am I doing wrong?
Sorry for my stupid question. It works but my Visual Studio 2012 doesn't mark class name with cyan color as it usually does.
(source: piccy.info)
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!