I have some issues with getting the RescueAttribute in Caliburn 1.1.0 to work. Basically I intend to put a general catch-all exception handler in every view model, but I it seems like the method never gets called.
[PerRequest("ConfigurationGroupViewModel")]
[Rescue("GeneralRescue")]
public class ConfigurationGroupViewModel : Presenter
{
................
public void GeneralRescue(Exception ex)
{
MessageBox.Show(ex.Message);
}
}
I have followed exactly what was specified in the Caliburn documentation, and I saw a post earlier that mentioned something about IConventionManager but my concern is that even by putting the rescue method directly on the ViewModel class itself the rescue method never gets called. Can anyone assist me in this?
Thanks!
Could you please provide some other details?
Are you invoking action with messaging infrastructure or manually? (Rescue only works in the first case)
Are you calling a regular action or a coroutine (IEnumerable)?
Related
Grails makes it very easy for a Controller to call into a Service and for a Controller to forward a request onto another Controller.
So suppose you have a service method as such
List<String> updateNames() {
...
}
You can call it very easily from any controller.
I am wondering, say if you have an edge case where you realise there is a validation problem in your service method. You don't want to throw an Exception back to your controller, because it is not really an exceptional case. But you can't return back an error message from your Service to the Controller that called because that will mean you have to use some wrapper object instead of a nice List
Is there anyway for these cases, you can get the Service to do a server side forward onto another Controller which could return an Error response to user?
Thanks.
Grails already have a structure for validation in your beans, called Errors (comming form Spring). For example, if you have a service to upload files, you could easily attach validation errors in your bean:
class UploadService {
void doUpload(MultipartFile file, MyDomainClass domainClassInstance) {
if(validationsFail) {
domainClassInstance.errors.rejectValue("myUploadField","my.i18n.code")
}
}
}
If it's not a domain class, you can consider using a command object since they're validateable too.
In your controller, it's just a metter of checking if your instance has errors:
def upload() {
MyDomainClass instance = ...
uploadService.doUpload(request.getFile('file'), instance)
if(!instance.hasErrors()) {
//save and go on...
}
}
Another option is to work with exceptions like #Joshua Moore answered. Just remember to extend RuntimeException. If you don't, your transaction will not be rolledback automatically.
Services are not aware of the web/http request context in this way. I won't get into how this line is blurred with session or request scoped services since it still doesn't apply to what you are asking about. Plus, you really don't want your service to even be aware that it's dealing with a web/http request, since you want to separate responsibilities and have a good/clean design.
So, back to your question. This is exactly the case for raising an exception from your service and letting your controller handle the result of that exception. If it's a validation error on an instance then you should be able to access the errors collection of the instance in your controller (provided of course that it was an input into your service).
As a side note about exceptions from services. Stack traces are expensive to fill in. This is even more so in Grails since there are a lot of pieces at work. I highly recommend if you are going to raise your own business logic exceptions from your services that you override the fillInStackTrace method on your exception to avoid this cost.
Here is an example:
package com.example
class MyBusinessException extends RuntimeException {
List<String> argList = []
public MyBusinessException (String message, List<String> args){
super(message)
argList = args
}
public MyBusinessException (String message){
super(message)
}
/**
* Don't fill in the stack trace because we want things to be faster.
**/
#Override
public Throwable fillInStackTrace() {
// do nothing
return this
}
}
I have created a base api controller that allows me to access data from the header.
public virtual int GetHeaderData()
{
if (Request != null)
{
var headers = Request.Headers;
int customValue;
if (headers.Contains("mycustomvalue"))
{
int.TryParse(headers.GetValues("mycustomvalue").First(), out customValue);
return customValue;
}
}
throw new Exception();
}
So calling this is pretty easy from any controller e.g. GetHeaderData()
However, to me this seems very difficult to unit test as the helper requires
Request.Headers
Should I really be trying to read the header value at the controller level or should I be doing it somewhere else that will make this easier to test?
I am looking for a little advise on the best way I should be doing the above.
Thank you
I wouldn't go so far to call this an advice but just a suggestion for you to consider. First of all, unit testing should not determine your class design. It is possible to set the request object at controller level so that Request.Headers return the headers correctly for you to unit test. However, if I ask myself the question do this method belong in the controller, the answer is no, regardless of the desire to unit test or not. If I were to do this, I would much rather create an extension method for HttpRequestMessage. Extension method is just syntactic sugar but it is fundamentally a static helper method and I can use the extension method anywhere - controller, message handler, filter and so on. And then, I can unit test if I want.
Is there a way to handle 404 (resource not found) generically, or do I have to write logic for each action? A simple example of what I am currently doing:
//single-read
public HttpResponseMessage Get(Guid guid)
{
School school = new School(guid);
if (school == null)
{
return Request.CreateResponse(HttpStatusCode.NotFound);
//bonus-question: would it be better to instead: throw new HttpResponseException(HttpStatusCode.NotFound);
}
//bonus-bonus-question: what is the benefit of using a typed response?
return Request.CreateResponse<School>(HttpStatusCode.OK, school);
}
If possible, I would like the "not found" logic to be handled elsewhere so that I didn't need to repeat those few lines of checking for each action. For example, I'd like it if it could be reduced to:
//single-read
public HttpResponseMessage Get(Guid guid)
{
School school = new School(guid);
return Request.CreateResponse<School>(HttpStatusCode.OK, school);
}
You can implement an IActionFilter on your controller which will be called everytime an action is about to be executed and also when an action has finished execution. You can then perform your checking logic there. See documentation. You would annotate the controller class itself with your filter and it would be called for all actions.
In terms of the error handling, if you don't throw an exception, then you won't pay the cost of exceptions (which I'd like to pretend to be negligible), but more importantly, you won't allow any exception handlers to kick in and that may be something you actually want. Take a look at IExceptionFilter for example that gets called whenever an exception is thrown. If there is a part of your application that relies on that (for example logging errors), that component won't know that there was an error when you don't throw an exception, so it's a design call.
I have following controller structure:
abstract class AbstractController {
// ...
}
abstract class AbstractDiagramController extends AbstractController {
// ...
}
class PopulationController extends AbstractDiagramController {
// ...
}
Most controller-actions call various methods of the abstract base classes. If now one of these base-methods needs to send a redirect (or forward) to the client, Grails won't prevent the application from processing the remaining action code of the controller-action anyway.
From my point of view this is an undesirable behaviour, due the base-methods do some kind of validation (like validating parameter, user, session etc), and the controller assumes that the validation succeeded (thence produces subsequent errors).
How can i prevent this insufficient behaviour?
Kind regards,
Christopher
PS: I found already this question, but the answers did not satisfy my needs, because none of them deal with a base controller:
PPS: I am using Grails in version 1.3.7
EDIT
This is a reaction of Victor Sergienko's comments.
Here I give a more detailled code-example of my problem.
// The very base controller
abstract class AbstractController {
// The interceptor gets called before any action of inheritors get processed
def beforeInterceptor = [action:this.&initialize]
// Method validates various stuff
protected initialize() {
if( someThingIsWrong() ) {
// This redirect should stop any other code of inheritors
redirect( controller: "foo", action: "bar" )
return false
}
}
}
// The second base controller
abstract class AbstractDiagramController extends AbstractController {
// This object must get initialized. If not (eg any errors or exceptions occured)
// all inheritors actions are not allowed to do anything
MyObject myGreatObject = null
// Overriden, because of additional individual diagram validation
#Override
protected initialize() {
// Do parents stuff first
super.auth()
// If parent failed, this code should not get executed anymore.
// Yes, here I could check if parent returned false and return false as well before
// continuing the next validation. Anyway I have to do this because grails, comprehendibly,
// will throw an exception if two redirects were executed in a row.
// (With this I just want to visualize the behaviour I'd expect)
if( someThingElseIsWrong() ) {
redirect( controller: "hello", action: "world")
return false
}
// After validation I can initialize the object
myGreatObject = new MyObject()
}
}
// A controller implementation
class MyDiagramController extends AbstractDiagramController {
// Overriden because of inidividual validation
#Override
protected initialize() {
// First do parent stuff
boolean succeeded = super.auth()
// Again, annoying double check
if( !succeeded ) {
return false
}
}
def myAction = {
myGreatObject.SpinAroundAndBeHappy()
}
}
Looks like it was a good idea to reduce the use-case to the minimum lines of code. Now it seem like Victor's suggestions (either canContinue or hasErrors) could solve this unpleasant circumstances somehow, even though it's some kind of workaround.
But somehow I don't like those double-checks. I'm still struggling against the fact, that all layers above the abstract base controller have to react on invalid validations that happened already before (and also should be managed by the base controllers on their own). From my point of view those checks should not be the business of the controller implementations.
PS: I hope no grave mistakes have slipped in the code.
As a workaround, you can return a boolean canContinue from an ancestor action or throw an exception, or check instance.hasErrors() in your case.
EDIT: The fact initialize() is called before an action looks like access control or another complete override of action semantics (before any part of action is executed). Please tell if my assumption is wrong.
When we did a custom security access to different actions, we annotated the actions with own tags like #SecuredDoodah (see #Secured), and added a Filter that completely overrides the action (for us, Filter responds with 403, but it's not necessary).
Filter might be better than beforeInterceptor. If you need to pass some state from Filter, like myGreatObject in the sample, you can inject a Service into Filter and save the state in the Service.
I'm sure there are better ways then my idea, but this should work transparently for Controllers.
You're limited by the fact that this is Java/Groovy and there's no way for a method call to immediately trigger an exit from a method (or Closure). I saw that another framework cheats and when you call render, redirect, etc. it throws an exception that's caught it the framework base class. This acts like a Goto, which doesn't really exist.
It's an expensive approach though - filling in all those stack frames unnecessarily is wasteful since it's not an exception case and the stack will always be ignored.
Unfortunately you need an approach like Victor's where you use boolean return values.
I asked a question earlier today about ActionFilters in ASP.Net MVC. It turned out my problem was really that my ActionFilter is not even running. Among other things I read this article, and I can't find anything he does that I don't.
This is my code:
// The ActionFilter itself
public class TestingIfItWorksAttribute : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
filterContext.Controller.TempData["filter"] = "it worked!";
base.OnActionExecuting(filterContext);
}
}
// The Controller Action with the filter applied
[TestingIfItWorks]
public ActionResult Test()
{
var didit = TempData["filter"];
return View();
}
A breakpoint in the filter method is never hit when I debug, and TempData["filter"] holds a null value when the view is rendered.
Why is this not working?
In case it's helpful to anyone using MVC 4/5:
ActionFilters don't run if you get the namespace of your ActionFilterAttribute or IActionFilter wrong: https://stackoverflow.com/a/13710468/188926
Use System.Web.Http.Filters for Web API, System.Web.Mvc for standard MVC actions.
As in the question, the filter attribute will simply be ignored (no error) if you get it wrong, which makes it difficult to diagnose.
Based on your comments to another answer
When testing via unit tests, the filter is not invoked. If you want to invoke the filter then you'll need mimic the ControllerActionInvoker. It's probably better, to test the filter itself in isolation, then use reflection to ensure that the filter is applied to your action with the correct attributes. I prefer this mechanism over testing the filter and action in combination.
Original
Surely you need an override on your method otherwise you aren't actually replacing the method on the base class. I would have expected the compiler to complain that you needed either a new or override on it. If you don't include the override keyword, it will behave as if you used new. Since the framework invokes it as an ActionFilterAttribute, this means that your method will never get called.
Quoting from MSDN:
If the method in the derived class is
not preceded by new or override
keywords, the compiler will issue a
warning and the method will behave as
if the new keyword were present.
In addition to what tvanofosson said, your action method isn't actually rendering anything to the view. Does your view have a <%=TempData["Filter"].ToString()%> statement or something similar?