Safely release dependency injected wcf client in .net core - c#

I want to use Microsoft's dependency injection in .Net Core (2.2) to inject and safely release WCF clients. I'm using the "WCF Web Service Reference Provider Tool" in VS2019 to add WCF proxy classes to my solution. Using Microsoft.Extensions.DependencyInjection I can register the clients in the services collection, but I can't seem to find a way of hooking into a release lifecycle event (as can be done in various other IoC frameworks, e.g. Autofac), to add code for doing a safe release according to Microsoft's recommendations described here: https://learn.microsoft.com/en-us/dotnet/framework/wcf/samples/use-close-abort-release-wcf-client-resources
Is there any way of doing something like that in the quite basic dependency injection functionality that comes with .Net Core framework? Or am I forced to use 3rd party IoC framework?
Pseudo code:
So basically I want to do something like this:
// Register the channel factory for the service. Make it
// Singleton since you don't need a new one each time.
services.AddSingleton(p => new ChannelFactory<IWcfService>(
new BasicHttpBinding(),
new EndpointAddress("http://localhost/WcfService")));
// Register the service interface using a lambda that creates
// a channel from the factory.
// TODO: need a way to handle proper disposal, e.g. like OnRelease().
services.AddTransient<IWcfService>(p =>
p.GetService<ChannelFactory<IWcfService>>().CreateChannel())
.OnRelease(CloseChannel); // <---This is what I would like to do
static void CloseChannel<T>(T channel)
{
var disp = (ICommunicationObject) channel;
try
{
if (disp.State == CommunicationState.Faulted)
disp.Abort();
else
disp.Close();
}
catch (TimeoutException)
{
disp.Abort();
}
catch (CommunicationException)
{
disp.Abort();
}
catch (Exception)
{
disp.Abort();
throw;
}
}
But I need a way to hook into the service release lifecycle event, e.g. something like .OnRelease() in Autofac, so I can do proper disposal.

I dont know if you still need a response, but on my end to resolve this issue I implemented the dispose into the partial class.
Each time the wcf client is disposed the correct clean up is made:
public partial class MyWcfClient : IDisposable
{
protected void Dispose(bool disposing)
{
if (disposing)
{
bool success = false;
try
{
if (State != CommunicationState.Faulted)
{
Close();
}
success = true;
}
finally
{
if (!success)
{
Abort();
}
}
}
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
}

Related

Injecting Singleton Instance of class into SignalR Hub using Autofac

I am creating an application where SignalR is used to broadcast real-time tweets to a map. I am using the C# Tweetinvi library (tweetinvi.codeplex.com) to handle all of the logic associated with connecting to the Twitter Streaming API.
The Twitter API specifies that only one streaming connection can be open to Twitter at any time. As I am using SignalR, there is a dependency between the Streaming connection and the Hub class. I know that the Hub class is transient, meaning that it is created each time a client requests it, so I need to ensure that the instance of my Twitter Stream class injected into the Hub class is a singleton, or at least IFilteredStream is only created once in the lifetime of the application. Here is the boilerplate code to connect to the API:
public class TweetStream
{
private IFilteredStream _stream;
public TweetStream()
{
var consumerKey = ConfigurationManager.AppSettings.Get("twitter:ConsumerKey");
var consumerSecret = ConfigurationManager.AppSettings.Get("twitter:ConsumerSecret");
var accessKey = ConfigurationManager.AppSettings.Get("twitter:AccessKey");
var accessToken = ConfigurationManager.AppSettings.Get("twitter:AccessToken");
TwitterCredentials.SetCredentials(accessKey, accessToken, consumerKey, consumerSecret);
_stream = Stream.CreateFilteredStream();
}
// Return singular instance of _stream to Hub class for usage.
public IFilteredStream Instance
{
get { return _stream; }
}
}
The IFilteredStream interface exposes a lambda method as below which allows for receiving Tweets in real-time, which I would like to be able to access from within my SignalR Hub class:
_stream.MatchingTweetReceived += (sender, args) => {
Clients.All.broadcast(args.Tweet);
};
The source for this method can be found here
I've tried to implement Autofac, and it seems that the connection to the Twitter API happens, however nothing more happens. I've tried to debug this, but am unsure how to debug such a scenario using dependency injection. My Hub class currently looks like this:
public class TwitterHub : Hub
{
private readonly ILifetimeScope _scope;
private readonly TweetStream _stream;
// Inject lifetime scope and resolve reference to TweetStream
public TwitterHub(ILifetimeScope scope)
{
_scope = scope.BeginLifetimeScope();
_stream = scope.Resolve<TweetStream>();
var i = _stream.Instance;
_stream.MatchingTweetReceived += (sender, args) => {
Clients.All.broadcast(args.Tweet);
};
i.StartStreamMatchingAllConditions();
}
}
And finally, my OWIN Startup class, where I register my dependencies and Hub with Autofac:
[assembly: OwinStartup(typeof(TwitterMap2015.App_Start.OwinStartup))]
namespace TwitterMap2015.App_Start
{
public class OwinStartup
{
public void Configuration(IAppBuilder app)
{
var builder = new ContainerBuilder();
// use hubconfig, not globalhost
var hubConfig = new HubConfiguration {EnableDetailedErrors = true};
builder.RegisterHubs(Assembly.GetExecutingAssembly()); // register all SignalR hubs
builder.Register(i => new TweetStream()).SingleInstance(); // is this the correct way of injecting a singleton instance of TweetStream?
var container = builder.Build();
hubConfig.Resolver = new AutofacDependencyResolver(container);
app.MapSignalR("/signalr", hubConfig);
}
}
}
Sorry if this question is a bit of a mess, I'm having a hard time of understand what kind of architecture I need to implement to get this working! Open to advice / recommendations on how this could be improved, or how it should be done!
IMO this cannot work because you are wiring your event to call over the context of a specific hub instance, regardless of any code related to Autofac (which might have issues too but I'm not a big expert on it). Your hub's constructor will be called each time a new connection happens or a method is called from a client, so:
you are subscribing that event potentially multiple times per client. I don't know the Twitter API you are using, but on this note the fact that you call i.StartStreamMatchingAllConditions() all these times seems wrong to me
each time you create a closure over the Clients member of that instance in your event handler, which is supposed to go away when the hub is destroyed (so probably you are leaking memory)
What you need to do, given that your are calling over Client.All, and therefore this is a pure broadcast independent on any specific caller, is:
initialize your Twitter connection in the constructor of your TwitterStream service
in that same place (maybe with some indirection, but probably not necessary) take an instance of the hub context of your TwitterHub
subscribe to the event and use the context you just retrieved to broadcast over it
Such constructor might look like this:
public service TwitterStream : ??? <- an interface here?
{
...
public TwitterStream (ILifetimeScope scope ??? <- IMO you don't need this...)
{
//Autofac/Twitter stuff
...
var context = GlobalHost.DependencyResolver.GetHubContext<TwitterHub>();
_stream.MatchingTweetReceived += (sender, args) => {
context.Clients.All.broadcast(args.Tweet);
};
//maybe more Autofac/Twitter stuff
...
}
...
}
TwitterHub must exist, but in case you just need it to do this kind of broadcast to all, with no special code needed to monitor connections or handle client-generated calls, it could well be empty and it's just fine that your actual hub-related code lives outside of it and uses a IHubContext to broadcast messages. Such a code would take care of handling all the existing connected clients each time a tweet arrives, so no need to track them.
Of course if you have more requirements for actually handling clients separarely, then things might need to be different, but your code does not make me think otherwise.

Registering same singleton for multiple interfaces in IOC

I have a service that needs to be able to handle native assets and attribute types, so I have a core service in my PCL called BaseThemeService which implements interface IThemeService. I need to be able to access some attributes from the core PCL, which is why it implements the IThemeService from the core PCL.
Within each platform project, I have a class ThemeService which implements IDroidThemeService and extends BaseThemeService. I then register the IDroidThemeService singleton in the setup of each project manually.
This works, except that there are now 2 instances of BaseThemeService. 1 that is registered for the IThemeService for the core, and 1 that is registered for the IDroidThemeService for the platform.
To work around this I construct it myself and then register each appropriately:
protected override void InitializeFirstChance()
{
ThemeService themeService = new ThemeService(Mvx.Resolve<IMvxJsonConverter>(), Mvx.Resolve<IMvxResourceLoader>());
Mvx.RegisterSingleton<IDroidThemeService>(themeService);
Mvx.RegisterSingleton<IThemeService>(themeService);
base.InitializeFirstChance();
}
This seems like it should work, but it doesn't since the IMvxJsonConverter and IMvxResourceLoader services have not been registered yet.
I see in the MvvmCross documentation that auto-loading using lazy construction will register a service with all implemented interfaces. Is there a way to use that functionality here to remove the manual registration?
Answer
protected override void InitializeFirstChance()
{
Mvx.RegisterSingleton<IDroidThemeService>(GetThemeService);
Mvx.RegisterSingleton<IThemeService>(GetThemeService);
base.InitializeFirstChance();
}
private DroidThemeService DroidSingletonService = null;
private DroidThemeService GetThemeService()
{
if (DroidSingletonService == null)
{
DroidSingletonService = Mvx.IocConstruct<DroidThemeService>();
}
return DroidSingletonService;
}
This ended up being the ultimate resolution. I know the RegisterAsLazySingleton looks to solve this problem automatically, so I'll update again if I find a way to implement this that is slightly cleaner.
You can register a factory for the singleton which can produce a singleton manually and return that whenever anyone wants to call it. See the docs for Lazy Singleton Registration
ThemeService singletonService = null;
private ThemeService GetThemeService()
{
if (singletonService == null)
{
singletonService = new ThemeService(Mvx.Resolve<IMvxJsonConverter>(), Mvx.Resolve<IMvxResourceLoader>());
}
return singletonService;
}
protected override void InitializeFirstChance()
{
Mvx.RegisterSingleton<IDroidThemeService>(GetThemeService);
Mvx.RegisterSingleton<IThemeService>(GetThemeService);
base.InitializeFirstChance();
}
Depending on your situation, it may be appropriate for the field and method to be static.

Console app with MVC, Ninject and WCF Service (Dispose issue?)

I have a MVC application with all Ninject stuff wired up properly. Within the application I wanted to add functionality to call a WCF service, which then sends bulk messages (i.e. bulk printing) to RabbitMQ queue .
A 'processor' app subscribes to messages in the queue and process them. This is where I also want to update some stuff in the database, so I want all my services and repositories from the MVC app to be available too.
The processor app implements the following:
public abstract class KernelImplementation
{
private IKernel _kernel;
public IKernel Kernel
{
get
{
if (_kernel != null)
return _kernel;
else
{
_kernel = new StandardKernel(new RepositoryModule(),
new DomainModule(),
new ServiceModule(),
new MessageModule());
return _kernel;
}
}
}
}
All Ninject repository bindings are specified within RepositoryModule, which is also used within MVC app and look like this:
Bind<IReviewRepository>().To<ReviewRepository>().InCallScope();
The processor class
public class Processor : KernelImplementation
{
private readonly IReviewPrintMessage _reviewPrintMessage;
public Processor()
{
_reviewPrintMessage = Kernel.Get<IReviewPrintMessage>();
[...]
_bus.Subscribe<ReviewPrintContract>("ReviewPrint_Id",
(reviewPrintContract) => _reviewPrintMessage.ProcessReviewPrint(reviewPrintContract));
//calling ProcessReviewPrint where I want my repositories to be available
}
}
Everything works fine until I update the database from the MVC app or database directly. The processor app doesn't know anything about those changes and the next time it tries to process something, it works on a 'cached' DbContext. I'm sure it's something to do with not disposing the DbContext properly, but I'm not sure what scope should be used for a console app (tried all sort of different scopes to no avail).
The only solution I can think of at the moment is to call WCF service back from the processor app and perform all the necessary updates within the service, but I would want to avoid that.
UPDATE: Adding update logic
Simplified ReviewPrintMessage:
public class ReviewPrintMessage : IReviewPrintMessage
{
private readonly IReviewService _reviewService;
public ReviewPrintMessage(IReviewService reviewService)
{
_reviewService = reviewService;
}
public void ProcessReviewPrint(ReviewPrintContract reviewPrintContract)
{
var review =
_reviewService.GetReview(reviewPrintContract.ReviewId);
[...]
//do all sorts of stuff here
[...]
_reviewService.UpdateReview(review);
}
}
UpdateReview method in ReviewService:
public void UpdateTenancyAgreementReview(TenancyAgreementReview review)
{
_tenancyAgreementReviewRepository.Update(review);
_unitOfWork.Commit();
}
RepositoryBase:
public abstract class EntityRepositoryBase<T> where T : class
{
protected MyContext _dataContext;
protected EntityRepositoryBase(IDbFactory dbFactory)
{
this.DbFactory = dbFactory;
_dbSet = this.DataContext.Set<T>();
}
[...]
public virtual void Update(T entity)
{
try
{
DataContext.Entry(entity).State = EntityState.Modified;
}
catch (Exception exception)
{
throw new EntityException(string.Format("Failed to update entity '{0}'", typeof(T).Name), exception);
}
}
}
Context itself is bound like this:
Bind<MyContext>().ToSelf().InCallScope();
From the description of scopes I thought that Transient scope was the right choice, but as I said earlier I tried all sorts including RequestScope, TransientScope, NamedScope and even Singleton (although I knew it wouldn't be desired behaviour), but none of them seem to be disposing the context properly.
What you'll need is one DbContext instance per transaction.
Now other "applications" like web-applications or wcf-service may be doing one transaction per request (and thus use something like InRequestScope(). Also note, that these application create an object graph for each request. However, that is a concept unknown to your console application.
Furthermore, scoping only affects the instantiation of objects. Once they are instantiated, Scoping does not have any effect on them.
So one way to solve your issue would be to create the (relevant) object tree/graph per transaction and then you could use InCallScope() (InCallScope really means "once per instantiation of an object graph", see here).
That would mean that you'd need a factory for IReviewPrintMessage (have a look at ninject.extensions.factory) and create an instance of IReviewPrintMessage every time you want to execute IReviewPrintMessage.ProcessReviewPrint.
Now you have re-created the "per request pattern".
However, regarding CompositionRoot this is not recommended.
Alternative: you can also only re-create the DbContext as needed. Instead of passing it around everywhere (DbContext as additional parameter on almost every method) you use a SynchronizationContext local storage (or if you don't use TPL/async await: a ThreadLocal). I've already described this method in more detail here

How to create web reference manually

I know that I can point to some SOAP web service by adding web reference using visual studio.
But I need to do it from code.
How can I manually create web reference object in code and access all methods from that object?
Basically I want to avoid generating proxy classes.
If you can get a copy of the service contract (interface)(svcUtil can help with this) then you can include it in your project and use the ChannelFactory class to dynamically create a channel for the client to communicate with the service.
I tend to encapsulate it all up in a SAL (Service Application Layer) to re-use as required.
This is a simple (and in no way complete!) example demonstrating how to connect to a fictious time service and call the GetTime() operation without using a VS generated proxy:
public class TimeSAL : IDisposable
{
private ChannelFactory<ITimeService> timeServiceProxyFactory;
private ITimeService timeServiceProxy;
private ITimeService TimeService
{
get
{
//create channel factory if not there
if (timeServiceProxyFactory == null)
timeServiceProxyFactory = new ChannelFactory<ITimeService>(new BasicHttpBinding(), new EndpointAddress("http://url_to_my_timeservice_endpoint")); //
if (timeServiceProxy == null)
timeServiceProxy = amlProxyFactory.CreateChannel();
return timeServiceProxy;
}
}
public string GetTime()
{
return TimeService.GetTime();
}
public void Dispose()
{
//dispose of ChannelFactory and proxy.
//ensure you check for comm faults to abort before closing
}
}
Now I can use this SAL throughout my code as necessary:
....
using(TimeSAL timeSAL = new TimeSAL())
{
myBusinessObject.CurrentTime = timeSAL.GetTime();
}
....
If you are unable to get your hands on a copy of the service contract, a long-winded way is to handcraft the soap request. Fiddler or soapUI can help with what the message should look like.
Hope some of this helps.

Exception Handling : AOP vs Classic Handling?

I'm upgrading a Plugin Loading Engine (.NET) which does the following :
Loads Plugins
Connects them to the appropriate Data Source
Launchs the Plugins
Displays the results
All the plugins implement the same Interface : IPluginand each one is launched in a separate BackGroundWorker. All the BackgroundWorkers are managed by a module called Host.
My problem is the Errors/Exceptions Handling. The engine is already deployed and I want to find an elegant way to handle the Errors/Exceptions that could be thrown when the plugins run. Some Exceptions are caught in the plugins but not all of them.
I was thinking about a separate layer that could catch the errors and treat them for all the plugins.
I imagined a kind of Context attached to each Plugin which contain its progress level (BackgroundWorker.ReportProgress), its status, the thrown exceptions(using the RunWorkerCompletedEvent) but the errors are thrown only after the BackgroundWorker stops. I would like to interrupt it when an exception is thrown.
I was also thinking that Aspect Oriented Programming could be a great way. I took a look on the net and found some framework like Spring.NET. But not sure if it could be appropriate in my case.
[UPDATE]
Here are more design details as requested :
IPlugin Interface : Called AbstractEnvChecker :
The application is a Rich Client App. After compiling the plugins, the generated DLL are loaded and a List is displayed to the users in a simple Windows Form. The user selects then the plugins to launch and the Plugin.DoWork() method is called.
And here is how the Host launches the selected Plugins :
void LaunchPlugin(AbstractEnvChecker p_Plugin)
{
if (p_Plugin != null)
{
BackgroundWorker l_BackgroundWorker = new BackgroundWorker();
l_BackgroundWorker.WorkerReportsProgress = true;
l_BackgroundWorker.WorkerSupportsCancellation = true;
l_BackgroundWorker.DoWork +=
new DoWorkEventHandler(bw_DoWork);
l_BackgroundWorker.ProgressChanged +=
new ProgressChangedEventHandler(bw_ProgressChanged);
l_BackgroundWorker.RunWorkerCompleted +=
new RunWorkerCompletedEventHandler(bw_RunWorkerCompleted);
m_PluginByThreadMap.Add(l_BackgroundWorker, p_Plugin);
l_BackgroundWorker.DoWork += p_Plugin.DoWork;
l_BackgroundWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(l_BackgroundWorker_RunWorkerCompleted);
l_BackgroundWorker.RunWorkerAsync(p_Plugin);
}
}
Is AOP an appropriate solution to add the Error Handling Layer ?
The simplest way would be to just wrap the IPlugin.DoWork() method in a try/catch clause. something like this:
l_BackgroundWorker.DoWork += (o, e) => ExecutePlugin(o, e, p_plugin);
private void ExecutePlugin(object sender, DoWorkEventArgs e, IPlugin plugin)
{
try
{
plugin.DoWork(o, e);
}
catch (Exception e)
{
//do something with the error. disable the plugin maybe?
}
}
If this work then using Spring just for the Error handling is a bit overkill in my opinion.
Something additional you could do is throwing a custom exception (e.g. a PluginException) and handle those globally in your Application, this can be achieved by attaching to:
Application.ThreadException and AppDomain.CurrentDomain.UnhandledException events
Spring.net uses dynamic weaving, which basically means that at runtime Spring.net aop can wrap exception handlers around method calls. But Spring.net aop needs a seam to position it's interceptor in.
If your plugins should be loaded into a UI, then the user (probably) can invoke methods that don't go through the host or IPlugin interface at all, making it hard (if not impossible) for spring.net aop to intercept and wrap exception handlers.
If your host is a console application or service that calls myPlugin.DoWork(), then it's definitely possible to intercept any exceptions thrown by the plugin using Spring.net aop. If you could provide a bit more detail (see comments to your question) then I can show you how to do this.
Below an example that uses Spring.net AOP to proxy a plugin instance and wrap it with an interceptor, that catches a thrown exception and delegates it back to the host. Note that you can do this without AOP too ... that's up to you.
using System;
using AopAlliance.Intercept;
using NUnit.Framework;
using Spring.Aop.Framework;
namespace Aop
{
[TestFixture]
public class SimpleProxyFactoryTests
{
[Test]
public void Main()
{
var host = new Host();
var mp = new SimplePlugin();
var pf = new ProxyFactory(mp);
pf.AddAdvice(new DelegateToHostExceptionHandlingAdvice(host));
var proxy = (IPlugin)pf.GetProxy();
proxy.DoWork();
}
}
public interface IPlugin
{
void DoWork();
}
public class Host
{
public void HandleExceptionFromPlugin(Exception ex)
{
Console.WriteLine("Handling exception: {0}", ex.Message);
}
}
public class SimplePlugin : IPlugin
{
public void DoWork()
{
Console.WriteLine("Doing it and throwing an exception ... ");
throw new ApplicationException("Oops!");
}
}
public class DelegateToHostExceptionHandlingAdvice : IMethodInterceptor
{
private readonly Host _host;
public DelegateToHostExceptionHandlingAdvice(Host host)
{
_host = host;
}
public object Invoke(IMethodInvocation invocation)
{
try
{
return invocation.Proceed();
}
catch (Exception ex)
{
_host.HandleExceptionFromPlugin(ex);
return null;
}
}
}
}
Discussion
I hope I've shown you how you could leverage an aop framework to do exception handling. As Sebastian mentions in his answer, using Spring aop only for exception wrapping might be considered overkill - and I agree; compare the simplicity of his code example to the complexity of mine. Imagine explaining either one to a new developer on your team.
Spring aop starts to "shine" when you use it in combination with the Spring IOC container.

Categories

Resources