ASP.NET MVC 4 Background operations - asp.net-mvc-4

I am looking for nice and elegant architectural solution for ASP.NET MVC 4 Background operations.
My goal is developing some world that lives its own life and clients can only interact with it. For now let's say that it will be a simple clock and clients can watсh on it.
Now I have WebBackrounder + SignalR packages.
WebBackrounder:
[assembly: PostApplicationStartMethod(typeof(WebBackgrounderSetup), "Start")]
[assembly: ApplicationShutdownMethod(typeof(WebBackgrounderSetup), "Shutdown")]
namespace LibcanvasStudy.App_Start
{
public static class WebBackgrounderSetup
{
static readonly JobManager _jobManager = CreateJobWorkersManager();
public static RedrawJob RedrawJob { get; private set; }
public static void Start()
{
_jobManager.Start();
}
public static void Stop()
{
_jobManager.Stop();
}
public static void Shutdown()
{
_jobManager.Dispose();
}
private static JobManager CreateJobWorkersManager()
{
RedrawJob = new RedrawJob(TimeSpan.FromSeconds(1));
var manager = new JobManager(new[] { RedrawJob }, new JobHost());
return manager;
}
}
RedrawJob while its execution rise event and SignalR hub catches it:
public class CanvasHub : Hub
{
public CanvasHub()
{
if (WebBackgrounderSetup.RedrawJob != null)
WebBackgrounderSetup.RedrawJob.Executing += (sender, args) => Request(args);
}
public void Request(RedrawEventArgs eventArgs)
{
Clients.All.redraw(...);
}
}
I have one main problem for now - How I can dynamicaly add and remove jobs from my JobManager?
Also I don't like this job-event system, it's a little bit awkwardly for me. Any proposal?

What darin says is correct, but it can be worked around. For example what I do for these kind of scenarios is to have a internal WCF service that handles all jobs, you call it from the schedular or workflow engine using net.tcp or memory pipe. This way you benefit from all IIS sugar coating. And dont need to marshal your threads and error handing.
Second, implement some kind of event bus to decouple SignalR and your domain logic.
I have written this little lib that proxies between domain events and SignalR
https://github.com/AndersMalmgren/SignalR.EventAggregatorProxy
Install using nuget
Install-Package SignalR.EventAggregatorProxy
Please look at the wiki for the few easy steps required to hook it up
https://github.com/AndersMalmgren/SignalR.EventAggregatorProxy/wiki
For a super lightweight in process event bus look at Caliburn.Micros EventAggregator
http://nuget.org/packages/Caliburn.Micro.EventAggregator/

What do you think about using this code in any part of MVC app?
IHubContext hub = GlobalHost.ConnectionManager.GetHubContext<CanvasHub>();
hub.Clients.All.redraw(redrawData);

Related

.NET Community Toolkit Messaging - Registering with Blazor Server

I am experimenting with the .NET Community Toolkit IMessenger interface in a Blazor Server application.
It appears a singleton service is utilized which is not ideal as the messages are shared across all connected sessions. This causes the behavior shown in the gif below. The count in the sidebar is incrementing across all browser tabs/sessions.
Is it possible to use the WeakReferenceMessenger and/or the StrongReferenceMessenger in a Blazor Server application registered with a transient service lifetime?
Sender
private void IncrementCount()
{
currentCount++;
WeakReferenceMessenger.Default.Send(new IncrementCountMessage(currentCount));
}
Receiver
using CommunityToolkit.Mvvm.Messaging;
using Microsoft.AspNetCore.Components;
namespace BlazorServerSandbox;
public partial class Receiver : ComponentBase, IRecipient<IncrementCountMessage>
{
public int CurrentCount { get; set; } = 0;
public Receiver()
{
WeakReferenceMessenger.Default.Register(this);
}
public void Receive(IncrementCountMessage message)
{
CurrentCount = message.Value;
InvokeAsync(() => StateHasChanged());
}
}
Use this in your Program/Startup class:
services.AddScoped<IMessenger, WeakReferenceMessenger>();
then in your components/pages inject IMessenger and use like:
receiver:
[Inject] IMessenger Messenger
Messenger.Register<MyMessage>(this, (r, m) => DoSomthing());
sender:
[Inject] IMessenger Messenger
Messenger.Send(new MyMessage("test"));
Hope this help.

How to send constantly updates using .Net Core SignalR?

I am new to SignalR and I would like to build such app -- every second a hub sends current time to all connected clients.
I found tutorial, but it is for .Net Framework (not Core): https://learn.microsoft.com/en-us/aspnet/signalr/overview/getting-started/tutorial-high-frequency-realtime-with-signalr So on one hand I don't know how to translate it to .Net Core SignalR, on the other hand I don't know how to write it from scratch (the limiting condition is the fact a hub is a volatile entity, so I cannot have state in it).
I need something static (I guess) with state -- let's say Broadcaster, when I create some cyclic action which in turn will send updates to clients. If such approach is OK, how to initialize this Broadcaster?
Currently I added such static class:
public static class CrazyBroadcaster
{
public static void Initialize(IServiceProvider serviceProvider)
{
var scope = serviceProvider.CreateScope();
var hub = scope.ServiceProvider.GetRequiredService<IHubContext<ChatHub>>();
var sub = Observable.Interval(TimeSpan.FromSeconds(1)).Subscribe(_ => hub.Clients.All.SendAsync("Bar", DateTimeOffset.UtcNow));
}
}
Yes, I know it is leaky. I call this method at the end of Startup.Configure, probably tons of violations here, but so far it is my best shot.
The missing piece was hosted service, i.e. the code that runs in the background -- https://learn.microsoft.com/en-US/aspnet/core/fundamentals/host/hosted-services?view=aspnetcore-2.2.
So my crazy class is now transformed into:
public sealed class HostedBroadcaster : IHostedService, IDisposable
{
private readonly IHubContext<ChatHub> hubContext;
private IDisposable subscription;
public HostedBroadcaster(IHubContext<ChatHub> hubContext)
{
this.hubContext = hubContext;
}
public void Dispose()
{
this.subscription?.Dispose();
}
public Task StartAsync(CancellationToken cancellationToken)
{
this.subscription = Observable.Interval(TimeSpan.FromSeconds(1)).Subscribe(_ => hubContext.Clients.All.SendAsync("Bar", DateTimeOffset.UtcNow));
return Task.CompletedTask;
}
public Task StopAsync(CancellationToken cancellationToken)
{
this.subscription?.Dispose();
return Task.CompletedTask;
}
}

Running WCF service method during start of Windows Service

I have got WCF service running as Windows service and I need to run a method of the WCF Service when Windows Service is starting. Is it possible in any way?
[ServiceContract]
public interface IWebMonitorServiceLibrary
{
[OperationContract]
void TestMethod();
}
[ServiceBehavior(IncludeExceptionDetailInFaults = true)]
public class WebMonitorServiceLibrary : IWebMonitorServiceLibrary
{
#region properties
#endregion
#region events
#endregion
public WebMonitorServiceLibrary()
{
Initialization();
}
private void Initialization()
{
/////////
}
public void TestMethod()
{
//////////
}
}
You don't explain why you want this initialization code to run, but given you almost never want to use a single-instance WCF service, the proper way would be to use dependency injection (see How do I pass values to the constructor on my wcf service?).
Create an object in which you store the things you want to initialize, which you initialize on your Windows Service start:
public class SomeSettingsYouWantToInitialize
{
public string SomeSetting { get; set; }
}
public class WindowsServiceInstance : ServiceBase
{
protected override void OnStart(string[] args)
{
InitializeWcfService();
}
private void InitializeWcfService()
{
var settings = new SomeSettingsYouWantToInitialize
{
SomeSetting = "Foo"
};
_yourDependencyContainer.Register<SomeSettingsYouWantToInitialize>(settings);
}
}
Then (using whatever dependency injection framework you use), inject that into your service's constructor:
public class WebMonitorServiceLibrary
{
public WebMonitorServiceLibrary(SomeSettingsYouWantToInitialize settings)
{
// do stuff with settings
}
}
Generally, no. This is because by default (and following best practice) you will have configured your service to run per-call (or per session), which means there can be multiple instances of your actual service running in your service host.
Therefore, any requirement for you to be able to return an instance of the service from the service host will involve some nasty plumbing code and is not advised.
Specifically, however, there are two approaches you could use to do what you want.
The first involves running your service in InstanceContextMode.Single - this means there will be a single service instance which will handle all requests. If you do this then you can simply create the service instance and then pass it into the servicehost when you start the windows service:
var service = new MyService();
var host = new ServiceHost(service);
You then have access to the service instance and can call the operation directly.
service.MyOperation("something");
The second thing you can do for when you don't want to run a singleton service you can make your service implementation just a wrapper around a static instance of a shared class that actually process the requests. As an example:
public class MyService : IMyService
{
private static IMyService instance = new MySharedServiceClass();
public static IMyService Instance
{
get { return instance ; }
}
public bool MyOperation(string something)
{
return instance.MyOperation(something);
}
}
Then you can call the method on the class like this:
var host = new ServiceHost(typeof(MyService));
var instance = MyService.Instance;
instance.MyOperation("something");
I would still avoid doing this if at all possible. Think to yourself why do you even want this method called on startup? Surely it would be better to have this code directly in the windows service if it's something that needs to be run on startup?

How to use dynamic module loading in an onion architecture using MVC4 as frontend

I'm trying to wrap my head around dependency injection in the Onion Architecture, I've found this solution which uses a dependency resolution layer around the onion. But there is so much going on that I'm completely lost.
So I setup a project to try it out. I like to start off simple, so a simple log entry on a (MVC) controller method would be a good start.
I'd like to use Dynamic Module Loading (kernel.Load("*.dll");) since it comes recommended from the Ninject wiki.
My solution looks like this: (For now)
Solution
- Core.Services
- Infrastructure.Logging
- DependencyResolution
- UI.MVC (default internet template)
I'd like to follow the guides lines for dependency resolution outlined here.
Ilogger
namespace Core.Services
{
public interface ILogger
{
void Log(string message);
}
}
Logging Implementation
namespace Infrastructure.Logging
{
public class DebugLogger : ILogger
{
public void Log(string message)
{
Debug.WriteLine(message);
}
}
}
Dependency Resolution
namespace DependencyResolution
{
public class TestModule : NinjectModule
{
public override void Load()
{
Bind<ILogger>().To<DebugLogger>();
}
}
}
What I want to accomplish
UI
namespace UI.MVC.Controllers
{
public class HomeController : Controller
{
private readonly ILogger _logger;
public HomeController(ILogger logger)
{
_logger = logger;
}
public ActionResult Index()
{
ViewBag.Message = "Modify this template to jump-start your ASP.NET MVC application.";
_logger.Log("It works!");
return View();
}
}
}
I need to run kernel.Load("*.dll"); somehow and I need to setup my MVC to use DI. I'm just now sure how since the UI cannot know about the Dependency Resolution layer.
Your DI container should be composed somewhere. This place is called the composition root and is the outermost layer. In your case that would be the ASP.NET MVC application. So saying that it should not know about the DI simply doesn't make sense. The Ninject.MVC3 package comes with a custom dependency resolver implementation that gets plugged into the application and you will get automatic DI in your controllers.

MEF example in Silverlight 4

Although there are many examples of Silverlight projects using MEF (Managed Extensibility Framework), since the System.ComponentModel.Composition.Packaging.Toolkit package was removed in the version that is shipped inside Silverlight 4, these projects are away from helping to run some basic MEF example.
Some tutorials using the newer API will be very beneficial.
Thanks.
Although I can't point you in the direction of a concrete example, it's quite trivial to start composing parts of your Silverlight 4 application. Given the example:
public partial class MainPage : UserControl, IContext
{
[ImportMany]
public IEnumerable<IPlugin> Plugins { get; set; }
public MainPage()
{
InitializeComponent();
CompositionInitializer.SatisfyImports(this);
Plugins.First().Run(this);
}
public void ShowMessage(string message)
{
textBox1.Text = message;
}
}
public interface IContext
{
void ShowMessage(string message);
}
public interface IPlugin
{
void Run(IContext context);
}
[Export(typeof(IPlugin))]
public class SamplePlugin : IPlugin
{
public void Run(IContext context)
{
context.ShowMessage("Hello World");
}
}
The CompositionInitializer type provides SatisfyImports methods which action a default CompositionContainer which is plugged into a catalog that reads parts from your deployed XAP files. If you want more fine grained control over how the catalog is created, you can always create your own CompositionContainer.
Are there any particular aspects of MEF with Silverlight you are looking for advice on?
I wrote a blog post how you can implement MEF into you Silverlight applictaion see
http://www.arrangeactassert.com/solid-design-principles-using-mef-in-silverlight-and-wpf/
I think this is what you are after.