Ninject Topshelf Microsoft.Owin.Hosting - ninject

How can I utilize Topshelf.Ninject and incorporate OwinNinjectDependencyResolver (from Ninject.Web.WebApi.OwinHost)?
I can get it to work but I need to instantiate the Ninject kernel twice (once for Topshelf and once for my HttpConfiguration.DependencyResolver. This does not seem to be the right way to use Ninject.
Any help or example code related to this specific design would be very helpful.

So I had this same problem and I managed to solve it.
The key to this is to:
Not use the [assembly: OwinStartup(...)] attribute to bootstrap OWIN.
Inject an IKernel using Ninject into the service class being used to configure Topshelf.
Use the Start(StartOptions options, Action<Owin.IAppBuilder> startup) method of the Microsoft.Owin.Hosting.WebApp class to start the self-hosted web-app.
Pass in the injected kernel to the OWIN bootstrap routine via the startup action.
Use the passed-in reference to the kernel in the call to appBuilder.UseNinjectMiddleware(() => kernel); in the OWIN startup routine, rather than appBuilder.UseNinjectMiddleware(CreateKernel);.
Profit.
The complete solution is as follows:
Create a console application solution called BackgroundProcessor.
Add packages listed in the Packages.config listing below to the solution using NuGet.
Add an App.config to the solution using the listing below.
Add each of the code files provided below to the solution; I have provided the full listings because of the lines of code are quite sensitive to the using statements because of heavy use of extension methods by the libraries utilized by the solution.
Compile and run the project.
Test the solution by hitting the URL http://localhost:9000/test on your local machine.
Packages.config
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Microsoft.AspNet.WebApi" version="5.0.0" targetFramework="net45" />
<package id="Microsoft.AspNet.WebApi.Client" version="5.0.0" targetFramework="net45" />
<package id="Microsoft.AspNet.WebApi.Core" version="5.0.0" targetFramework="net45" />
<package id="Microsoft.AspNet.WebApi.Owin" version="5.0.0" targetFramework="net45" />
<package id="Microsoft.AspNet.WebApi.WebHost" version="5.0.0" targetFramework="net45" />
<package id="Microsoft.Owin" version="2.1.0" targetFramework="net45" />
<package id="Microsoft.Owin.Host.HttpListener" version="2.1.0" targetFramework="net45" />
<package id="Microsoft.Owin.Hosting" version="2.1.0" targetFramework="net45" />
<package id="Newtonsoft.Json" version="4.5.11" targetFramework="net45" />
<package id="Ninject" version="3.2.2.0" targetFramework="net45" />
<package id="Ninject.Extensions.ContextPreservation" version="3.2.0.0" targetFramework="net45" />
<package id="Ninject.Extensions.NamedScope" version="3.2.0.0" targetFramework="net45" />
<package id="Ninject.Web.Common" version="3.2.2.0" targetFramework="net45" />
<package id="Ninject.Web.Common.OwinHost" version="3.2.2.0" targetFramework="net45" />
<package id="Ninject.Web.WebApi" version="3.2.0.0" targetFramework="net45" />
<package id="Ninject.Web.WebApi.OwinHost" version="3.2.1.0" targetFramework="net45" />
<package id="Owin" version="1.0" targetFramework="net45" />
<package id="Topshelf" version="3.1.3" targetFramework="net45" />
<package id="Topshelf.Ninject" version="0.3.0.0" targetFramework="net45" />
</packages>
App.config
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
</startup>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="Topshelf" publicKeyToken="b800c4cfcdeea87b" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-3.1.122.0" newVersion="3.1.122.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Ninject" publicKeyToken="c7192dc5380945e7" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-3.2.0.0" newVersion="3.2.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Microsoft.Owin" publicKeyToken="31bf3856ad364e35" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-2.1.0.0" newVersion="2.1.0.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>
Program.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Ninject;
using Topshelf;
using Topshelf.Ninject;
namespace BackgroundProcessor
{
using Modules;
using Services;
public class Program
{
public static int Main(string[] args)
{
var exitCode = HostFactory.Run
(
c =>
{
c.UseNinject(new Module());
c.Service<Service>
(
sc =>
{
sc.ConstructUsingNinject();
sc.WhenStarted((service, hostControl) => service.Start(hostControl));
sc.WhenStopped((service, hostControl) => service.Stop(hostControl));
}
);
c.SetServiceName("BackgroundProcessorSvc");
c.SetDisplayName("Background Processor");
c.SetDescription("Processes things in the background");
c.EnablePauseAndContinue();
c.EnableShutdown();
c.StartAutomaticallyDelayed();
c.RunAsLocalSystem();
}
);
return (int)exitCode;
}
}
}
Modules\Module.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Ninject.Modules;
namespace BackgroundProcessor
{
using Contracts;
using Services;
namespace Modules
{
public class Module : NinjectModule
{
public override void Load()
{
Bind<IService>().To<Service>();
}
}
}
}
Contracts\IService.cs
using System;
namespace BackgroundProcessor
{
namespace Contracts
{
public interface IService
{
bool Start(Topshelf.HostControl hostControl);
bool Stop(Topshelf.HostControl hostControl);
}
}
}
Services\Service.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Owin.Hosting;
using Ninject;
using Topshelf;
namespace BackgroundProcessor
{
using Configs;
using Contracts;
namespace Services
{
public class Service : IService
{
private readonly IKernel kernel;
public Service(IKernel kernel)
: base()
{
this.kernel = kernel;
}
protected IKernel Kernel
{
get
{
return this.kernel;
}
}
protected IDisposable WebAppHolder
{
get;
set;
}
protected int Port
{
get
{
return 9000;
}
}
public bool Start(HostControl hostControl)
{
if (WebAppHolder == null)
{
WebAppHolder = WebApp.Start(new StartOptions { Port = Port }, appBuilder =>
{
new StartupConfig().Configure(appBuilder, Kernel);
});
}
return true;
}
public bool Stop(HostControl hostControl)
{
if (WebAppHolder != null)
{
WebAppHolder.Dispose();
WebAppHolder = null;
}
return true;
}
}
}
}
Configs\StartupConfig.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web.Http;
using Ninject;
using Ninject.Web.Common.OwinHost;
using Ninject.Web.WebApi.OwinHost;
using Owin;
namespace BackgroundProcessor
{
namespace Configs
{
public class StartupConfig
{
public void Configure(IAppBuilder appBuilder, IKernel kernel)
{
var config = new HttpConfiguration();
config.MapHttpAttributeRoutes();
config.MapDefinedRoutes();
appBuilder.UseNinjectMiddleware(() => kernel);
appBuilder.UseNinjectWebApi(config);
}
}
}
}
Configs\RoutesConfig.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Web;
using System.Web.Http;
namespace BackgroundProcessor
{
namespace Configs
{
public static class RoutesConfig
{
public static void MapDefinedRoutes(this HttpConfiguration config)
{
config.Routes.MapHttpRoute
(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new
{
id = RouteParameter.Optional
}
);
}
}
}
}
Controllers\TestController.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
using System.Web;
using System.Web.Http;
namespace BackgroundProcessor
{
namespace Controllers
{
[RoutePrefix("test")]
public class TestController : ApiController
{
[HttpGet]
[Route("")]
public HttpResponseMessage Index()
{
return Request.CreateResponse<string>(HttpStatusCode.OK, "Hello world!");
}
}
}
}

Related

NLog is not sending logs to AWS CloudWatch

I am setting up NLog in my asp net core 2.1 application
But it is not generating the log on AWS, I followed the documentation, I did some tests, I was only able to generate the log.txt on localhost, however for the AWS configuration it is not working. am i doing something wrong?
follow the code:
Here is the configuration NLog
<?xml version="1.0" encoding="utf-8" ?>
<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
throwConfigExceptions="true">
<extensions>
<add assembly="NLog.AWS.Logger" />
</extensions>
<targets>
<target name="aws" type="AWSTarget" logGroup="NLog.ConfigExample" region="us-east-1"/>
<target name="logfile" xsi:type="Console" layout="${callsite} ${message}" />
</targets>
<rules>
<logger name="*" minlevel="Info" writeTo="logfile,aws" />
</rules>
</nlog>
I'm calling it like this:
Program.cs
using Microsoft.AspNetCore;
using Microsoft.AspNetCore.Hosting;
using NLog.Web;
using Microsoft.Extensions.Logging;
using System;
using NLog;
using NLog.Config;
using NLog.Targets;
using NLog.AWS.Logger;
namespace API_Coletor_Status
{
public class Program
{
public static void Main(string[] args)
{
CreateWebHostBuilder(args).Build().Run();
ConfigureNLog();
Logger loggerr = LogManager.GetCurrentClassLogger();
loggerr.Info("Check the AWS Console CloudWatch Logs console in us-east-1");
loggerr.Info("to see messages in the log streams for the");
loggerr.Info("log group NLog.ConfigExample");
}
static void ConfigureNLog()
{
var config = new LoggingConfiguration();
var consoleTarget = new ColoredConsoleTarget();
config.AddTarget("console", consoleTarget);
var awsTarget = new AWSTarget()
{
LogGroup = "NLog.LogPlataforma",
Region = "us-east-1"
};
config.AddTarget("aws", awsTarget);
config.LoggingRules.Add(new LoggingRule("*", NLog.LogLevel.Debug, consoleTarget));
config.LoggingRules.Add(new LoggingRule("*", NLog.LogLevel.Debug, awsTarget));
LogManager.Configuration = config;
}
public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.UseStartup<Startup>()
.ConfigureLogging((hostingContext, logging) =>
{
logging.AddConfiguration(hostingContext.Configuration.GetSection("Logging"));
logging.AddConsole();
logging.AddDebug();
logging.AddEventSourceLogger();
})
.UseNLog();
}
}
Am I doing something wrong?

Why does calling Breeze metadata() return an error with .net core 3.0.100

Until now I've been using Breeze on .net framework. Works great. For a new project I want to switch to .net core 3.0.100 to write the backend software, aka web api.
So this is my first time setup of a .net core web api application with breeze and EF.
Setup per https://github.com/Breeze/northwind-core-ng-demo
.netcore 3.0.100
Breeze .netcore
Breeze persistence EFCore
Entity framework SQLServer
Calling Metadata() on persistencemanager throws an error:
Message [string]:"Method not found: 'System.Type Microsoft.EntityFrameworkCore.Metadata.IProperty.get_ClrType()'."
Detailed error:
Exception has occurred: CLR/System.MissingMethodException
An exception of type 'System.MissingMethodException' occurred in Breeze.Persistence.EFCore.dll but was not handled in user code: 'Method not found: 'System.Type Microsoft.EntityFrameworkCore.Metadata.IProperty.get_ClrType()'.'
at Breeze.Persistence.EFCore.MetadataBuilder.CreateDataProperty(IProperty p)
at Breeze.Persistence.EFCore.MetadataBuilder.<>c__DisplayClass3_0.<CreateMetaType>b__0(IProperty p)
at System.Linq.Enumerable.SelectEnumerableIterator`2.ToList()
at System.Linq.Enumerable.ToList[TSource](IEnumerable`1 source)
at Breeze.Persistence.EFCore.MetadataBuilder.CreateMetaType(IEntityType et, Dictionary`2 dbSetMap)
at Breeze.Persistence.EFCore.MetadataBuilder.<>c__DisplayClass1_0.<GetMetadataFromContext>b__1(IEntityType et)
at System.Linq.Enumerable.WhereSelectEnumerableIterator`2.ToList()
at System.Linq.Enumerable.ToList[TSource](IEnumerable`1 source)
at Breeze.Persistence.EFCore.MetadataBuilder.GetMetadataFromContext(DbContext dbContext)
at Breeze.Persistence.EFCore.MetadataBuilder.BuildFrom(DbContext dbContext)
at Breeze.Persistence.EFCore.EFPersistenceManager`1.BuildJsonMetadata()
at Breeze.Persistence.PersistenceManager.Metadata()
at JobtrackerBOBreezeController.metaData() in /Users/roydecaestecker/Documents/angular-cli-apps/sulo-solution/Sulo.Jobtracker.BO.Api/Controllers/JobtrackerBOBreezeController.cs:line 21
at Microsoft.Extensions.Internal.ObjectMethodExecutor.Execute(Object target, Object[] parameters)
at Microsoft.AspNetCore.Mvc.Infrastructure.ActionMethodExecutor.SyncObjectResultExecutor.Execute(IActionResultTypeMapper mapper, ObjectMethodExecutor executor, Object controller, Object[] arguments)
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.InvokeActionMethodAsync()
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.InvokeNextActionFilterAsync()
Klant model
[Table("klant", Schema="Sulo")]
public class Klant
{
public Klant(){}
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int id { get; set; }
public string naam { get; set; }
}
DBContext
using Microsoft.EntityFrameworkCore;
namespace Sulo.Jobtracker.Model
{
public class SuloJobtrackerContext : DbContext
{
public SuloJobtrackerContext(DbContextOptions options) : base(options) { }
public DbSet<Klant> klanten { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Klant>();
}
}
}
Project file
<?xml version="1.0" encoding="utf-8"?>
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>netcoreapp3.0</TargetFramework>
<UserSecretsId>...</UserSecretsId>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\Sulo.Jobtracker.Model\Sulo.Jobtracker.Model.csproj" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Breeze.AspNetCore.NetCore" Version="1.0.3.3" />
<PackageReference Include="Breeze.Persistence.EFCore" Version="1.0.3.3" />
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="3.0.0" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="3.0.0" />
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="3.0.0" />
</ItemGroup>
</Project>
Breeze controller
using Microsoft.AspNetCore.Mvc;
using Newtonsoft.Json.Linq;
using System.Linq;
using Breeze.Persistence;
using Breeze.AspNetCore;
using Microsoft.AspNetCore.Authorization;
[Breeze.AspNetCore.BreezeQueryFilter]
[Route("api/v1/[controller]/[action]")]
public class JobtrackerBOBreezeController {
private SuloJobtrackerPersistenceManager persistenceManager;
public JobtrackerBOBreezeController(SuloJobtrackerContext dbcontext){
persistenceManager = new SuloJobtrackerPersistenceManager(dbcontext);
}
[HttpGet, HttpOptions]
public string metaData() {
return persistenceManager.Metadata();
}
[HttpGet, HttpOptions]
[Authorize]
public IQueryable<Klant> klanten() {
return persistenceManager.Context.klanten;
}
}
calling klanten() method works just fine
Breeze support of .NET Core 3 has been released.
And the https://github.com/Breeze/northwind-demo is updated.

WebApi PUT does not work when the method has variables MVC 4

I'm new to WebApi and the tutorial was going well. I got Get, Get with variables, Post, and Delete to work, but I can't seem to get Put to work. Well, if I remove all the variables from the method the in the controller, it actually goes into the method, but that's pretty useless. Has anyone come across this before that knows how to fix it?
PUT Url sent to Postman:
http://localhost:60679/api/incident/1234
Preview:
PUT /api/incident/1234 HTTP/1.1
Host: localhost:60679
Cache-Control: no-cache
Error Message:
{"Message":"No HTTP resource was found that matches the request URI
'http://localhost:60679/api/incident/1234'.","MessageDetail":"No action was found on the
controller 'Incident' that matches the request."}
Controller:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Web.Http;
using WebApiTest.AppLogic;
using WebApiTest.Data.Core;
namespace WebApiTest.WebApi.Controllers
{
public class IncidentController : ApiController
{
// GET api/values
public IEnumerable<Incident> Get()
{
using (EntityDemoEntities context = new EntityDemoEntities())
{
return context.Incidents.ToList<Incident>();
}
}
// GET api/values/5
public Incident Get(string id)
{
using (EntityDemoEntities context = new EntityDemoEntities())
{
Guid tempGuid = new Guid(id);
return context.Incidents.SingleOrDefault(i => i.IncidentId == tempGuid);
}
}
// PUT api/values/5
[HttpPut]
public void Put(string guid)
{
HttpResponseMessage result = new HttpResponseMessage();
try
{
if (ModelState.IsValid)
{
//Do something
}
else
{
result = Request.CreateResponse(HttpStatusCode.InternalServerError, "Invalid Model");
}
}
catch (Exception ex)
{
result = Request.CreateResponse(HttpStatusCode.InternalServerError, String.Format("{1}{0}{2}{0}{3}{0}{4}", Environment.NewLine, ex.Message, ex.StackTrace, ex.InnerException == null ? String.Empty : ex.InnerException.Message, ex.InnerException == null ? String.Empty : ex.InnerException.StackTrace));
}
}
}
}
WebApiConfig
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
}
}
Web.config
<system.webServer>
<validation validateIntegratedModeConfiguration="false" />
<handlers>
<remove name ="WebDAVModule"/>
<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>
<modules runAllManagedModulesForAllRequests="true">
<remove name='WebDAVModule'/>
</modules>
Change your action to Put(string id) or Put([FromUri(Name="id")]string guid)

Ninject.Web.Common No parameterless constructor defined for this object

I used Nuget to install the Ninject.Web.Common reference. I use it with ASP.net Web API (APIController) with no problem, but I hit problem when using the ASP.net MVC 4(Controller).
The error:
No parameterless constructor defined for this object.
NinjectWebCommon.cs:
[assembly: WebActivator.PreApplicationStartMethod(typeof(CarsApp.Web.App_Start.NinjectWebCommon), "Start")]
[assembly: WebActivator.ApplicationShutdownMethodAttribute(typeof(CarsApp.Web.App_Start.NinjectWebCommon), "Stop")]
namespace CarsApp.Web.App_Start
{
using System;
using System.Web;
using Microsoft.Web.Infrastructure.DynamicModuleHelper;
using Ninject;
using Ninject.Web.Common;
//using App.WebUI.Infrastructure;
using App.Domain.Abstract;
using App.Domain.Concreate;
using System.Web.Http;
using App.Web.Infrastructure;
public static class NinjectWebCommon
{
private static readonly Bootstrapper bootstrapper = new Bootstrapper();
/// <summary>
/// Starts the application
/// </summary>
public static void Start()
{
DynamicModuleUtility.RegisterModule(typeof(OnePerRequestHttpModule));
DynamicModuleUtility.RegisterModule(typeof(NinjectHttpModule));
bootstrapper.Initialize(CreateKernel);
}
/// <summary>
/// Stops the application.
/// </summary>
public static void Stop()
{
bootstrapper.ShutDown();
}
/// <summary>
/// Creates the kernel that will manage your application.
/// </summary>
/// <returns>The created kernel.</returns>
private static IKernel CreateKernel()
{
var kernel = new StandardKernel();
kernel.Bind<Func<IKernel>>().ToMethod(ctx => () => new Bootstrapper().Kernel);
kernel.Bind<IHttpModule>().To<HttpApplicationInitializationHttpModule>();
// Install our Ninject-based IDependencyResolver into the Web API config
GlobalConfiguration.Configuration.DependencyResolver = new NinjectDependencyResolver(kernel);
RegisterServices(kernel);
return kernel;
}
/// <summary>
/// Load your modules or register your services here!
/// </summary>
/// <param name="kernel">The kernel.</param>
private static void RegisterServices(IKernel kernel)
{
kernel.Bind<IMembershipRepository>().To<EFMembershipRepository>();
kernel.Bind<IBranchRepository>().To<EFBranchRepository>();
}
}
}
I am using MVC5 and using Install-Package Ninject.MVC5 solved my issue.
try with Install-Package Ninject.MVC3
Check if in your Web.config you have two lines for MVC versioning, I had something like:
<dependentAssembly>
<assemblyIdentity name="System.Web.Mvc" publicKeyToken="31bf3856ad364e35" />
<bindingRedirect oldVersion="0.0.0.0-4.0.0.0" newVersion="4.0.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Web.Mvc" publicKeyToken="31bf3856ad364e35" />
<bindingRedirect oldVersion="4.0.0.0-4.0.0.1" newVersion="4.0.0.1" />
</dependentAssembly>
If you do then replace them with one line like, to redirect to highest version that you are using in my case it's 4.0.0.1:
<dependentAssembly>
<assemblyIdentity name="System.Web.Mvc" publicKeyToken="31bf3856ad364e35" />
<bindingRedirect oldVersion="0.0.0.0-4.0.0.1" newVersion="4.0.0.1" />
</dependentAssembly>
This did it for me.

NHibernate mapping error SQL Server 2008 Express

I tried an example from NHibernate in Action book and when I try to run the app, it throws an exception saying "Could not compile the mapping document:
HelloNHibernate.Employee.hbm.xml"
Below is my code,
Employee.hbm.xml
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" auto-import="true">
<class name="HelloNHibernate.Employee, HelloNHibernate" lazy="false" table="Employee">
<id name="id" access="field">
<generator class="native"/>
</id>
<property name="name" access="field" column="name"/>
<many-to-one access="field" name="manager" column="manager" cascade="all"/>
</class>
</hibernate-mapping>
Program.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using NHibernate;
using System.Reflection;
using NHibernate.Cfg;
namespace HelloNHibernate
{
class Program
{
static void Main(string[] args)
{
CreateEmployeeAndSaveToDatabase();
UpdateTobinAndAssignPierreHenriAsManager();
LoadEmployeesFromDatabase();
Console.WriteLine("Press any key to exit...");
Console.ReadKey();
}
static void CreateEmployeeAndSaveToDatabase()
{
Employee tobin = new Employee();
tobin.name = "Tobin Harris";
using (ISession session = OpenSession())
{
using (ITransaction transaction = session.BeginTransaction())
{
session.Save(tobin);
transaction.Commit();
}
Console.WriteLine("Saved Tobin to the database");
}
}
static ISession OpenSession()
{
if (factory == null)
{
Configuration c = new Configuration();
c.AddAssembly(Assembly.GetCallingAssembly());
factory = c.BuildSessionFactory();
}
return factory.OpenSession();
}
static void LoadEmployeesFromDatabase()
{
using (ISession session = OpenSession())
{
IQuery query = session.CreateQuery("from Employee as emp order by emp.name asc");
IList<Employee> foundEmployees = query.List<Employee>();
Console.WriteLine("\n{0} employees found:", foundEmployees.Count);
foreach (Employee employee in foundEmployees)
Console.WriteLine(employee.SayHello());
}
}
static void UpdateTobinAndAssignPierreHenriAsManager()
{
using (ISession session = OpenSession())
{
using (ITransaction transaction = session.BeginTransaction())
{
IQuery q = session.CreateQuery("from Employee where name='Tobin Harris'");
Employee tobin = q.List<Employee>()[0];
tobin.name = "Tobin David Harris";
Employee pierreHenri = new Employee();
pierreHenri.name = "Pierre Henri Kuate";
tobin.manager = pierreHenri;
transaction.Commit();
Console.WriteLine("Updated Tobin and added Pierre Henri");
}
}
}
static ISessionFactory factory;
}
}
Employee.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace HelloNHibernate
{
class Employee
{
public int id;
public string name;
public Employee manager;
public string SayHello()
{
return string.Format("'Hello World!', said {0}.", name);
}
}
}
App.config
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<section name="nhibernate" type="System.Configuration.NameValueSectionHandler, System, Version=1.0.3300.0, Culture=neutral
PublicKeyToken=b77a5c561934e089"/>
</configSections>
<nhibernate>
<add key="hibernate.show_sql" value="false"/>
<add key="hibernate.connection.provider" value="NHibernate.Connection.DriverConnectionProvider"/>
<add key="hibernate.dialect" value="NHibernate.Dialect.MsSql2005Dialect"/>
<add key="hibernate.connection.driver_class" value="NHibernate.Driver.SqlClientDriver"/>
<add key="hibernate.connection.connection_string" value="Server=(local)\SQLEXPRESS; Database=HelloNHibernate;Integrated Security=SSPI;"/>
</nhibernate>
</configuration>
Let's open the Matryoshka doll a bit further, and solve the other problem:
In this line:
<section name="nhibernate" type="System.Configuration.NameValueSectionHandler, System, Version=1.0.3300.0, Culture=neutral
PublicKeyToken=b77a5c561934e089"/>
you're missing a comma between "neutral" and "PublicKeyToken".
Give that a try.
Do you have a manager class and mapping defined? The
<many-to-one access="field" name="manager" column="manager" cascade="all"/>
line is looking for one. If the "manager" field is supposed to be an Employee, then you probably want:
<many-to-one access="field" name="manager" column="manager" class="HelloNHibernate.Employee, HelloNHibernate" cascade="all"/>
I think I see the problem now. The problem appears to be in this line:
<add key="hibernate.connection.connection_string" value="SQL2008EXPRESS" Database="HelloNHibernate;Integrated Security=SSPI;User Id=SQL2008"/>
The connection string is malformed, and it's throwing off the XML parser. Since the "value" attribute ends early, the XML parser thinks "Database=" is another XML attribute, but it's not one it recognizes, so it chokes. The solution is to fix the connection string.
The line should probably read:
<add key="hibernate.connection.connection_string" value="Server=(local)\SQLEXPRESS; Database=HelloNHibernate;Integrated Security=SSPI;"/>
This is assuming you're using Windows authentication; given that this is a learning project, that's probably the best way to go. If you're using SQL Server authentication, use this line instead:
<add key="hibernate.connection.connection_string" value="Server=(local)\SQLEXPRESS; Database=HelloNHibernate; User Id=theusername; Password=thepassword"/>
An aside: I don't think NHibernate 1.2.1GA has a SQL Server 2008 dialect. Instead, use NHibernate.Dialect.MsSql2005Dialect.