I have an ASP.NET MVC 2 application in which I am creating a custom action filter. This filter sits on the controllers in the application and verifies from the database whether that function is currently available.
Public Overrides Sub OnActionExecuting(ByVal filterContext As System.Web.Mvc.ActionExecutingContext)
Try
' Check controller name against database.
Dim controllerName = filterContext.Controller.GetType().Name
controllerName = controllerName.Remove(controllerName.Length - 10)
' Look up availability.
Dim available As Boolean = _coreService.GetControllerAvailability(controllerName)
If Not available Then
' Redirect to unavailable notice.
filterContext.Result = New RedirectResult("/Home/Unavailable/")
End If
Catch ex As Exception
_eventLogger.LogWarning(ex, EventLogEntryType.Error)
Throw
End Try
End Sub
My problem is that depending on the action that has been requested I need to redirect the user to an action that returns either a view, partial views or JSON.
Given the ActionExecutingContext can I find out what the return type of the originally requested action is?
EDIT:
Ok, I'm getting closer but have another problem.
Public Overrides Sub OnActionExecuting(ByVal filterContext As System.Web.Mvc.ActionExecutingContext)
Try
' Check controller name against database.
Dim controllerName = filterContext.Controller.GetType().Name
Dim shortName = controllerName.Remove(controllerName.Length - 10)
' Look up availability.
Dim available As Boolean = _coreService.GetControllerAvailability(shortName)
If Not available Then
' find out what type is expected to be returned
Dim actionName As String = filterContext.ActionDescriptor.ActionName
Dim controllerType = Type.GetType("Attenda.Stargate.Web." & controllerName)
Dim actionMethodInfo = controllerType.GetMethod(actionName)
Dim actionReturnType = actionMethodInfo.ReturnType.Name
Select Case actionReturnType
Case "PartialViewResult"
filterContext.Result = New RedirectResult("/Home/UnavailablePartial/")
Case "JsonResult"
filterContext.Result = New RedirectResult("/Home/UnavailableJson/")
Case Else
filterContext.Result = New RedirectResult("/Home/Unavailable/")
End Select
End If
Catch ex As Exception
_eventLogger.LogWarning(ex, EventLogEntryType.Error)
Throw
End Try
End Sub
I can use reflection to find the return type of the action method. My problem is if I have the following methods on a controller:
Public Function Create() As ViewResult
Return View()
End Function
<AcceptVerbs(HttpVerbs.Post)>
Public Function Create(values as FormCollection) As ViewResult
' Do stuff here
End Function
I get an AmbiguousMatchException thrown.
With the information I have in the OnActionExecuting method, is there anyway of being more precise with determining the overload that is being called?
I created an AuthenticationFilterAttribute based on this which returns different results based on type:
By the time
OnActionExecuting
is invoked, the action method has not been executed yet, so there's no way you know whether that action method is going to return which subclass ofActionResult
. So, unless you can go with CIL analysis implementation (which I think can get ugly very quickly), I don't think what you want to do is possible.That said, isn't the fact that you redirect users to a view when the controller isn't available enough? I mean, I don't understand why you want to redirect users to a JSON result or a partial view.
Ok, this is the solution I have come up with.
If the Type.GetMethod(string) call fails to identify the method requested, I fetch the parameters collection from the ActionExecutingContext.ActionParameters collection and build an array of the types of the parameters passed in the request. I can then use the Type.GetMethod(string,type()) overload to be more specific about my request.