Customize Authorization Rules Messages.

Customize Authorization Rules Messages.

Old forum URL: forums.lhotka.net/forums/t/10773.aspx


omarcusido posted on Friday, October 14, 2011

Hello all. I'm using Authorization Rules in my Business Objects but when any Authorization Rule is broken the message provided on the exception do not fits my needs. I was reviewing the implementation of the DataPortal class and CSLA throws a Security Exception and loads the exception message from a resource. I really wanted to know if there's a way to change that message to a customized dynamically created message without modify my DataPortal class, I also can't write directly in the resource file because the message is not always the same.

 

Regards.

 

OCP.

StefanCop replied on Friday, October 14, 2011

Hi

As far as I know: no.  The EditObject action would be possible by overriding BusinessBase Save() Method or somthing in this area.

If I got the idea from the ebook ("Creating Business Objects") right, receiving a Security Exception for a broken authorization rule should be an "exception".

It's the UI's responsibility to check if its allowed before doing it: 

Also have a look at Csla.Xaml.ViewModelBase, which provides the Can.... Properties.

Here's a post which suggests to use validation rules in some cases rather than authorization rules.
http://forums.lhotka.net/forums/p/5760/28042.aspx

 

JonnyBee replied on Saturday, October 15, 2011

Hi,

CSLA does not provide a direct method for replacing the error message with your own.But you can add the checks in your own code and throw your own exception.

For the DataPortal you will have to implement the authorization check in you own static factory methods, ex:

    public static Root NewEditableRoot()
    {
      if (!Csla.Rules.BusinessRules.HasPermission(AuthorizationActions.CreateObject, typeof(Root)))
          throw new SecurityException("my custom message");
      
      return DataPortal.Create<Root>();
    }

For Save I would recommend that you create your own intermediate base class for ex BusinessBase and override the Save method and you could even promote the message to a property or lambda expression (marked as nonserializable) to allow to just set the message for each object.

  [Serializable]
  public class MyBusinessBase<T> : Csla.BusinessBase<T> where T:MyBusinessBase<T>
  {
    public override T Save()
    {
      T result;
      if (this.IsChild)
        throw new InvalidOperationException(Csla.Properties.Resources.NoSaveChildException);
      if (EditLevel > 0)
        throw new InvalidOperationException(Csla.Properties.Resources.NoSaveEditingException);
      if (!IsValid && !IsDeleted)
        throw new Csla.Rules.ValidationException(Csla.Properties.Resources.NoSaveInvalidException);
      if (IsBusy)
        throw new InvalidOperationException(Csla.Properties.Resources.BusyObjectsMayNotBeSaved);
      if (IsDirty)
      {
        // this is the same check that DataPortal does for object of type BusinessBase
        if (this.IsDeleted)
        {
          if (!Csla.Rules.BusinessRules.HasPermission(Csla.Rules.AuthorizationActions.DeleteObject, this))
            throw new System.Security.SecurityException("custom message - not allowed to delete");
        }
        else
        {
          if (!Csla.Rules.BusinessRules.HasPermission(Csla.Rules.AuthorizationActions.EditObject, this))
            throw new System.Security.SecurityException("custom message - not allowed to save");
        }
        result = (T) DataPortal.Update(this);
      }
      else
        result = (T)this;
      OnSaved(result, nullnull);
      return result;
    }
  }

 

StefanCop replied on Saturday, October 15, 2011

Jonny,

good, clean sample of what I meant to say....

thx

omarcusido replied on Monday, October 17, 2011

Thats works for me. Thanks a lot guys.

Copyright (c) Marimer LLC