I have a simple ApiController
that I am trying to catch and return an error. This was for a quick OnExceptionAspect
demo but I ran into a snag: I can't figure out how to return BadRequest
as the args.ReturnValue
. I thought it would be simpler than this. This is my first time using PostSharp in a very long time and certainly the first time while using ASP.Net Core.
Note: I have a bad connection string on the context to force a quick error (not shown).
ParentController
[HttpGet("Get/{studentId}")]
[ActionResultExceptionAspect(StatusCode = HttpStatusCode.BadRequest)]
public ActionResult<IEnumerable<ParentModel>> RetrieveParents(string studentId)
{
var query = Context.ParentViews
.Where(x => x.StudentID == studentId)
.Select(s => EntityMapper.MapFromEntity(s));
return query.ToArray();
}
ActionResultExceptionAspect
public override void OnException(MethodExecutionArgs args)
{
args.FlowBehavior = FlowBehavior.Return;
args.ReturnValue = ((StudentControllerBase)args.Instance).BadRequest();
}
I get an error of:
System.InvalidCastException: Unable to cast object of type 'Microsoft.AspNetCore.Mvc.BadRequestResult' to type 'Microsoft.AspNetCore.Mvc.ActionResult`1[System.Collections.Generic.IEnumerable`1[Student.Models.ParentModel]]'.
The problem seems to be an instance based issue. I see a lot of solutions that seem overly complicated for what I needed so I went with the simplest way to resolve this until I can find something better. I have seen this as an issue specific for ActionResult<T>
return types whenever generated outside the instance. This seems simple with generics for purposes of unit tests but since this is runtime and hard to resolve an unknown return type I went with Activator.CreateInstance
My new OnException
method is:
public override void OnException(MethodExecutionArgs args)
{
var methType = ((MethodInfo)args.Method).ReturnType;
args.ReturnValue = Activator.CreateInstance(methType, ((ControllerBase)args.Instance).BadRequest());
args.FlowBehavior = FlowBehavior.Return;
}
I am by no means sure this is the right way to do it, but it works for this instance.