0

Is there any way this. I want to invoke an action with parameter (or parameterless at least) like below.

My situation is;

Interceptor not contains any reference from MVC, Interceptor is located at ApplicationService layer. This is a service Interceptor.

public class ControllerInterceptor : IInterceptor
    {
        public void Intercept(IInvocation invocation)
        {
            var retVal = (ResponseDTOBase) invocation.ReturnValue;
            if (retVal.ResponseCode == UsrNotAuth)
            {
                //Invoke Controller Action With passsing parameter (retVal)
            }

            invocation.Proceed();
        }
    }

Any ideas ? Thanks.

Oğuzhan Soykan
  • 2,522
  • 2
  • 18
  • 33
  • Can you explain a bit more what are you trying to achieve? I mean what is required. There is real chance that a different design approach exists which better will meet better your requirements. I say this because you try to achieve indirection with interceptors. If you want pure indirection you can make it with typeFactory which invokes the proper controller method after examining the incomming arguments. – Ognyan Dimitrov Apr 04 '15 at 07:38
  • I want to intercept a service call and i'm looking the its `ResponseCode` and the `ResponseCode` is UsrNotAuth then throw an unathorized exception on Mvc layer. If you are throwing an expception at Application service layer it only stay on there. I want to inform Mvc layer for this exception. So I want to clear user session(Http session). So I wrote an action method on Shared Controller and I thought intercept the service call and invoke the controller action here. So How can I handle this other way ? – Oğuzhan Soykan Apr 04 '15 at 20:37

1 Answers1

1

May I offer you another approach for request authorization. MVC is a state machine in its core principle. State machines have actions, triggers and guards. There is already such a 'guard' in MVC for the very purpose of intercepting controller actions and checking for the user privileges. This is the AuthorizeAttribute. This class implements IAuthorizationFilter. Another aspect is that authorization and authentication should happen before they reach your services. What I mean exactly is that there are two types of authorization :

  1. Action Authorization and
  2. Data Authorization.

The first type of authorization you can implement with AuthorizeAttribute or your custom attribute implementation of IAuthorizationFilter + FilterAttribute. Here is an example implementation of such an attribute for a SPA (Single Page Application) that works with ajax requests :

The attribute :

[AttributeUsage( AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false, Inherited = false)]
public class LoggedOrAuthorizedAttribute : AuthorizeAttribute
{
    public override void OnAuthorization(AuthorizationContext filterContext)
    {
        base.OnAuthorization(filterContext);
        CheckIfUserIsAuthenticated(filterContext);
    }

    private void CheckIfUserIsAuthenticated(AuthorizationContext filterContext)
    {
        // If Result is null, we’re OK: the user is authenticated and authorized. 
        if (filterContext.Result == null)
            return;

        // If here, you’re getting an HTTP 401 status code. In particular,
        // filterContext.Result is of HttpUnauthorizedResult type. Check Ajax here. 
        // User is logged in but this operation is not allowed
        if (filterContext.HttpContext.User.Identity.IsAuthenticated && filterContext.HttpContext.Request.IsAjaxRequest())
        {
            //filterContext.HttpContext.Response.StatusCode = 401;
            JsonNetResult jsonNetResult = new JsonNetResult();
            jsonNetResult.Data = JsonUtils.CreateJsonResponse(ResponseMessageType.info, "msgOperationForbiddenYouAreNotInRole");
            filterContext.Result = jsonNetResult;
            //filterContext.HttpContext.Response.End();
        }
    }
}

If you use pure MVC there is an example implementation here. The usage :

In your controller

[LoggedOrAuthorized(Roles = Model.Security.Roles.MyEntity.Create)]
public ActionResult CreateMyEntity(MyEntityDto myEntityDto)
{
...
}

You can apply this on every controller action and block the user even before the controller is reached.

You can supply Loggers and other 'plumbing' through Castle Windsor inside your filters in order to record the events.

A very good and important links and comments are available in this answer of a similar question. These links provide very good guide for proper implementation too.

The other type of authorization - Data Access Authorization can be handled in the service or in the controller. I personally prefer to handle all kinds of authorization as soon as possible in the pipeline.

General practice is not to show to the user any data or action that he is not authorize to view or to execute commands upon it. Of course you have to double check this because the user can modify the POST and GET requests.

You can make simple interface with implementation IDataAccessService and control data access by passing user id and entity id to it.

Important thing is that you should not throw exception when the user is not authorized because this is no exception at all. Exception means that your program is in an unexpected state which prohibits its normal execution. When a user is not authorized this is not something unexpected - it is very well expected. That is why in the example implementation a message is returned rather then exception.

Another subtlety is that "exceptions" are handled differently by the .NET framework and they cost a lot more resources. This means that your site will be very vulnerable to easy DDOS outages or even they can perform not as they can. General rule is that if you control your expected program flow through exceptions you are not doing it properly - redesign is the cure.

I hope this guides you to the right implementation in your scenario.

Please provide the type of the authorization you want to achieve and parameters you have at hand so I can suggest a more specific implementation.

Community
  • 1
  • 1
Ognyan Dimitrov
  • 6,026
  • 1
  • 48
  • 70
  • Very good answer, it sheds light to my thoughts thanks for this but, i have done this implementation already. I mean i used AuthorizationFilter for invoking actions. I'm checking the session and my static User context for Authorization like above. And you are right ,this things should not be done with exceptions. But I make service call in action method and I provide service security with permissions(user permissions) but in my product must be done that same user not be able to online two or more environment(mozilla or chrome). Im checking this mvc side and I want check this service call side. – Oğuzhan Soykan Apr 05 '15 at 14:03
  • Sorry, but I am not able to get it. Can you explain this a bit more? – Ognyan Dimitrov Apr 06 '15 at 06:53