How to create a publisher within a console application - c#

I'm just starting out with NServiceBus and have updated the PubSub sample to work with .NET 4.0 Framework. That's working perfectly ok. This runs one publisher and two subscribers within the "NServiceBus.Host.exe" environment - so it is that which takes responsibility for setting up an instance of the Bus and doing any relevant subscriptions. That's all working fine (as you'd expect) but I'm now trying to move the publisher out of being run within "NServiceBus.Host.exe" into it's own console application (eventually I would like to publish messages from a website so this seems a good small step in that direction).
If I start the 3 projects (my console app, Sub1 and Sub2) it creates 5 msmq on my local machine, but instead of the endpoint.config...subscriptions Q, it creates a generic "nservicebus_subscriptions" Q. If I enable journals, I see that the MyPublisherInputQueue has three (processed) completion messages with an errorcode 0, whilst the subscriber1inputqueue and subscriber2inputqueue each have one. This all seems good, but if I then publish messages, the publisher doesn't appear to throw any errors, but no messages make it as far as the subscribers (they just sit waiting for a message). Also no messages appear in either the new message or journal for any of the MQs.
I'm obviously missing some step(s) - Is the console application not opening itself up for subscriptions? If so, what steps are needed to do that? What steps am I missing that run when you host the publisher in the nservicebus.host.exe?
To create the console application I've done the following:
Within the pubsub solution, created a console application.
Added references in the console application to mymessages, nservicebus.dll and nservicebus.core.dll
From the existing pub code and example on the NServiceBus website, added following code to "Main()"
Code:
IBus Bus = Configure.With()
.Log4Net()
.DefaultBuilder()
.MsmqSubscriptionStorage()
.XmlSerializer()
.MsmqTransport()
.UnicastBus()
.LoadMessageHandlers()
.CreateBus()
.Start();
bool publishIEvent = true;
do
{
Console.ReadLine();
var eventMessage = publishIEvent ? Bus.CreateInstance<IEvent>() : new EventMessage();
eventMessage.EventId = Guid.NewGuid();
eventMessage.Time = DateTime.Now.Second > 30 ? (DateTime?)DateTime.Now : null;
eventMessage.Duration = TimeSpan.FromSeconds(99999D);
Bus.Send(eventMessage);
Console.WriteLine("Published event with Id {0}.", eventMessage.EventId);
} while (true);
Created an app.config for the new console application using the contents of the existing "publisher" app.config.
Added "NServiceBus.Integration" to command line arguments for console application project.

If you look at your logs, it is likely that NServiceBus is telling you that you need to have your publisher be configured to be transactional. The way to do that is to include .IsTransactional(true) after .MsmqTransport().

Related

Need to receive Azure Service Bus Messages on a .NET Framework 4.6.1 application

I Have an Azure Cloud Function that pushes messages to a queue under a Azure Service Bus namespace. The receiver for this queue is a .NET Framework 4.6.1 application which has the Service Bus SDK[Azure.Messaging.ServiceBus] installed. Problem is that the code sample references online are mostly for console applications which has Program.cs. My application has a Global.asax file, i believe, as the startup file.
So I referred the code from here. Placed it in Global.asax but not able to receive messages.
What has been tried is, I've created a console application on the same VM as the one which has the application mentioned above. Installed the SDK and pasted the listener code. It was able to receive messages from Service bus, which strikes off any possibilities of network misconfiguration. So most likely its the setup at .net 4.6.1 application level
Can anyone help with a sample service bus receiver/listener code?
Create a Service Bus in Azure.
And create a Queue.
And pushed some messages to the queue as per the link given.
For Queue_AccessKey string, copy the string from azure as shown below.
Use the Console application and use the below code in .Net 4.6.1 framework.
For this the NuGet "Microsoft.Azure.ServiceBus" version="5.2.0" targetFramework="net461” has to be installed in the project.
And the below namespace has to be used in the code.
using Microsoft.Azure.ServiceBus;
connectionString = new ServiceBusConnectionStringBuilder(Queue_AccessKey);
qClient = new QueueClient(connectionString, ReceiveMode.ReceiveAndDelete, RetryPolicy.Default);
var msgHandler = new MessageHandlerOptions(ListenerExceptionHandler)
{
MaxConcurrentCalls = 1,
AutoComplete = false
};
qClient.RegisterMessageHandler(ReceiveMessageFromQueue, msgHandler);

Publishing an NServiceBus 4 event from a windows forms application

I'm trying to write a test harness to send NServiceBus commands and events. I've managed to get it to send commands, and it happily calls publish, but it doesn't handle subscription requests when the app starts up so the publish call doesn't actually send any messages.
How do I tell NServiceBus to process the subscription requests when I initialise the Bus?
Here's the initialisation code so far:
Bus = Configure.With(LoadAssemblies())
.DefaultBuilder()
.UnicastBus()
.ImpersonateSender(true)
.DefiningCommandsAs(AllValidCommands)
.DefiningMessagesAs(AllValidMessages)
.DefiningEventsAs(AllValidEvents)
.RavenSubscriptionStorage()
.CreateBus();
In case of Pub/sub mode, you need to make sure, you run Publisher first & then subscribe .... check these link http://dennis.bloggingabout.net/2015/10/28/nservicebus-publish-subscribe-tutorial/

Push Notifications with PushSharp - the basics

I need to push notifications to tens of thousands of iOS devices that my app installed. I'm trying to do it with PushSharp, but I'm missing some fundamental concepts here. At first I tried to actually run this in a Windows service, but couldn't get it work - getting null reference errors coming from _push.QueueNotification() call. Then I did exactly what the documented sample code did and it worked:
PushService _push = new PushService();
_push.Events.OnNotificationSendFailure += new ChannelEvents.NotificationSendFailureDelegate(Events_OnNotificationSendFailure);
_push.Events.OnNotificationSent += new ChannelEvents.NotificationSentDelegate(Events_OnNotificationSent);
var cert = File.ReadAllBytes(HttpContext.Current.Server.MapPath("..pathtokeyfile.p12"));
_push.StartApplePushService(new ApplePushChannelSettings(false, cert, "certpwd"));
AppleNotification notification = NotificationFactory.Apple()
.ForDeviceToken(deviceToken)
.WithAlert(message)
.WithSound("default")
.WithBadge(badge);
_push.QueueNotification(notification);
_push.StopAllServices(true);
Issue #1:
This works perfectly and I see the notification pop up on the iPhone. However, since it's called a Push Service, I assumed it would behave like a service - meaning, I instantiate it and call _push.StartApplePushService() within a Windows service perhaps. And I thought to actually queue up my notifications, I could do this on the front-end (admin app, let's say):
PushService push = new PushService();
AppleNotification notification = NotificationFactory.Apple()
.ForDeviceToken(deviceToken)
.WithAlert(message)
.WithSound("default")
.WithBadge(badge);
push.QueueNotification(notification);
Obviously (and like I already said), it didn't work - the last line kept throwing a null reference exception.
I'm having trouble finding any other kind of documentation that would show how to set this up in a service/client manner (and not just call everything at once). Is it possible or am I missing the point of how PushSharp should be utilized?
Issue #2:
Also, I can't seem to find a way to target many device tokens at once, without looping through them and queuing up notifications one at a time. Is that the only way or am I missing something here as well?
Thanks in advance.
#baramuse explained it all, if you wish to see a service "processor" you can browse through my solution on https://github.com/vmandic/DevUG-PushSharp where I've implemented the workflow you seek for, i.e. a win service, win processor or even a web api ad hoc processor using the same core processor.
From what I've read and how I'm using it, the 'Service' keyword may have mislead you...
It is a service in a way that you configure it once and start it.
From this point, it will wait for you to push new notifications inside its queue system and it will raise events as soon as something happens (delivery report, delivery error...). It is asynchronous and you can push (=queue) 10000 notifications and wait for the results to come back later using the event handlers.
But still it's a regular object instance you will have to create and access as a regular one. It doesn't expose any "outside listener" (http/tcp/ipc connection for example), you will have to build that.
In my project I created a small selfhosted webservice (relying on ServiceStack) that takes care about the configuration and instance lifetime while only exposing the SendNotification function.
And about the Issue #2, there indeed isn't any "batch queue" but as the queue function returns straight away (enqueue and push later) it's just a matter of a looping into your device tokens list...
public void QueueNotification(Notification notification)
{
if (this.cancelTokenSource.IsCancellationRequested)
{
Events.RaiseChannelException(new ObjectDisposedException("Service", "Service has already been signaled to stop"), this.Platform, notification);
return;
}
notification.EnqueuedTimestamp = DateTime.UtcNow;
queuedNotifications.Enqueue(notification);
}

Keep C# application running

I'm building a Windows Service that uses FileSystemWatcher, and runs in the background.
I don't want to keep on uninstalling and installing the service every time I want to debug, so would like to do most of my development in a normal program before moving it into a service. But I'm quite new to this, and when I run it, it just runs through the block and exits.
What would be a good way to keep the program running?
http://einaregilsson.com/run-windows-service-as-a-console-program/
I've used this before to debug my service as a Console application based on whether its running in an interactive user environment.
public partial class DemoService : ServiceBase
{
static void Main(string[] args)
{
DemoService service = new DemoService();
if (Environment.UserInteractive)
{
service.OnStart(args);
Console.WriteLine("Press any key to stop program");
Console.Read();
service.OnStop();
}
else
{
ServiceBase.Run(service);
}
}
while (true)
{
// Execute your program's functionality here.
}
I wrote a 7 part series a while ago titled: Building a Windows Service. It covers all the intricacies of building services, making them friendly to debug, and self-installing.
The basic feature set I was looking for was as follows:
Building a service that can also be used from the console
Proper event logging of service startup/shutdown and other activities
Allowing multiple instances by using command-line arguments
Self installation of service and event log
Proper event logging of service exceptions and errors
Controlling of start-up, shutdown and restart options
Handling custom service commands, power, and session events
Customizing service security and access control
The final result was a Visual Studio project template that creates a working service, complete with all of the above, in a single step. It's been a great time saver for me.
see Building a Windows Service – Part 7: Finishing touches for a link to the project template and install instructions.
Here’s documentation from MSDN # http://msdn.microsoft.com/en-us/library/7a50syb3(v=vs.80).aspx?ppud=4 . I have tried it before and it works under .NET Framework 3.x. I could not find my descriptive notes on it, at the moment.
Use the pragma #If DEBUG for debugging purposes like console outputs. Another is using the Debug object.
If you have any trouble with this, say so. I may be able to find my notes or make a Windows Service app myself, just to see if the steps on MSDN still work.

Problem with calling Console application (WCF Service) from webform

I am using a ASP.net webform application to run an existing console application which get all records from DB and send them through a third party WCF service. Locally everything is working fine. When I run the application it opens the console, gets the records and sends them. But now I pushed my files over to Test server along with the exe file and related config files. But when I access the application through the browser (test url) I get the same error message time and again and I don't see the console window. Sometimes everything works fine but never two times in a row.
The error message is:
"There was no end point listening at '.....svc' that could accept message. This is often caused by incorrect address or soap action.
System.net.webexception. Remote name could not be resolved
at System.Net.HttpWebRequest.GetRequestStream
at System.ServiceModel.Channels.HttpOutput.Webrequest.HttpOutput.GetOutputStream()
The code I have used in the webform to call console application is:
ProcessStartInfo p = new ProcessStartInfo();
p.Arguments = _updateNow.ToString();
p.FileName="something";
p.UseShellExecute = false;// tried true too without luck
Process.Start(p);
Error message denotes "there is no end point" and sounds like there is problem with the WCF service but if I double click the executable in Test there is no problem. What could be the possible problem or should I redo the console application functionality to my main webform application?
Update: After adding Thread.Sleep(3000) after Process.Start(p), I'm having no problem. So seems like main application is not waiting for the batch process to complete. How to solve this problem?
It seems like there is a short delay between starting the console application and the WCF web service becoming initialise and available to use - this is to be expected.
You could either:
Work around the issue using Thread.Sleep() and possibly with a couple of catch - retry blocks.
You could have the console application report to the creating process when it is ready to recieve requests (for example by having it write to the standard output and using redirected streams).
However at this point I'd probably reconsider the architecutre slightly - starting a new process is relativley costly, and on top of that initialising a WCF serice is also relatively costly too. If this is being done once per request then as well as the above timing issues you are also incurring performance penalties.
Is it not possible to change the architecutre slightly so that a single external process (for example a Windows service) is used for all requests instead of spawning a new process each time?

Categories