Nservicebus configuration in WPF - wpf

Using the pub/sub sample i managed to get multiple instances of the same console app to read all messages sent from the publisher. What I did whas this:
namespace Subscriber1
{
public class EndpointConfig : IConfigureThisEndpoint, AsA_Server
{
}
public class OverrideInputQueue : IWantCustomInitialization
{
public void Init()
{
Configure
.Instance
.Configurer
.ConfigureComponent<MsmqTransport>(NServiceBus.ObjectBuilder.ComponentCallModelEnum.None)
.ConfigureProperty(p => p.InputQueue, Guid.NewGuid());
}
}
}
How do i setup a wpf app to have multiple instances all read notifications from the publisher??
Using the code above doesn't do it for me because those lines of code will never be hit.
In my wpf app i reference the NServiceBus host, I add this to the windows code behind:
public Window1()
{
InitializeComponent();
this.Title = App.AppId.ToString();
var bus = NServiceBus.Configure.With()
.DefaultBuilder()
.XmlSerializer()
.MsmqTransport()
.IsTransactional(true)
.PurgeOnStartup(false)
.UnicastBus()
.ImpersonateSender(false)
.LoadMessageHandlers()
.CreateBus()
.Start();
}
and I put the I "OverrideInputQueue : IWantCustomInitialization"-part in my endpoint config.
But as I said that part never gets hit. The result is that when you start up two instances of the app, they take turns in picking up the message sent from the publisher. I want both instances to receive ALL messages.
What have I missed?
/Johan

The problem is that IWantCustomInitialization is only relevant when using the NServiceBus.Host.exe process. What you need to do in your initialization code is this:
var bus = NServiceBus.Configure.With()
.DefaultBuilder()
.XmlSerializer()
.MsmqTransport()
.IsTransactional(true)
.PurgeOnStartup(false)
.RunCustomAction( () => Configure.Instance.Configurer.ConfigureProperty<MsmqTransport>(p => p.InputQueue, Guid.NewGuid()) )
.UnicastBus()
.ImpersonateSender(false)
.LoadMessageHandlers()
.CreateBus()
.Start();

Related

Elegant way to handle exceptions in Test cases of MVVM Light's ViewModel

I am working on a wpf application using mvvm light toolkit. Whenever something goes outside the business logic we'll prompt the user with the message box and I send the message from view model to view using
Messenger.Default.Send(Token,"Some text message here");
Now I am writing test cases for view models and in some cases, Code Under Test is linked with such message calls. These are exceptions to me but test cases does not treat them exception as long as it is not being called by throw exception("message")
Suggestions.
Assuming you are sending message from VM to View, which handles the actual "showing logic", then just register for the message in your VM tests and verify that it has been sent/received. For example:
[TestMethod]
public void SendSomethingBadHappenedMessageTest()
{
const string expected = "oh noes!";
string actual = null;
// Register for message to ensure message was sent from VM
Messenger.Default.Register<SomethingBadHappenedMessage>(this,
message => actual = message.Message);
// Assuming command triggers Messenger.Send
_viewModel.SomethingBadHappenedCommand.Execute(expected);
Assert.AreEqual(expected, actual);
}
If you test for exceptions, just mark test method with ExpectedException attribute.
I assume you are trying to verify that the business logic detects a problem and the correct message box is being "shown" in your test case. If that's so, here's what I do:
Instead of using messaging, create a UserNotificationService and IUserNotificationService interface. The concrete implementation would be something like:
public class UserNotificationService : IUserNotificationService
{
public void MessageBox(string message)
{
// code to make the message box pop up goes here
}
}
Inject IUserNotificationService in your view model's constructor (you already have SimpleIoC since you are using mvvm-light) and use it to communicate with the user.
When unit testing, either mock the IUserNotificationService or create a new FakeUserNotificationService class that is capable of verifying the correct message/error was sent. Put that in the constructor of the view model being tested.
public class FakeUserNotificationService : IUserNotificationService
{
public void MessageBox(string message)
{
LastMessage = message;
}
public string LastMessage {get; set;}
}
In your test:
var ns = new FakeUserNotificationService();
var viewModel = new MyViewModel(ns);
viewModel.DoSomethingBad();
Assert.AreEqual(ns.LastMessage, "expected error message");

WCF sending information to WPF application

I want to send data from WCF to my desktop application while executing a service method.
The WCF service is hosted in windows service.
For example: In my service I am counting from 1 to 100 and when I am hitting 10,20,30 etc I want to set that value on my textbox.
This may be done using duplex channels services:
http://msdn.microsoft.com/en-us/library/ms731064.aspx
Be careful however : this will not work if the server can't reach the client : for example if you are behind a proxy.
I've simpy passed that with get/set like below: (Maybe someone will search smthing similar in future)
public class CallbackHandler : WCFService.IWCFServiceCallback
{
public ListBox LtBox { get; set; }
public void Message(string result)
{
LtBox.Items.Add(result);
}
}
InstanceContext instanceContext = new InstanceContext(new CallbackHandler() { LtBox=this.ltBox });
Where ltBox is my Listbox in desktop application.
Thanks all for help.

SignalR not working when using sql server as backlplane

I've tried to setup the following configuration with SQL Server and SignalR
http://www.asp.net/signalr/overview/performance/scaleout-with-sql-server
Everything seems to be setup correctly, if I profile SQL server I can see SignalR making calls to the DB, but when I call the hub to send a message to all the clients connected, the message is never sent to the connected browsers.
any idea what could be the problem?
Thank you #smnbss, you just saved my life with your comment inside your question. Just to make it clear for everyone in the future with the same problem, here is the wrong implementation: I was getting the context only once like:
public class SyncService : ISyncService
{
private IHubContext StatusChangeHub { get; set; }
public GatewaySyncService()
{
StatusChangeHub = GlobalHost.ConnectionManager.GetHubContext<Hub>();
}
public void SyncStatusChange(Status newStatus)
{
StatusChangeHub.Clients.All.onStatusChange(newStatus);
}
}
But somehow this only work while not using a backplane. And the correct implementation: you need to get the context everytime you want to send a message:
public class SyncService : ISyncService
{
public void SyncStatusChange(Status newStatus)
{
var context = GlobalHost.ConnectionManager.GetHubContext<Hub>();
context.Clients.All.onStatusChange(newStatus);
}
}

DataContract doesn't work after publish into web site

I tried to solve by myself, but... Looks like I need help from people.
I have Business Silverlight application with WCF RIA and EntityFramework. Access to Database I get via LinqToEntites.
Common loading data from database I making by this:
return DbContext.Customers
This code returns full Customers table from DataBase. But sometimes I do not need to show all data. Easy way is use linq filters in client side by next code:
public LoadInfo()
{
...
var LO1 = PublicDomainContext.Load(PublicDomainContext.GetCustomersQuery());
LO1.Completed += LO1Completed;
...
}
private void LO1Completed(object sender, EventArgs eventArgs)
{
...
DatatViewGrid.ItemsSource = null;
DatatViewGrid.ItemsSource = loadOperation.Entities.Where(c=>c ...filtering...);
//or PublicDomainContext.Customers.Where(c=>c ...filtering...)
...
}
However this way has very and very important flaw: all data passing from server to client side via DomainService may be viewed by applications like Fiddler. So I need to come up with another way.
Task: filter recieving data in server side and return this data.
Way #1: LinqToEntites has a beautiful projection method:
//MSDN Example
var query =
contacts.SelectMany(
contact => orders.Where(order =>
(contact.ContactID == order.Contact.ContactID)
&& order.TotalDue < totalDue)
.Select(order => new
{
ContactID = contact.ContactID,
LastName = contact.LastName,
FirstName = contact.FirstName,
OrderID = order.SalesOrderID,
Total = order.TotalDue
}));
But, unfortunately, DomainServices cannot return undefined types, so this way won't work.
Way #2: I found next solution - make separate DTO classes (DataTransferObject). I just read some samples and made on the server side next class:
[DataContract]
public partial class CustomerDTO
{
[DataMember]
public int ISN { get; set; }
[DataMember]
public string FIO { get; set; }
[DataMember]
public string Listeners { get; set; }
}
And based this class I made a row of methods which return filtered data:
[OperationContract]
public List<CustomerDTO> Customers_Common()
{
return DbContext.Customers....Select(c => new CustomerDTO { ISN = c.ISN, FIO = c.FIO, Listeners = c.Listeners }).ToList();
}
And this works fine, all good...
But, there is strange problem: running application locally does not affect any troubles, but after publishing project on the Web Site, DomainService returns per each method HTTP 500 Error ("Not Found" exception). Of course, I cannot even LogIn into my application. DomainService is dead. If I delete last class and new methods from application and republish - all works fine, but without speacial filtering...
The Question: what I do wrong, why Service is dying with new classes, or tell me another way to solve my trouble. Please.
U P D A T E :
Hey, finally I solved this!
There is an answer: Dynamic query with WCF RIA Services
Your best shot is to find out what is causing the error. For that, override the OnError method on the DomainService like this:
protected override void OnError(DomainServiceErrorInfo errorInfo)
{
/* Log the error info to a file. Don't forget inner exceptions.
*/
base.OnError(errorInfo);
}
This is useful, because only two exceptions will be passed to the client, so if there are a lot of nested inner exceptions, you should still be able to see what actually causes the error.
In addition, you can inspect the error by attaching the debugger to the browser instance you are opening the site with. In VS2010 this is done by doing [Debug] -> [Attach to Process] in the menu-bar.

How do oob silverlight application communicate through windows

If I have two windows in an oob application how do I communicate between them?
This is the new feature of silverlight 5 that allows for multiple windows.
They run in a common application. Hence they share the same static data. The scope of communication choices are therefore very large. Here is an example:-
public class MessageEventArgs : EventArgs
{
public MessageEventArgs(object payload)
{
Payload = payload;
}
public object Payload {get; private set; }
}
public class Messenger
{
private static readonly Messenger _current = new Messenger();
public static Messenger Current { get { return _current; } }
public event EventHandler<MessageEventArgs> MessageReceived;
public void Send(object payload)
{
if (MessageReceived != null)
MessageReceived(this, new MessageEventArgs(payload));
}
}
All windows can attach a handler to Messenger.Current.MessageReceived (just be sure to detach when the window closes) and any window can call Messenger.Current.Send.
Ok so you wouldn't actually use this code its a bit rubbish, the point is Windows in SL5 are not isolated. You can create whatever internal application communication mechanism you need.
Option 1: MVVM Pattern
Both windows share a reference to the same view-model. Changes made by one are seen by both.
Option 2: Normal references
Window A can how a refernce to Windows B when it creates it.
Option 3: Message Passing
You can have a global event that you subscribe to in the Load event. (Make sure you unsubscribe in the Unload event or you will leak memory!) Windows can post messages to that event which the other windows listen for.

Resources