Private messaging in a asp.net mvc app with email reply - asp.net-mvc

We are currently implementing private messaging in our asp.net mvc app and we have come to the conclusion that we would like to make it work like github does... meaning we would like the user to receive the message both through our site and to his email inbox(this is somewhat easy to achieve with mvcmailer nuget).. but we would also like the option to have the user reply to the email (through his email client) and have that email be sent to our app (if you have used guthubs private messaging you should know what I mean)..... what is a common approach to implementing this feature?

See my comment regarding how to read emails from a mailbox.
I would use a message bus so that you are not limited to just internal and email notifications, for example you may wish to add SMS notifications in the future.
You may want to check out MassTransit or NServiceBus although for something like this it may be easier to just create your own.
public class Message {
public string Title {get;set;}
public string Body {get;set;}
}
public interface IMessageBus {
void Send(Message message);
}
public interface IMessageHandler {
void Handle(Message message);
}
public class InternalMessageHander : IMessageHandler {
public void Handle(Message message) {
// send internal message
}
}
public class EmailMessageHandler : IMessageHandler {
public void Handle(Message message) {
// send email
}
}
Your IMessageBus implementation would need to locate all the handlers (I would use an IoC container for this).
If you need to process large volumes of messages then I would recommend handing these off to a queue and processing these asynchronously (both MassTransit and NServiceBus support message queues but you could just as easily use a simple database table).
As far as reading emails, I would have background task that connects to the mailbox, downloads emails, parses them and updates your content.

Usually you put either something in the subject line or at the end of the body to track the email. Any UID will do.
Hope that helps.

Related

MassTransit configured with StructureMap - ContainerScoped not working

I've configured a class X with ContainerScope in my StructureMap configuration, but for some reason, when the app initially starts up and MassTransit consumer consumes the initial message, it creates the instance, but on subsequent messages received for that consumer, the consumer is recreated, but not object X (I would expect a new instance is created per message received). I know if I configure it with transient it'll work, but I just want a single instance of that class created for the entirety of the processing of that message.
Any help with this would be greatly appreciated.
When using MassTransit, creating a new consumer instance is the preferred behavior for each message. It is recommended that any state or behavior that needs to be maintained as a single instance across messages is done using a dependency of that consumer (which can be configured in the container by the application developer).
I realize that you are asking how to configure your consumer to be a singleton, and you can probably figure that out, but MassTransit will reconfigure the container to make it scoped for each message if you're using AddMassTransit/AddConsumer.
A better approach is to have your state configured:
public interface IConsumerState
{
}
public class ConsumerState :
IConsumerState
{
}
x.For<IConsumerState>().Use<ConsumerState>().Singleton();
Then, for MassTransit, configure your consumer where your consumer depends upon that interface.
public class Consumer :
IConsume<Message>
{
public Consumer(IConsumerState state)
{
_state = state;
}
public async Consume(ConsumeContext<Message> context)
{
}
}
x.AddMassTransit(m =>
{
m.AddConsumer<Consumer>();
m.AddBus(provider => Bus.Factory.CreateUsingInMemory(cfg =>
{
cfg.ConfigureEndpoints();
}
});
Using this approach, a new consumer is created for each message and the state is maintained/shared by all consumer instances.

SignalR with orleans how to pass SignalR from startup to grain

I am very new with orleans and trying to grasp everything with grains and so forth.
What i got is that in my startup.cs file i add the SignalR like this
public IServiceProvider ConfigureServices(IServiceCollection services)
{
Program.WriteConsole("Adding singletons");
services
.AddSingleton(achievementManager)
.AddMvc();
services.AddSingleton(SignalRClient);
return services.BuildServiceProvider();
}
So far everything is fine i can start my host/application and it connects to SignalR as it should. But what i cant wrap my head around is how do i get this down to my grain? if i had a controller i would simply send it down in the constructor on startup but how do i do this with a grain? Or can i even do it like this. Any guidance is appreciated.
In the grain then i want to do something like this
[StatelessWorker]
[Reentrant]
public class NotifierGrain : Grain, INotifierGrain
{
private HubConnection SignalRClient { get; }
public NotifierGrain(HubConnection signalRClient)
{
SignalRClient = signalRClient;
SignalRClient.SendAsync(Methods.RegisterService, Constants.ServiceName);
}
public Task NotifyClients(object message, MessageType type)
{
var registerUserNotification = (RegisterUserNotificationModel)message;
SignalRClient.SendAsync(Methods.RegisterUserToMultipleGroups, registerUserNotification.UserId, registerUserNotification.InfoIds);
}
return Task.CompletedTask;
}
Then i try to call the Notify method from another grain like this
var notifier = GrainFactory.GetGrain<INotifierGrain>(Constants.NotifierGrain);
await notifier.NotifyClients(notification, MessageType.RegisterUser);
But trying to do this ends up with an error like this
InvalidOperationException: Unable to resolve service for type 'Microsoft.AspNetCore.SignalR.Client.HubConnection' while attempting to activate 'User.Implementation.Grains.NotifierGrain'.
Orleans supports constructor injection, so you can inject the SignalRClient into your grain constructor. In your code you are already correctly registering the client using services.AddSingleton(SignalRClient), so I will focus on how to inject the type into your grain.
I do not know what the type the SignalR client object is, but in this example I assume that the type is "SignalRClient":
[StatelessWorker]
[Reentrant]
public class NotifierGrain : Grain, INotifierGrain
{
private readonly SignalRClient signalRClient;
public NotifierGrain(SignalRClient signalRClient)
{
this.signalRClient = signalRClient;
}
public async Task NotifyClients(object message, MessageType type)
{
var registerUserNotification = (RegisterUserNotificationModel)message;
await this.signalRClient.SendAsync(
MessageMethods.RegisterUserToMultipleGroups,
registerUserNotification.UserId,
registerUserNotification.infoIds);
}
}
Depends how you're thinking to use SignalR Server, if you're going to host your SignalR server with Microsoft Orleans for sure you need to have backplane to handle the Orleans cluster communications.
You can use SignalR Orleans which has everything done out of the box for you :)
Also if you need a reactive SignalR library for the frontend, you can use Sketch7 SignalR Client
PS I m one of the authors of both libraries.

How to auto update/refresh in grails view/site?

I am making an xmpp webchat application in Grails. I have a message listener that can log the recieved messages in console. But how can I do this dinamycally in a website ? I am new to webapp development so please dont down vote. I am guessing Ajax but not sure.
My listener:
private MessageListener messageListener = new MessageListener() {
#Override
public void processMessage(Chat chat, Message message) {
// 'from' and 'to' fields contains senders ids, e.g.
// 17792-1028#chat.quickblox.com/mac-167
// 17744-1028#chat.quickblox.com/Smack
String from = message.getFrom().split("#")[0];
String to = message.getTo().split("#")[0];
org.jivesoftware.smack.packet.Message.Type type = message.getType();
String tajp = type.toString();
println String.format(">>> Message received (from=%s, to=%s, type=%s): %s", from, to, tajp, message.getBody())
if (onMessageReceivedListener != null) {
onMessageReceivedListener.onMessageReceived(message);
}
}
}
I suggest you to take a look on the Events Push plugin. With that you can propagate your messages and notify your clients.
You will need:
Service that notify a new message
Controller method to call this service
Ajax request to the controller, sending the user message
JavaScript to handle incoming messages
I am new to webapp development
Web development is pretty different from desktop, so I suggest you to slow down to something more easy. There's other topics on StackOverflow that will introduce you to Grails.
Also, for webdev, it's essential to know about JavaScript, CSS and HTML for your front end.

SingnalR with Redis Send Msg to Specific ConnectionID

I am using SingalR for my Chat Application. Wanted to play with Redis
and SignalR but I cannot find an working example where i can send msg to
specific connectionId. Below Code that works for a single server instance.
But when i make it a Web Garden with 3 process it stops working as my
server instance that gets the message cannot find the connectionId
for that destination UserId to send the message.
private readonly static ConnectionMapping<string> _connections = new ConnectionMapping<string>();
public void Send(string sendTo, string message, string from)
{
string fromclientid = Context.QueryString["clientid"];
foreach (var connectionId in _connections.GetConnections(sendTo))
{
Clients.Client(connectionId).send(fromclientid, message);
}
Clients.Caller.send(sendTo, "me: " + message);
}
public override Task OnConnected()
{
int clientid = Convert.ToInt32(Context.QueryString["clientid"]);
_connections.Add(clientid.ToString(), Context.ConnectionId);
}
I have used the example below to setup my box and code but none of
them have examples for sending from one client to specific client or
group of specific clients.
http://www.asp.net/signalr/overview/performance-and-scaling/scaleout-with-redis
https://github.com/mickdelaney/SignalR.Redis/tree/master/Redis.Sample
The ConnectionMapping instance in your Hub class will not synced across different SignalR server instances. You need to use permanent external storage such as a database or a Windows Azure table. Refer to this link for more details:
http://www.asp.net/signalr/overview/hubs-api/mapping-users-to-connections

Any existing projects/software for sending hourly status emails

Classic requirement of checking system state and notifying users. Specifically, I'll be hitting the database every x-amount of time, getting some data, then sending out email notifications based on the results. Heck, this service might not even send out an email, but create a notification record in the database.
Seems like with IOC and configuration there could be a generic windows service that manages all this, along with metrics and management, in a simple manner.
In the past I've done email notifications by:
1) Running scripts as cron (at on Windows) jobs
2) running custom executables as cron/at jobs
3) using something like SQLServer's DatabaseMail.
4) Custom NT Services that run all the time monitoring things.
Is there any open source projects that manages this? It's the type of code I've written many, many times in various platforms, but don't want to spend the few days doing it now.
The only thing I found so far was Quartz.Net
Thanks
I just create a Windows service and use the Reactive Extensions to schedule tasks. If you don't need as much flexibility as cron offers, this works fine. Here's an abstract hourly task runner. (uses log4net)
public abstract class HourlyTask : IWantToRunAtStartup
{
protected readonly ILog Log = LogManager.GetLogger(typeof (HourlyTask).FullName);
private IDisposable _Subscription;
private void ExecuteWithLog()
{
Log.Debug("Triggering " + GetType());
try
{
Execute();
}
catch (Exception exception)
{
Log.Error("Hourly execution failed", exception);
}
}
public abstract void Execute();
public void Run()
{
_Subscription = Observable
.Interval(TimeSpan.FromMinutes(1))
.Select(x => DateTime.Now.Hour)
.DistinctUntilChanged()
.Subscribe(i => ExecuteWithLog());
}
public void Stop()
{
if (_Subscription == null)
{
return;
}
_Subscription.Dispose();
}
}
Then in your start up method you can just resolve all IWantToRunAtStartup instances and call Run() on them.

Resources