NserviceBus property injection - inversion-of-control

I am attempting to inject an object into my saga. Using the following endpoint, when the message arrives at the handle method of the saga the property is null.
The endpoint:
public class EndpointConfig : IConfigureThisEndpoint, AsA_Server, IWantToRunAtStartup
{
public void Run()
{
IOrderRepository orderRepository = new OrderRepository();
Configure.Instance.Configurer.ConfigureProperty<CreateOrderSaga>(x => x.OrderRepository, orderRepository);
}
// stop method removed
}
The app.config
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<section name="MsmqTransportConfig" type="NServiceBus.Config.MsmqTransportConfig, NServiceBus.Core" />
<section name="UnicastBusConfig" type="NServiceBus.Config.UnicastBusConfig, NServiceBus.Core" />
</configSections>
<MsmqTransportConfig
InputQueue="Fulfilment.CreateOrder.OrderRecievedMessage"
ErrorQueue="error"
NumberOfWorkerThreads="1"
MaxRetries="3"
/>
<UnicastBusConfig
DistributorControlAddress=""
DistributorDataAddress="">
<MessageEndpointMappings>
<add Messages="NServiceBus.Saga.TimeoutMessage, NServiceBus" Endpoint="timeoutmanager" />
</MessageEndpointMappings>
</UnicastBusConfig>
</configuration>
and my Saga accepting messages as follows
public class CreateOrderSaga : Saga<CreateOrderSagaData>,
IAmStartedByMessages<OrderRecievedMessage>,
IHandleMessages<OrderCompletedMessage>,
IHandleMessages<OrderCancelledMessage>
{
public IOrderRepository OrderRepository { get; set; }
public void Handle(OrderRecievedMessage message)
{
var order = new Order();
OrderRepository.SaveOrder(order);
}
a null reference expection will be thrown when attempting to call SaveOrder(). Have i configured the dependency injection correctly?

NServiceBus will automatically do property injection for you so you only need to register your repository with the container:
In your Init() method: (Implement IWantCustomInitialization on a separate class)
Configure.Instance.ConfigureComponent< OrderRepository >([The lifecycle you want]);
IWantToRunAtStartup is not meant for configuration tasks (use IWantCustomInitialization instead)

Related

ODP.NET and EF6 configuration on ASP.NET Core targeting .NET 4.7.2

I can't get Entity Framework to use the Oracle Provider (ODP.NET) with my project.
Setup:
ASP.NET Core MVC 2.1 targeting .NET Framework 4.7.2
EntityFramework 6.2
ODP.NET 18.3 (Oracle.ManagedDataAccess and Oracle.ManagedDataAccess.EntityFramework)
Although I'd prefer to use EF Core, I can't because Oracle isn't supporting EF Core yet, just .NET Core.
The errors I'm receiving indicate that the application is trying to use the SQL Server driver.
I can't find an example online for my scenario. Either its MVC5 with EF6/ODP.NET, or .NET Core examples with Oracle that don't have EF.
My assumption is the problem lies in that in MVC5 configures it through web.config/app.config. I'm assuming I need to configure Oracle in start.cs but need the right syntax.
What I have coded for the Context class:
public class MainContext : DbContext
{
public MainContext(string connectionString) : base(connectionString)
{
Database.SetInitializer<MainContext>(null);
}
public virtual DbSet<ApplicationSetting> ApplicationSettings { get; set; }
}
Then I created a factory:
public class MainContextFactory : IDbContextFactory<MainContext>
{
private readonly string _connectionString;
public MainContextFactory(string connectionString)
{
_connectionString = connectionString;
}
public MainContext Create()
{
return new MainContext(_connectionString);
}
}
In Startup.cs I have:
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc()
.SetCompatibilityVersion(CompatibilityVersion.Version_2_1)
services.AddTransient<IDbContextFactory<MainContext>>(d =>
new MainContextFactory(Configuration["ConnectionStrings:Primary"]));
I call this from my Repository project (targets .NET 4.7.2) and contains the MainContext:
public class ApplicationSettingRepository : BaseDbRepository, IApplicationSettingRepository
{
private readonly ILogger<ApplicationSettingRepository> _logger;
public ApplicationSettingRepository(ILogger<ApplicationSettingRepository> logger,
IUserContext userContext,
IDbContextFactory<MainContext> dbContextFactory) : base(userContext, dbContextFactory)
{
_logger = logger;
}
/// <summary>
/// Get All Application Settings
/// </summary>
public async Task<List<IApplicationSetting>> GetAllAsync()
{
var list = new List<IApplicationSetting>();
using (var db = _contextFactory.Create())
{
list.AddRange(await db.ApplicationSettings.ToListAsync());
}
return list;
}
which calls a base repository class:
public abstract class BaseDbRepository : IBaseRepository
{
protected IDbContextFactory<MainContext> _contextFactory;
public IUserContext UserContext { get; set; }
protected BaseDbRepository(IUserContext userContext, IDbContextFactory<MainContext> dbContextFactory)
{
UserContext = userContext;
_contextFactory = dbContextFactory;
}
}
Questions:
What do I need to update or add to make it call the ODP.NET provider?
Is there a better approach to config?
To associate the Oracle Provider:
Update add.config with the values that were in web.config from MVC5:
<configuration>
<configSections>
<section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
<section name="oracle.manageddataaccess.client" type="OracleInternal.Common.ODPMSectionHandler, Oracle.ManagedDataAccess, Version=4.122.18.3, Culture=neutral, PublicKeyToken=89b483f429c47342" />
</configSections>
<runtime>
<gcServer enabled="true"/>
</runtime>
<entityFramework>
<providers>
<provider invariantName="Oracle.ManagedDataAccess.Client" type="Oracle.ManagedDataAccess.EntityFramework.EFOracleProviderServices, Oracle.ManagedDataAccess.EntityFramework, Version=6.122.18.3, Culture=neutral, PublicKeyToken=89b483f429c47342" />
</providers>
</entityFramework>
<system.data>
<DbProviderFactories>
<remove invariant="Oracle.ManagedDataAccess.Client" />
<add name="ODP.NET, Managed Driver" invariant="Oracle.ManagedDataAccess.Client" description="Oracle Data Provider for .NET, Managed Driver" type="Oracle.ManagedDataAccess.Client.OracleClientFactory, Oracle.ManagedDataAccess, Version=4.122.18.3, Culture=neutral, PublicKeyToken=89b483f429c47342" />
</DbProviderFactories>
</system.data>
<oracle.manageddataaccess.client>
<version number="*">
<dataSources></dataSources>
</version>
</oracle.manageddataaccess.client>
</configuration>
Then add after the services.AddMvc() in startup.cs:
services.AddScoped(provider =>
{
return new OracleDbContext(Configuration["ConnectionString"]);
});
Credit to Tony Sneed Post.

WCF Entity Framework 6 SQL Provider not found

i write a client server application. If the server request data from EF6 there is no problem and no exception. If the client asks over WFC data from the EF6 there is a provider not found exception. My database is a MS SQL Server 2017. CLient and Server have the same debug folder.
Exception over WFC:
"No Entity Framework provider found for the ADO.NET provider with invariant name 'System.Data.SqlClient'. 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."
Server App.config
<?xml version="1.0" encoding="utf-8"?>
Integrated
Security=True;Database=PeddTax;MultipleActiveResultSets=True"/>
<system.web>
<compilation debug="true" />
</system.web>
<system.serviceModel>
<services>
<service name="PeddTaxServer.Communication.UserService">
<endpoint address="http://localhost:6060/wcf/UserService" binding="basicHttpBinding"
bindingConfiguration="" name="UserServiceEndpoint" contract="PeddTax.Communication.Interfaces.IUserService" />
</service>
</services>
</system.serviceModel>
Client App.config
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7.1" />
</startup>
<system.serviceModel>
<client>
<endpoint address="http://localhost:6060/wcf/UserService"
binding="basicHttpBinding" bindingConfiguration=""
contract="PeddTax.Communication.Interfaces.IUserService"
name="UserServiceEndpoint" kind="" endpointConfiguration="" />
</client>
</system.serviceModel>
<system.web>
<compilation debug="true" />
</system.web>
</configuration>
IUserInterface for WFC
[ServiceContract]
public interface IUserService
{
[OperationContract]
void AddUser(User user);
[OperationContract]
void UpdateUser(User user);
[OperationContract]
User GetUser(Guid id);
[OperationContract]
List<User> GetUsers();
[OperationContract]
void DeleteUser(User user);
}
UserService for WFC
public class UserService : IUserService, IService
{
UserRepository userRep = new UserRepository();
public void AddUser(User user)
{
userRep.Add(user);
userRep.Save();
}
public void DeleteUser(User user)
{
userRep.Delete(user);
userRep.Save();
}
public User GetUser(Guid id)
{
return userRep.GetSingle(id);
}
public List<User> GetUsers()
{
return userRep.GetAll().ToList();
}
public void UpdateUser(User user)
{
userRep.Edit(user);
userRep.Save();
}
}
In the userRepository there is this method
public IQueryable<T> GetAll()
{
IQueryable<T> query = entities.Set<T>();
return query;
}
1) Turn on all exceptions in Visual Studio if you want to see the place where it is thrown.
2) Re-install EF on a correct project as suggested here

How to get Entity Framework to read my app.config file in Unit Test project

I'm trying to create a database for my entity framework tests, but I can't get it to read my configuration files correctly. My app.config file in test project looks like this:
<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=5.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
</configSections>
<connectionStrings>
<add name="TestConnection"
connectionString= "Data Source=(LocalDb)\v11.0;
Initial Catalog=LocabalTestDB;
Integrated Security=SSPI;
MultipleActiveResultSets=true"
providerName="System.Data.SqlClient" />
</connectionStrings>
<entityFramework>
<defaultConnectionFactory type="System.Data.Entity.Infrastructure.LocalDbConnectionFactory, EntityFramework">
<parameters>
<parameter value="v11.0" />
</parameters>
</defaultConnectionFactory>
</entityFramework>
....
</configuration>
However, it is not creating a database called LocabalTestDB, it is creating a database called Locabal.Model.LocabalSqlContext, and this is what the connection string looks like:
"Data Source=(localdb)\v11.0;Initial Catalog=Locabal.Model.LocabalSqlContext;Integrated Security=True;MultipleActiveResultSets=True;Application Name=EntityFrameworkMUE"
This is what the DB creation/seed code looks like (it runs once before I run any tests):
[AssemblyInitialize]
public static void Init(TestContext c)
{
Database.SetInitializer<LocabalSqlContext>(null);
using (var db = new LocabalSqlContext())
{
if (!db.Database.Exists())
{
db.Database.Create();
Locabal.Model.Migrations.Configuration.SeedData(db);
}
}
}
From this MSDN article, you have to set the name in connection string to the name of your DbContext, then the "Initial Catalog" parameter will be your DB name. For example:
<connectionStrings>
<add name="LocabalSqlContext"
connectionString= "Data Source=(LocalDb)\v11.0;
Initial Catalog=LocabalTestDB;
Integrated Security=SSPI;
MultipleActiveResultSets=true"
providerName="System.Data.SqlClient" />
</connectionStrings>
Then you can set your test class like this:
public class TestDBSeeder : DropCreateDatabaseIfModelChanges<LocabalSqlContext>
{
protected override void Seed(LocabalSqlContext context)
{
Locabal.Model.Migrations.Configuration.SeedData(context);
base.Seed(context);
}
}
[TestClass]
public class LocabalSqlContextIntegrationBaseTest
{
protected TransactionScope Transaction { get; set; }
[AssemblyInitialize]
public static void Init(TestContext c)
{
Database.SetInitializer<LocabalSqlContext>(new TestDBSeeder());
if (!Database.Exists("LocabalSqlContext"))
{
using (var db = new LocabalSqlContext())
{
db.Database.Initialize(true);
}
}
}
[TestInitialize]
public virtual void StartDbTransaction()
{
Transaction = new TransactionScope();
}
[TestCleanup]
public virtual void EndDbTransaction()
{
Transaction.Dispose();
}
}

Remove project.serviceclass name from servicestack url

I'm playing around with some of the ServiceStack demos and example code and I'm trying to see if there is a way to remove the need to have the project.serviceclass name in the url. I used the nuget packages and created a ASP.NET MVC application called MvcMovieApp and created a SS service called MovieService.
[Route("/Movie")]
[Route("/Movie/{Name}")]
public class Movie
{
public long Id { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public string Genre { get; set; }
}
public class MovieResponse
{
public string Result { get; set; }
}
public class MovieService : Service
{
public object Any(Movie request)
{
return new MovieResponse { Result = "The best Movie is " + request.Name };
}
}
So to get the response I have to request:
localhost/api/MvcMovieApp.MovieService/Movie/MyMovie
but I want to be able to make the request
localhost/api/Movie/MyMovie
Is there a way to do this?
Update
<httpHandlers>
<add path="api*" type="ServiceStack.WebHost.Endpoints.ServiceStackHttpHandlerFactory, ServiceStack" verb="*" />
</httpHandlers>
<location path="api">
<system.web>
<httpHandlers>
<add path="*" type="ServiceStack.WebHost.Endpoints.ServiceStackHttpHandlerFactory, ServiceStack" verb="*" />
</httpHandlers>
</system.web>
<!-- Required for IIS 7.0 -->
<system.webServer>
<modules runAllManagedModulesForAllRequests="true" />
<validation validateIntegratedModeConfiguration="false" />
<handlers>
<add path="*" name="ServiceStack.Factory" type="ServiceStack.WebHost.Endpoints.ServiceStackHttpHandlerFactory, ServiceStack" verb="*" preCondition="integratedMode" resourceType="Unspecified" allowPathInfo="true" />
</handlers>
</system.webServer>
</location>
Update 2:
I was able to get it to work kind of. I was trying to integrate ServiceStack in with an MVC application. So my Application_Start has the following:
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
// RouteConfig.RegisterRoutes(RouteTable.Routes);
}
Commenting out the MVC RouteConfig fixed the problem and lets me call the ServiceStack apis properly. Here's the RegisterRoutes method. I have the line so that MVC is supposed to ignore everything going to API.
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
//routes.MapHttpRoute(
// name: "DefaultApi",
// routeTemplate: "api/{controller}/{id}",
// defaults: new { id = RouteParameter.Optional }
//);
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
routes.IgnoreRoute("api/{*pathInfo}");
routes.IgnoreRoute("{*favicon}", new { favicon = #"(.*/)?favicon.ico(/.*)?" }); //Prevent exceptions for favicon
}
Any ideas what I've done wrong? Thanks
The httpHandlers section can only appear once per config file. Also you don't need to to include path=api* in the httpHandler when it is a sub item of the location.
Use only this for your config:
<location path="api">
<system.web>
<httpHandlers>
<add path="*" type="ServiceStack.WebHost.Endpoints.ServiceStackHttpHandlerFactory, ServiceStack" verb="*" />
</httpHandlers>
</system.web>
<!-- Required for IIS 7.0 -->
<system.webServer>
<modules runAllManagedModulesForAllRequests="true" />
<validation validateIntegratedModeConfiguration="false" />
<handlers>
<add path="*" name="ServiceStack.Factory" type="ServiceStack.WebHost.Endpoints.ServiceStackHttpHandlerFactory, ServiceStack" verb="*" preCondition="integratedMode" resourceType="Unspecified" allowPathInfo="true" />
</handlers>
</system.webServer>
</location>

Unable to instantiate Action, signupFormAction, defined for 'signupForm' in namespace '/'signupFormAction. ClassNotFoundException: signupFormAction

Been trying to setup a Struts2 + Sprint + Hibernate basic framework and was working on creating a sample application. Everything configured and the stack doesnt through any error/exception while starting tomcat. Even when I run the action it doesnt throw any Exception, but on the browser it throws the following stack
Unable to instantiate Action, signupFormAction, defined for 'signupForm' in namespace '/'signupFormAction
com.opensymphony.xwork2.DefaultActionInvocation.createAction(DefaultActionInvocation.java:318)
com.opensymphony.xwork2.DefaultActionInvocation.init(DefaultActionInvocation.java:399)
com.opensymphony.xwork2.DefaultActionProxy.prepare(DefaultActionProxy.java:198)
org.apache.struts2.impl.StrutsActionProxy.prepare(StrutsActionProxy.java:61)
org.apache.struts2.impl.StrutsActionProxyFactory.createActionProxy(StrutsActionProxyFactory.java:39)
com.opensymphony.xwork2.DefaultActionProxyFactory.createActionProxy(DefaultActionProxyFactory.java:58)
org.apache.struts2.dispatcher.Dispatcher.serviceAction(Dispatcher.java:475)
org.apache.struts2.dispatcher.ng.ExecuteOperations.executeAction(ExecuteOperations.java:77)
org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter.doFilter(StrutsPrepareAndExecuteFilter.java:91)
root cause
java.lang.ClassNotFoundException: signupFormAction
org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1645)
org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1491)
com.opensymphony.xwork2.util.ClassLoaderUtil.loadClass(ClassLoaderUtil.java:157)
com.opensymphony.xwork2.ObjectFactory.getClassInstance(ObjectFactory.java:107)
com.opensymphony.xwork2.spring.SpringObjectFactory.getClassInstance(SpringObjectFactory.java:223)
com.opensymphony.xwork2.spring.SpringObjectFactory.buildBean(SpringObjectFactory.java:143)
com.opensymphony.xwork2.ObjectFactory.buildBean(ObjectFactory.java:150)
com.opensymphony.xwork2.ObjectFactory.buildAction(ObjectFactory.java:120)
com.opensymphony.xwork2.DefaultActionInvocation.createAction(DefaultActionInvocation.java:299)
com.opensymphony.xwork2.DefaultActionInvocation.init(DefaultActionInvocation.java:399)
com.opensymphony.xwork2.DefaultActionProxy.prepare(DefaultActionProxy.java:198)
org.apache.struts2.impl.StrutsActionProxy.prepare(StrutsActionProxy.java:61)
org.apache.struts2.impl.StrutsActionProxyFactory.createActionProxy(StrutsActionProxyFactory.java:39)
com.opensymphony.xwork2.DefaultActionProxyFactory.createActionProxy(DefaultActionProxyFactory.java:58)
org.apache.struts2.dispatcher.Dispatcher.serviceAction(Dispatcher.java:475)
org.apache.struts2.dispatcher.ng.ExecuteOperations.executeAction(ExecuteOperations.java:77)
org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter.doFilter(StrutsPrepareAndExecuteFilter.java:91)
My struts.xml
<struts>
<!-- <constant name="struts.enable.DynamicMethodInvocation" value="false" />-->
<constant name="struts.devMode" value="false" />
<constant name="struts.custom.i18n.resources" value="ApplicationResources" />
<package name="default" extends="struts-default" namespace="/">
<action name="login" class="loginAction">
<result name="success">welcome.jsp</result>
<result name="error">login.jsp</result>
</action>
<action name="signup" class="registerAction" method="add">
<result name="success">welcome.jsp</result>
<result name="error">login.jsp</result>
</action>
<action name="signupForm" class="signupFormAction">
<result name="input">registerForm.jsp</result>
<result name="error">login.jsp</result>
</action>
</package>
</struts>
My SpringBeans.xml
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
<!-- Database Configuration -->
<import resource="config/spring/DataSource.xml" />
<import resource="config/spring/HibernateSessionFactory.xml" />
<!-- Beans Declaration -->
<import resource="com/srisris/khiraya/spring/register.xml" />
<import resource="com/srisris/khiraya/spring/login.xml" />
</beans>
My register.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
<!-- <bean id="ownerService" class="com.srisris.khiraya.service.OwnerServiceImpl">-->
<!-- <property name="ownerDAO" ref="ownerDAO" />-->
<!-- </bean>-->
<bean id="signupForm" class="com.srisris.khiraya.action.RegisterAction"/>
<!-- <bean id="registerAction" class="com.srisris.khiraya.action.RegisterAction">-->
<!-- <property name="ownerService" ref="ownerService" /> -->
<!-- </bean>-->
<!-- <bean id="ownerDAO" class="com.srisris.khiraya.dao.OwnerDAOImpl" >-->
<!-- <property name="sessionFactory" ref="sessionFactory" />-->
<!-- </bean>-->
</beans>
My Action Class
package com.srisris.khiraya.action;
import com.opensymphony.xwork2.ActionSupport;
import com.opensymphony.xwork2.ModelDriven;
import com.srisris.khiraya.dao.hibernate.Owner;
import com.srisris.khiraya.service.OwnerService;
#SuppressWarnings("rawtypes")
public class RegisterAction extends ActionSupport implements ModelDriven{
private static final long serialVersionUID = 6521996078347478542L;
private String ownerFirstName;
private String ownerLastName;
private String username;
private String password;
private String ownerPhone;
private String ownerEmail;
private OwnerService ownerService;
Owner owner = new Owner();
public void setOwnerService(OwnerService ownerService) {
this.ownerService = ownerService;
}
public String add() {
owner.setOwnerFirstName(ownerFirstName);
owner.setOwnerLastName(ownerLastName);
owner.setOwnerPassword(password);
owner.setOwnerPhone(ownerPhone);
owner.setOwnerEmail(ownerEmail);
ownerService.save(owner);
return SUCCESS;
}
public String execute() {
return INPUT;
}
public String getOwnerFirstName() {
return ownerFirstName;
}
public void setOwnerFirstName(String ownerFirstName) {
this.ownerFirstName = ownerFirstName;
}
public String getOwnerLastName() {
return ownerLastName;
}
public void setOwnerLastName(String ownerLastName) {
this.ownerLastName = ownerLastName;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getOwnerPhone() {
return ownerPhone;
}
public void setOwnerPhone(String ownerPhone) {
this.ownerPhone = ownerPhone;
}
public String getOwnerEmail() {
return ownerEmail;
}
public void setOwnerEmail(String ownerEmail) {
this.ownerEmail = ownerEmail;
}
public Object getModel() {
return owner;
}
}
I made a trivial mistake which costed me hours of pain. Silly me the problem was that my class name in struts.xml and id in register.xml were not matching and hence the issue.