I have been reviewing the official documentation, and use Automapper with Ninject, SimpleInjector, etc. which seems good to me.
I would like some example of how to register the profile with Unity container. (MVC5 and WebApi)
public class MyProfile : Profile
{
public MyProfile()
{
CreateMap<someDto, someEntity>();
}
}
Related
I have a development version of Acumatica running locally, and a QA version of Acumatica in the cloud.
I wrote c# program integrating with Acumatica through SOAP. I created WSDL file for Acumatica instance running locally at http://localhost/AcumaticaERP. Now I need to make the program to connect with Acumatica production instance in the cloud. soapClient.Login method does not have Acumatica URL as a parameter.
How do I allow users to dynamically chose an instance of Acumatica to use from within my program?
I would first suggest to look into the REST API since generally that's the recommended integration API to use.
Regarding dynamically changing the endpoint (i.e. Acumatica instance), note that the DefaultSoapClient has a number of overloaded constructors.
There is one where you can specify the endpointConfigurationName (see below). This would mean that your URL should be in your web.config/appsettings of the client application as explained in more detail here: https://help-2020r1.acumatica.com/(W(1))/Help?ScreenId=ShowWiki&pageid=37613e5f-7a72-4dec-b5d9-2525951e99cf
public partial class DefaultSoapClient : System.ServiceModel.ClientBase<ConsoleApp2.ServiceReference1.DefaultSoap>, ConsoleApp2.ServiceReference1.DefaultSoap {
public DefaultSoapClient() {
}
public DefaultSoapClient(string endpointConfigurationName) :
base(endpointConfigurationName) {
}
public DefaultSoapClient(string endpointConfigurationName, string remoteAddress) :
base(endpointConfigurationName, remoteAddress) {
}
public DefaultSoapClient(string endpointConfigurationName, System.ServiceModel.EndpointAddress remoteAddress) :
base(endpointConfigurationName, remoteAddress) {
}
public DefaultSoapClient(System.ServiceModel.Channels.Binding binding, System.ServiceModel.EndpointAddress remoteAddress) :
base(binding, remoteAddress) {
}
In case using configuration files will not work for you, you can refer to this example whereby it is done programmatically:
https://asiablog.acumatica.com/2019/01/dynamic-api-endpoint-url.html
ServiceStack uses a dialect of Funq (no support for metadata), where Kephas uses one of MEF/Autofac (requires metadata support). My question has two parts:
How to make ServiceStack and Kephas use one DI container, if this is possible?
Depending on the answer above: how to make ServiceStack services (like IClientCache) available to Kephas components, knowing that such services may not be annotated with [AppServiceContract]?
You can make ASP.NET and Kephas use one container by choosing to work with Autofac. However, as #mythz pointed out, you will need to provide the Autofac IoC Adapter to the ServiceStack. I don't think you will have any problems with ASP.NET in doing so, as Autofac is the first recommendation of the ASP.NET Core team.
For ASP.NET Core, reference the Kephas.AspNetCore package and inherit from the StartupBase class if you need to be all setup. However, if you need to be in control, have a look at https://github.com/kephas-software/kephas/blob/master/src/Kephas.AspNetCore/StartupBase.cs and write your own Startup class. Another resource that you might find useful is the Kephas.ServiceStack integration package.
Then, additionally to annotating service contracts and service implementations, Kephas allows you to provide service definitions by implementing the IAppServiceInfoProvider interface. These classes are automatically discovered, so this is pretty much everything you have to do.
public class ServiceStackAppServiceInfoProvider : IAppServiceInfoProvider
{
public IEnumerable<(Type contractType, IAppServiceInfo appServiceInfo)> GetAppServiceInfos(IList<Type> candidateTypes, ICompositionRegistrationContext registrationContext)
{
yield return (typeof(IUserAuthRepository),
new AppServiceInfo(
typeof(IUserAuthRepository),
AppServiceLifetime.Singleton));
yield return (typeof(ICacheClient),
new AppServiceInfo(
typeof(ICacheClient),
ctx => new MemoryCacheClient(),
AppServiceLifetime.Singleton));
}
}
Note in the above example that for IUserAuthRepository there is no implementation provided. This indicates Kephas to auto-discover the implementation in the types registered for composition. Alternatively, feel free to use an instance or a factory in the registration, if you need to be deterministic.
I've never heard of Kephas before, but if you're referring to this Kephas Framework on GitHub it says it uses ASP.NET Core in which case it's best if you get them to both use ASP.NET Core's IOC which you can do by either registering your dependencies in ConfigureServices in your App's Startup:
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
//...
}
}
Or alternatively in ServiceStack's latest v5.6 release for Modular Startup change your ASP.NET Core Startup class to inherit from ModularStartup, e.g:
public class Startup : ModularStartup
{
public Startup(IConfiguration configuration) : base(configuration){}
public new void ConfigureServices(IServiceCollection services)
{
//...
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
//...
}
}
In which case you'll be able to Register ASP.NET Core dependencies in AppHost by registering them in your AppHost's Configure(IServiceCollection) where they can be resolved through both ASP.NET Core's IOC + ServiceStack's IOC, e.g:
public class AppHost : AppHostBase
{
public override void Configure(IServiceCollection services)
{
services.AddSingleton<IRedisClientsManager>(
new RedisManagerPool(Configuration.GetConnectionString("redis")));
}
public override void Configure(Container container)
{
var redisManager = container.Resolve<IRedisClientsManager>();
//...
}
}
I followed Alexander Duemont's blog, trying to implement a Java Spring Boot application that consumes Cloud Foundry Destination. The Destination has a custom OData V2 behind it, coming from an On-Premise ERP system. For local dev, when I perform the Maven build, the Integration-Tests module registers failure due to dependency injection
This is part of my Controller
#RestController
#RequestMapping("/resources")
public class ClassificationsController {
private static final Logger logger = CloudLoggerFactory.getLogger(ClassificationsController.class);
private final ClassificationService service;
public ClassificationsController(#Nonnull final ClassificationService service) {
this.service = service;
}
…..
}
The #Nonnull final ClassificationService Service causes org.springframework.beans.factory.UnsatisfiedDependencyException
I cannot use Spring stereotype annotations on generated Service classes (Fluent) to create Beans!
This question is more likely related to Spring Boot configuration.
I'm assuming ClassificationService is an interface and the implementing class exists in the same package.
Please make sure...
... to add the implementing class of ClassificationService to your component scan / test runtime. Feel free to share the integration test code to setup the test environment. Maybe the additional class reference is missing.
... to correctly annotate the respective Application class of your Spring Boot project. For example, assuming your ClassificationService resides in org.example.services.classification, while the rest of your application uses org.example.app. Your basic Application class would look like this, when following the Cloud SDK guide:
#SpringBootApplication
#ComponentScan({"com.sap.cloud.sdk", "org.example.services.classification", "org.example.app"})
#ServletComponentScan({"com.sap.cloud.sdk", "org.example.app"})
public class Application extends SpringBootServletInitializer
{
#Override
protected SpringApplicationBuilder configure( final SpringApplicationBuilder application )
{
return application.sources(Application.class);
}
public static void main( final String[] args )
{
SpringApplication.run(Application.class, args);
}
}
... to annotate the implementing class of ClassificationService with javax.inject.Named. In case you have multiple implementations of the same interface, make sure to give the not-used class a custom (unique) value for the #Named annotation.
... to look for exceptions (Class not found) in the application log during startup.
I am doing some stuff in Service Stack self host in windows service. The link gave me some hint. But in the code, what is StarterTemplateAppListenerHost then?
It is a class which extends AppHostHttpListenerBase (Source here) which is used to provide the http listener and application configuration.
public class StarterTemplateAppListenerHost : AppHostHttpListenerBase
{
static readonly IAppSettings AppSettings = new AppSettings();
public StarterTemplateAppListenerHost()
: base(AppSettings.GetString("ServiceName") ?? "StarterTemplate HttpListener", typeof(HelloService).Assembly) { }
public override void Configure(Funq.Container container)
{
container.Register(new TodoRepository());
}
}
This is demonstrated also in the official documentation here.
I just wonder why the link doesn't have OnStart() etc
The example has two different compilation modes. When it's run in debug, it will not run as a service, and solely uses StarterTemplateAppListenerHost.
When it is run in release mode then it will create a service around the instance of StarterTemplateAppListenerHost. The WinService class provides the OnStart and OnStop methods which are expected of Windows Services by extending System.ServiceProcess.ServiceBase.
So to get it running as a Windows Service you will need to include these 3 files:
Program.cs
WinService.cs
StarterTemplateAppListenerHost.cs
I'm currently using AutoFac as the DI container for our ServiceStack web services app. I'm able to configure the wiring and everything, but after reading the section on Scopes, I'm at a loss at which scope would be best to use when registering my components. In our particular case, I think a PerHttpRequest scope would be OK since (please correct me if im wrong) I would want to dispose the dependencies as soon as the request ends.
My question is, how do I set this up in the container? I can't seem to find the "PerHttpRequest" lifetime scope within the included methods in autofac. I'm also unsure if ServiceStack does some kind of automagic to do this for me behind the scenes.
I'm using Autofac 3.0.1 on ServiceStack 3.9.35 on .Net 4 (running as a regular ASP host, not MVC). I'm also using the class described here as the IContainer adapter.
I wanted to avoid the overhead of the dependency on MVC, so the first answer didn't quite work for me.
Instead I used Funq to register a PerRequest ILifetimeScope, and resolve the ILifetimeScope in the ConatinerAdaptor before resolving the dependency.
public class AutofacLifetimeScopeIocAdapter : IContainerAdapter
{
private readonly Container _requestContainer;
public AutofacLifetimeScopeIocAdapter(Funq.Container requestContainer)
{
_requestContainer = requestContainer;
}
public T Resolve<T>()
{
var currentContainer = _requestContainer.Resolve<ILifetimeScope>();
return currentContainer.Resolve<T>();
}
public T TryResolve<T>()
{
var currentContainer = _requestContainer.Resolve<ILifetimeScope>();
T result;
if (currentContainer.TryResolve<T>(out result))
{
return result;
}
return default(T);
}
}
Then initialise with this
_autofacContainerRoot = builder.Build();
IContainerAdapter adapter = new AutofacLifetimeScopeIocAdapter(container);
container.Register<ILifetimeScope>((c) => _autofacContainerRoot.BeginLifetimeScope())
.ReusedWithin(ReuseScope.Request);
container.Adapter = adapter;
Then cleanup with
public override void OnEndRequest()
{
var currentContainer = _container.Resolve<ILifetimeScope>();
currentContainer.Dispose();
base.OnEndRequest();
}
This seems to behave as required for Autofac - SingleInstance, InstancePerDependency, and now InstancePerLifetimeScope which is perRequest.
Mythz response on the HostContext.Instance.Items collection can likely be used to remove the need for the
var currentContainer = _container.Resolve<ILifetimeScope>();
resolution, which should improve performance.
I think I have figured out how to make this work (using Autofac 2.6, which I am stuck on right now.) It involves using the following adapter and the Autofac.Mvc3 package:
public class AutofacIocAdapter : IContainerAdapter
{
private readonly IContainer _autofacRootContainer;
private readonly Container _funqContainer;
public AutofacIocAdapter(IContainer autofacRootContainer, Container funqContainer)
{
// Register a RequestLifetimeScopeProvider (from Autofac.Integration.Mvc) with Funq
var lifetimeScopeProvider = new RequestLifetimeScopeProvider(autofacRootContainer,null);
funqContainer.Register<ILifetimeScopeProvider>(x => lifetimeScopeProvider);
// Store the autofac application (root) container, and the funq container for later use
_autofacRootContainer = autofacRootContainer;
_funqContainer = funqContainer;
}
public T Resolve<T>()
{
return ActiveScope.Resolve<T>();
}
public T TryResolve<T>()
{
T result;
if (ActiveScope.TryResolve(out result))
{
return result;
}
return default(T);
}
private ILifetimeScope ActiveScope
{
get
{
// If there is an active HttpContext, retrieve the lifetime scope by resolving
// the ILifetimeScopeProvider from Funq. Otherwise, use the application (root) container.
return HttpContext.Current == null
? _autofacRootContainer
: _funqContainer.Resolve<ILifetimeScopeProvider>().GetLifetimeScope();
}
}
}
Steps to implement:
Add the Autofac.Mvc3 NuGet package to your web project (NOTE: does
not matter that your project isn't using MVC. The solution might be slightly different with Autofac 3, which cannot use Mvc3 integration.)
Follow the ServiceStack IoC page in hooking up a custom IContainerAdapter
for Autofac, using the following implementation
Note the RequestScope in ServiceStack's IOC only refers to ServiceStack's built-in Funq IOC.
To use RequestScope in another IOC Container like AutoFac you generally need to notify AutoFac at the end of the request so it can clean up all its request-scoped instances. To do this, ServiceStack provides the AppHostBase.OnEndRequest() hook you can override to get execute custom logic at the end of each request.
I'm not familiar with how AutoFac's custom lifetime scope works but more details about it can be found in:
AutoFac's InstanceScope wiki page
Primer on AutoFac's Lifetime scopes
Answer on how to manage AutoFac' request scope in MVC
Other info that might be useful for managing instances in ServiceStack is that every instance in put in the HostContext.Instance.Items dictionary or disposable added to HostContext.Instance.TrackDisposable are automatically disposed at the end of each request.
Update 2015-11-25: I changed the implementation by using global request and response filters. I put both ServiceStack V3 and V4 solutions into this repository and both versions are available as nuget packages.
I solved this problem by opening a new scope in Application_BeginRequest and disposing in Application_EndRequest. In the container adapter I check if this scope exists and use it, if not, I use the container. This allows using .InstancePerRequest() registration scope.
Described with gists here.