DotnetCore : OnException method in a custom filter is called two times - exception

I am using dotnet core and have created a custom exception filter to handle exceptions. The problem i face is that in case of exceptions , the onException method in the custom filter is called two times. Below is the code :
public class CustomExceptionFilter : ExceptionFilterAttribute
{
public override void OnException(ExceptionContext context)
{
// Code
base.OnException(context);
}
}
Controller Code is :
[CustomExceptionFilter]
public class MyController : Controller
{
// Raise an exception in any apis
}
Why onException is called two times?

Using Visual Studio I created a new Asp.Net Core Web Application and used the standard Web Application Template. Then I added the CustomExceptionFilter class and added the [CustomExceptionFilter] attribute to the HomeController and threw and exception inside it's Index method:
[CustomExceptionFilter]
public class HomeController : Controller
{
public IActionResult Index()
{
throw new Exception("Time to bail!");
return View();
}
}
Finaly, I set a breakpoint on this line in the CustomExceptionFilter:
base.OnException(context);
And ran the website. The debugger stops on the throw of course, and then it stops on the line with the breakpoint. The breakpoint is only hit once. So my setup verifies the expected behavior.
Troubleshooting
In the past, I have ran into similar situations where something that should only be called once is called twice and it's almost always turned out to be because a second http request came in that I wasn't expecting. So it really was only being called once per http request. One way to check on that is to look at the path and query in the method which you can do as indicated below:
public class CustomExceptionFilter : ExceptionFilterAttribute {
public override void OnException(ExceptionContext context) {
//set breakpoing on the following line to see what the requested path and query is
string pathAndQuery = context.HttpContext.Request.Path + context.HttpContext.Request.QueryString;
// Code
base.OnException(context);
}
}

Another scenario that can cause this is adding the attribute in two places:
I had this:
config.Filters.Add( new StandardExceptionHandlingAttribute() );
AND this:
[StandardExceptionHandling]
public async Task<int?> ....

Related

Testing class which creates objects from other classes

I have a class Component which creates two objects from other classes JMSConnector and AppiaConnector and links both of them.
I have a method that reads the status of both objects and return a combined value.
Here is the code:
Problem I am facing when testing this method is I have no way of injecting mocks of appiaConnector and jmsConnector to test the behaviour of this method.
For example I tried this:
#RunWith(MockitoJUnitRunner.class)
public class ComponentTest {
#Mock
JMSConnector jmsConnector;
#Mock
AppiaConnector appiaConnector;
Component component = new Component();
#Test
public void testGetStatus() {
given(jmsConnector.getStatus()).willReturn(true);
given(appiaConnector.getStatus()).willReturn(true);
// this is what I want... but I can't dynamically inject these mocks into component ???
assertTrue(component.getStatus());
}
}
Is there a way that I can achieve this, or should I use stubs? (which seems an overkill for such a small method)
You can pass them as parameters instead of creating them inside the method.
public Component(AppiaConnector appiaConnector, JMSConnector jmsConnector) {
// do your status check
}
Now if in your production code, you don't want to inject them, you can always create another constructor with no parameters. That way you keep your code the same but gain in testing flexibility
public Component() {
this(new AppiaConnector(), new JMSConnector());
}
Component(AppiaConnector appiaConnector, JMSConnector jmsConnector) {
// do your status check
}

ASP .Net Core Razor: Can't return ViewComponent from my PageModel

I am trying to use Ajax to call a handler in my Razor page that returns the result of a ViewComponent, however when I try the code below, it says:
Non-invocable member "ViewComponent" cannot be used like a method.
public IActionResult OnGetPriceist()
{
return ViewComponent("PriceList", new { id= 5 });
}
When using MVC, the Controller base class includes a ViewComponent method, which is just a helper method that creates a ViewComponentResult for you. This method does not yet exist in the Razor Pages world, where instead you use PageModel as the base class.
One option to work around this is to create an extension method on the PageModel class, that would look something like this:
public static class PageModelExtensions
{
public static ViewComponentResult ViewComponent(this PageModel pageModel, string componentName, object arguments)
{
return new ViewComponentResult
{
ViewComponentName = componentName,
Arguments = arguments,
ViewData = pageModel.ViewData,
TempData = pageModel.TempData
};
}
}
Apart from it being an extension method, the code above is just ripped out of Controller. In order to use it, you can call it from your existing OnGetPriceList (typo fixed) method, like this:
public IActionResult OnGetPriceList()
{
return this.ViewComponent("PriceList", new { id = 5 });
}
The key to making it work here is to use this, which will resolve it to the extension method, rather than trying to invoke the constructor as a method.
If you're only going to use this once, you could forego the extension method and just embed the code itself inside of your handler. That's entirely up to you - some people might prefer the extension method for the whole separation-of-concerns argument.

GET and parameterless GET causing AmbiguousActionException?

I'm trying to have two Web API methods in my controller. One for when GET is called with a MyViewModel object in the header, and one without.
MyController.cs:
[Produces("application/json")]
[Route("api/[controller]")]
public class MyController : Controller
{
[HttpGet]
public IEnumerable<UserModel> Get()
{
// ...
}
[HttpGet]
public IEnumerable<UserModel> Get(MyViewModel viewModel)
{
// ...
}
}
But browsing to the route address in Chrome without passing any MyViewModel gives me this error:
AmbiguousActionException: Multiple actions matched. The following
actions matched route data and had all constraints satisfied:
MyController.Get (MyProject)
MyController.Get (MyProject)
If I comment out the parameterless method and put a break point in the parameterized function and browse to the api URL, it looks like rather than the viewModel being null like I expected, it appears to be a new MyViewModel object made with a parameterless constructor. Seems like it may be relevant to my problem.
I'm running on Microsoft.AspNetCore v1.1.2 and Microsoft.AspNetCore.Mvc v1.1.3.
Add attribute routing to one of them.
For example:
[HttpGet("/myaction")]
public IEnumerable<UserModel> Get(MyViewModel viewModel)
{
// ...
}
Or add it to all of them. MVC can't distinguish two methods because viewModel can be null, and doesn't know if it should match first get action or another.
One for when GET is called with a MyViewModel object in the header, and one without.
Model Binding in ASP.NET Core by default uses query parameters as the source for model population, not headers. If you need to fill MyViewModel from the header, use [FromHeader] attribute:
public IEnumerable<UserModel> Get([FromHeader] MyViewModel viewModel)
ASP.NET Core routing implementation is not using headers for routing resolving. As you are using attribute routing, as #Vlado said, you need to use different Route Name for disambiguating actions.

Is it possible to bind hiding/showing a UIAlertController in Mvvmcross?

I have a command which interacts with an API. If the command doesn't return a desired result it sets a property of the ViewModel called Error.
I want to bind Error to a UIAlertController in my View and have it display when the error occurs.
Here's roughly what I have (although obviously the visibility converter isn't the way to go). I should add that I'm aware PresentViewController should be used to display the UIAlertController.
UIAlertController myAlert = UIAlertController.Create ("", Error.Text, UIAlertControllerStyle.Alert);
set.Bind(myAlert).For("Visibility").To((myViewModel vm) => vm.Error).WithConversion("Visibility");
Check out Observer design pattern.
The way I prefer to achieve that is simple:
Create class which inherits from MvxMessage - let say ShowAlertDialogMessage with properties like title, content and so on.
Create abstract MessageObserver where TMessage : MvxMessage class, ex.:
public interface IMessageObserver
{
void Subscribe(IMvxMessenger messenger);
void Unsubscribe();
}
public abstract class MessageObserver<TMessage> : IMessageObserver where TMessage : MvxMessage
{
public void Subscribe(IMvxMessenger messenger) {
messenger.SubscribeOnMainThread<TMessage>(OnMessageDelivered);
}
public abstract void OnMessageDelivered(TMessage message);
}
Create MessageObserverController
public class MessageObserverController {
public void SubscribeObserver(IMessageObserver msgObserver) {
msgObserver.Subscribe(messenger);
}
.. unsubscribe, dispose and so on goes here
}
Implement ShowAlertDialogMessageObserver class (inherit from MessageObserver<ShowAlertDialogMessage>() which shows UIAlertViewController with data from ShowAlertDialogMessage (title, content and so on). Pass root UIViewController as constructor if needed (you will register MessageObservers in your viewcontrollers anyway - so that's not a problem).
Use MessageObserverController in your ViewControllers (preferably create base view controller to simplify things).
VoilĂ  - you get reusable UI logic, which you can raise by publishing message in your PCL ViewModel (without creating any platform-specific coupling!).

How can I wrap a JSON response in Spring

Suppose I have two sets of controllers in Spring:
/jsonapi1/*
/jsonapi2/*
both of which return objects that are to be interpretted as JSON text.
I'd like some kind of filter to wrap the responses from one set of these controllers so that:
the original response is contained within another object.
For example, if /jsonapi1/count returns:
{"num_humans":123, "num_androids":456}
then the response should be wrapped and returned as follows:
{ "status":0,
"content":{"num_humans":123, "num_androids":456}
}
if an exception happens in the controller, then filter should catch the exception and report it as follows
{ "status":5,
"content":"Something terrible happened"
}
The responses from the other controllers are returned unchanged.
We're currently customizing a MappingJackson2HttpMessageConverter passed to WebMvcConfigurerAdapter.configureMessageConverters in order to perform the above tasks. Works great except that it doesn't seem possible for this approach to be selective about the URLs (or controller classes) it applies to.
Is it possible to apply these kinds of wrappers to individual controller classes or URLs?
Update: Servlet filters look like a solution. Is it possible chose which filter gets applied to which controller methods, or which URLs?
I was struggling on this for multiple days. The solution by #Misha didn't work for me. I was able to finally get this working using ControllerAdvice and ResponseBodyAdvice.
ResponseBodyAdvice allows to inject custom transformation logic on the response returned by a controller but before it is converted to HttpResponse and committed.
This is how my controller method looks:
#RequestMapping("/global/hallOfFame")
public List<HallOfFame> getAllHallOfFame() {
return hallOfFameService.getAllHallOfFame();
}
Now i wanted to add some standard fields around the response like devmessage and usermessage. That logic goes into the ResponseAdvice:
#ControllerAdvice
public class TLResponseAdvice implements ResponseBodyAdvice<Object> {
#Override
public boolean supports(MethodParameter returnType, Class<? extends HttpMessageConverter<?>> converterType) {
return true;
}
#Override
public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType,
Class<? extends HttpMessageConverter<?>> selectedConverterType, ServerHttpRequest request,
ServerHttpResponse response) {
// TODO Auto-generated method stub
final RestResponse<Object> output = new RestResponse<>();
output.setData(body);
output.setDevMessage("ResponseAdviceDevMessage");
output.setHttpcode(200);
output.setStatus("Success");
output.setUserMessage("ResponseAdviceUserMessage");
return output;
}
}
The entity classes look like this:
#Setter // All lombok annotations
#Getter
#ToString
public class RestResponse<T> {
private String status;
private int httpcode;
private String devMessage;
private String userMessage;
private T data;
}
#Entity
#Data // Lombok
public class HallOfFame {
#Id
private String id;
private String name;
}
To handle exceptions, simply create another ControllerAdvice with ExceptionHandler. Use the example in this link.
Advantages of this solution:
It keeps your controllers clean. You can support any return type from your controller methods.
Your controller return type class does not need to extend some base class as required by the AOP approach.
You do not need to hack your way through Spring filters by using HttpServletResponseWrappers. They come up with a performance penalty.
EDIT - 17th September 2019
To handle exceptions use #ExceptionHandler. Refer code below.
#ExceptionHandler(Exception.class)
#ResponseBody
public MyResponseEntity<Object> handleControllerException(HttpServletRequest request, Throwable ex) {
// default value
int httpCode = HttpStatus.INTERNAL_SERVER_ERROR.value();
if(ex instanceof ResourceNotFoundException) {
httpCode = HttpStatus.NOT_FOUND.value();
}
...
}
The way I understand your question, you have exactly three choices.
Option #1
Manually wrap your objects in simple SuccessResponse, ErrorResponse, SomethingSortOfWrongResponse, etc. objects that have the fields you require. At this point, you have per-request flexibility, changing the fields on one of the response wrappers is trivial, and the only true drawback is code repetition if many of the controller's request methods can and should be grouped together.
Option #2
As you mentioned, and filter could be designed to do the dirty work, but be wary that Spring filters will NOT give you access to request or response data. Here's an example of what it might look like:
#Component
public class ResponseWrappingFilter extends GenericFilterBean {
#Override
public void doFilter(
ServletRequest request,
ServletResponse response,
FilterChain chain) {
// Perform the rest of the chain, populating the response.
chain.doFilter(request, response);
// No way to read the body from the response here. getBody() doesn't exist.
response.setBody(new ResponseWrapper(response.getStatus(), response.getBody());
}
}
If you find a way to set the body in that filter, then yes, you could easily wrap it up. Otherwise, this option is a dead end.
Option #3
A-ha. So you got this far. Code duplication is not an option, but you insist on wrapping responses from your controller methods. I'd like to introduce the true solution - aspect-oriented programming (AOP), which Spring supports fondly.
If you're not familiar with AOP, the premise is as follows: you define an expression that matches (like a regular expression matches) points in the code. These points are called join points, while the expressions that match them are called pointcuts. You can then opt to execute additional, arbitrary code, called advice, when any pointcut or combination of pointcuts are matched. An object that defines pointcuts and advice is called an aspect.
It's great for expressing yourself more fluently in Java. The only drawback is weaker static type checking. Without further ado, here's your response-wrapping in aspect-oriented programming:
#Aspect
#Component
public class ResponseWrappingAspect {
#Pointcut("within(#org.springframework.stereotype.Controller *)")
public void anyControllerPointcut() {}
#Pointcut("execution(* *(..))")
public void anyMethodPointcut() {}
#AfterReturning(
value = "anyControllerPointcut() && anyMethodPointcut()",
returning = "response")
public Object wrapResponse(Object response) {
// Do whatever logic needs to be done to wrap it correctly.
return new ResponseWrapper(response);
}
#AfterThrowing(
value = "anyControllerPointcut() && anyMethodPointcut()",
throwing = "cause")
public Object wrapException(Exception cause) {
// Do whatever logic needs to be done to wrap it correctly.
return new ErrorResponseWrapper(cause);
}
}
The final result will be the non-repeating response wrapping that you seek. If you only want some or one controller receive this effect, then update the pointcut to match methods only within instances of that controller (rather than any class holding the #Controller annotation).
You'll need to include some AOP dependencies, add the AOP-enabling annotation in a configuration class, and make sure something component-scans the package this class is in.
Simplest way i manage custom responses from controllers is by utilising the Map variable.
so your code ends up looking like:
public #ResponseBody Map controllerName(...) {
Map mapA = new HashMap();
mapA.put("status", "5");
mapA.put("content", "something went south");
return mapA;
}
beauty of is is that you can configure it any thousand ways.
Currently i use for object transmition, custom exception handling and data reporting, too easy.
Hope this helps
I am also using AOP with #Around. Developed a custom annotation and using that for point cut. I am using a global Response. It has the status, Message and data which is of type List of type
List <? extends parent> dataList
( which can solve your class cast exception). All the entities extends this Parent class. This way I can set all the data into my List.
Also I am using the message key as param with the custom annotation and setting it in action.
Hope this helps.