I'm trying to register a generic request handler for a generic request, but I'm getting the error below when calling
await _mediator.Send(new ExchangeOrderRequest<ExchangeOrderResponseSuccessEvent>());
System.InvalidOperationException: Handler was not found for request of
type
MediatR.IRequestHandler`2[MyNamespace.ExchangeOrderRequest`1[MyNamespace.ExchangeOrderResponseSuccessEvent],MediatR.Unit]`.
Register your handlers with the container. See the samples in GitHub
for examples.
As side note, for giggles, I was able to inject an instance of IRequestHandler<ExchangeOrderRequest<ExchangeOrderResponseSuccessEvent>> into a controller just fine.
// Some assembly scanning, doesn't find my handler
services.AddMediatR(typeof(Startup), typeof(ExchangeOrderRequest), typeof(IDocumentMessage), typeof(OrderExecution.Handler));
// Try to manually add the handler. Still doesn't find it
services.AddTransient<IRequestHandler<ExchangeOrderRequest<ExchangeOrderResponseSuccessEvent>>, ExchargeOrderRequestHandler<ExchangeOrderResponseSuccessEvent, ExchangeOrderRequest<ExchangeOrderResponseSuccessEvent>>>();
public class ExchargeOrderRequestHandler<TEvent, TRequest> : IRequestHandler<TRequest>
where TRequest : ExchangeOrderRequest<TEvent>
where TEvent : ExchangeOrderEvent
{
// Stuff
}`
public class ExchangeOrderRequest<T>: DocumentMessage, IRequest where T: ExchangeOrderEvent
{
// Stuff
}
public class ExchangeOrderEvent : IEvent
{
// Stuff
}
What am I missing here?
I'm having the same issue...
However, I am able to register the handler like this..
services.AddTransient(typeof(IRequestHandler<,>), typeof(CustomHandler<,>));
This works for only one generic handler... I have many... I need to be able to do something like this:
services.AddTransient(typeof(IRequestHandler<,>), typeof(CustomHandler1<,>));
services.AddTransient(typeof(IRequestHandler<,>), typeof(CustomHandler2<,>));
//etc...
When I try and do this... no matter what command I send to MediatR it resolves the last handler I registered.. So naturally the type constraints are violoated and a runtime exception occurs.
Related
https://docs.particular.net/nservicebus/testing/ has a very neat example of how to test a simple Saga. Unfortunately it does not explain, how to do the same with a SqlSaga - ie. a Saga with persistence of state to a database.
Given this saga:
public class SomeFancySaga : SqlSaga<MySagaData>,
IAmStartedByMessages<ImportantCommand>
{
protected override string CorrelationPropertyName => nameof(Data.MyPrimaryKey);
protected override void ConfigureMapping(IMessagePropertyMapper mapper)
{
mapper.ConfigureMapping<ImportantCommand>(x => x.CommandId);
}
public async Task Handle(ImportantCommand command, IMessageHandlerContext context)
{
if (Data.State == MyState.ReadyForUse)
<do some stuff>
}
...
}
If I try to write test-code like the example in the link, I would do something like this:
// arrange
var context = new NServiceBus.Testing.TestableMessageHandlerContext();
var command = ImportantCommand.Create();
var sut = new CreateSomeFancySaga();
// act
sut.Handle(command, context);
// assert
...
The call to sut.Handle() will throw a NullReferenceException, because the Saga property Data has not been initialized.
How do I correctly wireup the saga for testing so that:
Data is initialized
A real database connection is not really needed
We have a related code sample showing unit testing in more detail: https://docs.particular.net/samples/unit-testing/. That includes a couple of tests for saga (SagaTests.cs).
You can take this as a starting point and modify the saga tests in the following way:
Add NServiceBus.Persistence.Sql package.
Modify the DiscountPolicy policy saga to inherit from SqlSaga instead of a Saga.
Resolve compilation errors (add missing method and property, you can keep them empty, plus remove the ConfigureHowToFindSaga method).
I hope that helps, but let me know if there's anything missing or your scenario can't be tested this way.
I'm using nServiceBus 5 and have created a number of host endpoints, two of which listen for database changes. (The specifics of how to do this can be found here). The intention is to have a service running in the background which publishes an event message using the Bus when notified to do so by the database listener.
The code which creates the database listener object and handles events is in the Start method, implemented as part of IWantToRunWhenBusStartsAndStops.
So - Is putting the code here likely to cause problems later on, for example if an exception is thrown (yes, I do have try/catch blocks, but I removed them from the sample code for clarity)? What happens when the Start method finishes executing?
Would I be better off with a constructor on my RequestNewQuoteSender class to instantiate the database listener as a class property and not use the Start method at all?
namespace MySample.QuoteRequest
{
public partial class RequestNewQuoteSender : IWantToRunWhenBusStartsAndStops
{
public void Start()
{
var changeListener = new DatabaseChangeListener(_ConnectionString);
// Assign the code within the braces to the DBListener's onChange event
changeListener.OnChange += () =>
{
// code to handle database change event
changeListener.Start(_SQLStatement);
};
// Now everything has been set up.... start it running.
changeListener.Start(_SQLStatement);
}
public void Stop() { LogInfo("Service Bus has stopped"); }
}
}
Your code seems fine to me.
Just a few small things:
Make changeListener a class field, so that it won't be GC (not 100% sure if it would be but just to make sure);
Unsubscribe from OnChange on the Stop() method;
You may also want to have a "lock" around changeListener.Start(_SQLStatement); and the Stop so that there are no racing conditions (I leave that one up to you to figure out if you need it or not);
Does this make sense ?
The problem: I'm crashing when I want to render my incoming data which was retrieved asynchronously.
The app starts and displays some dialog boxes using XAML. Once the user fills in their data and clicks the login button, the XAML class has in instance of a worker class that does the HTTP stuff for me (asynchronously using IXMLHTTPRequest2). When the app has successfully logged in to the web server, my .then() block fires and I make a callback to my main xaml class to do some rendering of the assets.
I am always getting crashes in the delegate though (the main XAML class), which leads me to believe that I cannot use this approach (pure virtual class and callbacks) to update my UI. I think I am inadvertently trying to do something illegal from an incorrect thread which is a byproduct of the async calls.
Is there a better or different way that I should be notifying the main XAML class that it is time for it to update it's UI? I am coming from an iOS world where I could use NotificationCenter.
Now, I saw that Microsoft has it's own Delegate type of thing here: http://msdn.microsoft.com/en-us/library/windows/apps/hh755798.aspx
Do you think that if I used this approach instead of my own callbacks that it would no longer crash?
Let me know if you need more clarification or what not.
Here is the jist of the code:
public interface class ISmileServiceEvents
{
public: // required methods
virtual void UpdateUI(bool isValid) abstract;
};
// In main XAML.cpp which inherits from an ISmileServiceEvents
void buttonClick(...){
_myUser->LoginAndGetAssets(txtEmail->Text, txtPass->Password);
}
void UpdateUI(String^ data) // implements ISmileServiceEvents
{
// This is where I would render my assets if I could.
// Cannot legally do much here. Always crashes.
// Follow the rest of the code to get here.
}
// In MyUser.cpp
void LoginAndGetAssets(String^ email, String^ password){
Uri^ uri = ref new URI(MY_SERVER + "login.json");
String^ inJSON = "some json input data here"; // serialized email and password with other data
// make the HTTP request to login, then notify XAML that it has data to render.
_myService->HTTPPostAsync(uri, json).then([](String^ outputJson){
String^ assets = MyParser::Parse(outputJSON);
// The Login has returned and we have our json output data
if(_delegate)
{
_delegate->UpdateUI(assets);
}
});
}
// In MyService.cpp
task<String^> MyService::HTTPPostAsync(Uri^ uri, String^ json)
{
return _httpRequest.PostAsync(uri,
json->Data(),
_cancellationTokenSource.get_token()).then([this](task<std::wstring> response)
{
try
{
if(_httpRequest.GetStatusCode() != 200) SM_LOG_WARNING("Status code=", _httpRequest.GetStatusCode());
String^ j = ref new String(response.get().c_str());
return j;
}
catch (Exception^ ex) .......;
return ref new String(L"");
}, task_continuation_context::use_current());
}
Edit: BTW, the error I get when I go to update the UI is:
"An invalid parameter was passed to a function that considers invalid parameters fatal."
In this case I am just trying to execute in my callback is
txtBox->Text = data;
It appears you are updating the UI thread from the wrong context. You can use task_continuation_context::use_arbitrary() to allow you to update the UI. See the "Controlling the Execution Thread" example in this document (the discussion of marshaling is at the bottom).
So, it turns out that when you have a continuation, if you don't specify a context after the lambda function, that it defaults to use_arbitrary(). This is in contradiction to what I learned in an MS video.
However by adding use_currrent() to all of the .then blocks that have anything to do with the GUI, my error goes away and everything is able to render properly.
My GUI calls a service which generates some tasks and then calls to an HTTP class that does asynchronous stuff too. Way back in the HTTP classes I use use_arbitrary() so that it can run on secondary threads. This works fine. Just be sure to use use_current() on anything that has to do with the GUI.
Now that you have my answer, if you look at the original code you will see that it already contains use_current(). This is true, but I left out a wrapping function for simplicity of the example. That is where I needed to add use_current().
I have a component with a custom model (extending the wicket standard Model class). My model loads the data from a database/web service when Wicket calls getObject().
This lookup can fail for several reasons. I'd like to handle this error by displaying a nice message on the web page with the component. What is the best way to do that?
public class MyCustomModel extends Model {
#Override
public String getObject() {
try {
return Order.lookupOrderDataFromRemoteService();
} catch (Exception e) {
logger.error("Failed silently...");
// How do I propagate this to the component/page?
}
return null;
}
Note that the error happens inside the Model which is decoupled from the components.
Handling an exception that happens in the model's getObject() is tricky, since by this time we are usually deep in the response phase of the whole request cycle, and it is too late to change the component hierarchy. So the only place to handle the exception is very much non-local, not anywhere near your component or model, but in the RequestCycle.
There is a way around that though. We use a combination of a Behavior and an IRequestCycleListener to deal with this:
IRequestCycleListener#onException allows you to examine any exception that was thrown during the request. If you return an IRequestHandler from this method, that handler will be run and rendered instead of whatever else was going on beforehand.
We use this on its own to catch generic stuff like Hibernate's StaleObjectException to redirect the user to a generic "someone else modified your object" page. If you
For more specific cases we add a RuntimeExceptionHandler behavior:
public abstract class RuntimeExceptionHandler extends Behavior {
public abstract IRequestHandler handleRuntimeException(Component component, Exception ex);
}
In IRequestCycleListener we walk through the current page's component tree to see whether any component has an instance of RuntimeExceptionHandler. If we find one, we call its handleRuntimeException method, and if it returns an IRequestHandler that's the one we will use. This way you can have the actual handling of the error local to your page.
Example:
public MyPage() {
...
this.add(new RuntimeExceptionHandler() {
#Override public IRequestHandler handleRuntimeException(Component component, Exception ex) {
if (ex instanceof MySpecialException) {
// just an example, you really can do anything you want here.
// show a feedback message...
MyPage.this.error("something went wrong");
// then hide the affected component(s) so the error doesn't happen again...
myComponentWithErrorInModel.setVisible(false); // ...
// ...then finally just re-render this page:
return new RenderPageRequestHandler(new PageProvider(MyPage.this));
} else {
return null;
}
}
});
}
Note: This is not something shipped with Wicket, we rolled our own. We simply combined the IRequestCycleListener and Behavior features of Wicket to come up with this.
Your model could implement IComponentAssignedModel, thus being able to get hold on the owning component.
But I wonder how often are you able to reuse MyCustomModel?
I know that some devs advocate creating standalone model implementations (often in separate packages). While there are general cases where this is useful (e.g. FeedbackMessagesModel), in my experience its easier to just create inner classes which are component specific.
Being the main issue here that Models are by design decoupled from the component hierarchy, you could implement a component-aware Model that will report all errors against a specific component.
Remember to make sure it implements Detachable so that the related Component will be detached.
If the Model will perform an expensive operation, you might be interested in using LoadableDetachableModel instead (take into account that Model.getObject() might be called multiple times).
public class MyComponentAwareModel extends LoadableDetachableModel {
private Component comp;
public MyComponentAwareModel(Component comp) {
this.comp = comp;
}
protected Object load() {
try {
return Order.lookupOrderDataFromRemoteService();
} catch (Exception e) {
logger.error("Failed silently...");
comp.error("This is an error message");
}
return null;
}
protected void onDetach(){
comp.detach();
}
}
It might also be worth to take a try at Session.get().error()) instead.
I would add a FeedbackPanel to the page and call error("some description") in the catch clause.
You might want to simply return null in getObject, and add logic to the controller class to display a message if getObject returns null.
If you need custom messages for different fail reasons, you could add a property like String errorMessage; to the model which is set when catching the Exception in getObject - so your controller class can do something like this
if(model.getObject == null) {
add(new Label("label",model.getErrorMessage()));
} else {
/* display your model object*/
}
I have just encountered a strange problem. I have fixed it, but I am hoping that you may be able to help me better understand what actually went wrong. I'll start with an explanation of what happened. The problem concerns a simple MVC3 RC1 app.
In my app's master page there is a call to an action on a controller to render a login-form:
#Html.Action("LoginForm", "Account")
The action method on the AccountController class returns a PartialViewResult containing the login-form.
public PartialViewResult LoginForm()
{
return PartialView();
}
Today I made a change to this action method and attributed it with the HttpGetAttribute like so:
[HttpGet]
public PartialViewResult LoginForm()
{
return PartialView();
}
This is what caused problems. However, the problems only existed in one particular scenario - and this is what baffles me. When posting a form to a controller everything would work just fine provided that the controller action then returned a RedirectToRouteResult. If the action just returned a ViewResult (to its default view), my Http404 error handling would kick in and loop forever.
I have implemented 404 error handling in a manner very similar to what is described in the third answer to this question: Requirements for 404. If you don't want to read that post, in simple terms I override the HandleUnknownAction method on my base controller class, and in that method I instantiate an instance of my ErrorController class and call Execute on it, passing it an instance of RouteData:
protected override void HandleUnknownAction(string actionName)
{
// If controller is ErrorController dont 'nest' exceptions
if (this.GetType() != typeof(ErrorController))
this.InvokeHttp404(HttpContext);
}
public ActionResult InvokeHttp404(HttpContextBase httpContext)
{
IController errorController = DependencyResolver.Current.GetService<ErrorController>();
var errorRoute = new RouteData();
errorRoute.Values.Add("controller", "Error");
errorRoute.Values.Add("action", "Http404");
errorRoute.Values.Add("url", httpContext.Request.Url.OriginalString);
errorController.Execute(new RequestContext(httpContext, errorRoute));
return new EmptyResult();
}
All the ErrorController does is log the error and return a view with a friendly error message. Well, that's how it should work. But in this case the error handling would enter into an infinite loop where the AccountController (to which my form was posted) would invoke the HandleUnknownAction over and over and over again.
There was nothing in the error logs to indicate what had gone wrong (I think I log just about everything) - which was also strange. So I figured that if removed the HandleUnknownAction method from my controller base class maybe something else would be revealed. And it was:
2010-12-10 19:11:47,956 [4] ERROR Infrastructure.Log4NetAuditor [System.Web.HttpException (0x80004005): Error executing child request for handler 'System.Web.Mvc.HttpHandlerUtil+ServerExecuteHttpHandlerAsyncWrapper'. ---> System.Web.HttpException (0x80004005): Execution of the child request failed. Please examine the InnerException for more information. ---> System.Web.HttpException (0x80004005): A public action method 'LoginForm' was not found on controller 'Cdo.Web.Controllers.AccountController'.
What the? When I saw this I remembered that I'd put the HttpGetAttribute on this method - so I promptly removed it... and order was restored. I am happy to have discovered what caused this - but I remain in the dark on why it happened. If you are able to help me shed some light on this I'd be much obliged. Why would the HttpGetAttribute make a difference here?
try setting outputcache attribute to action. I remember that kind of problem and this was a solution. set duration on 1
[OutputCache(Duration = 1, VaryByParam = "None")]