Base solution for your next web application
Open Closed

Data Annotation and DTOs #751


User avatar
0
maharatha created

Hi Hilkan -

Thanks again for this amazing framework. Your support has been extraordinary. I am currently working on programatically showing and hiding properties for my DTOs. One approach I was thinking of is using Data Annotations and programatically set the data annotations based on user preference. Some of the values that the user can manipulate for each property are

  1. Visibility
  2. Width
  3. Display Name

I would be storing these values in a json string in my database for each dto at the Tenant level as well as the user level.

I am also planning to create a DTO manager which will have an input as a DTO , and then all the above manipulations would occur and then send the back the modified DTO before sending to the Web layer.

Could you suggest some design ideas on implementing the above ?

Thanks, Partha


7 Answer(s)
  • User Avatar
    0
    maharatha created

    I see you have created the IShouldNormalize interface for Input DTO , won't it be good if you implement similar stuff for normalizing or decorating the output DTO

  • User Avatar
    0
    hikalkan created
    Support Team

    Hi,

    I think the best thing to do for your situation is interception. So, you can intercept calls to application service. After method execution, you can get the DTO and manipulate it via your DtoManager. We use interception for authotization (before method execution) and audit logging (after method execution) for example.

    This class registers the interceptor: <a class="postlink" href="https://github.com/aspnetboilerplate/aspnetboilerplate/blob/master/src/Abp/Authorization/Interceptors/AuthorizationInterceptorRegistrar.cs#L11">https://github.com/aspnetboilerplate/as ... rar.cs#L11</a> (Initialize is called from PreInitialize of the module: <a class="postlink" href="https://github.com/aspnetboilerplate/aspnetboilerplate/blob/master/src/Abp/AbpKernelModule.cs#L46">https://github.com/aspnetboilerplate/as ... ule.cs#L46</a>)

    You can find documents on the web for Castle Windsor interceptors.

  • User Avatar
    0
    maharatha created

    Hi Hikalkan -

    I tried my hand with Intercepting the calls but I am unable to intercept the Async methods. Is there a way I can intercept the result of the Aync methods.

    I see some explanation in the below link :

    <a class="postlink" href="https://gist.github.com/hikalkan/1e5d0f0142484da994e0">https://gist.github.com/hikalkan/1e5d0f0142484da994e0</a>

    But these aren't helpful.

    Could you throw some light into it ? I am kind of stuck.

    Thanks, Partha

  • User Avatar
    0
    hikalkan created
    Support Team

    Hi,

    Could you implement it for non-async methods? Can you share some of your code and describe your problems for better help.

  • User Avatar
    0
    maharatha created
    internal class DTOInterceptors : IInterceptor
        {
            public void Intercept(IInvocation invocation)
            {
                try
                {
                    if (AsyncHelper.IsAsyncMethod(invocation.Method))
                    {
                        PerformASyncDTOOperation(invocation);
                    }
                    else
                    {
                        PerformSyncDTOOperation(invocation);
                    }
                }
                catch (Exception ex)
                {
                    // OnException(invocation, ex);
                }
            }
    
    
           
    
    
            private void PerformSyncDTOOperation(IInvocation invocation)
            {
                var stopwatch = Stopwatch.StartNew();
    
                try
                {
                    invocation.Proceed();
                }
                catch (Exception ex)
                {
    
                    throw;
                }
                finally
                {
                    stopwatch.Stop();
    
                }
            }
            private void PerformASyncDTOOperation(IInvocation invocation)
            {
                var stopwatch = Stopwatch.StartNew();
    
                invocation.Proceed();
    
                if (invocation.Method.ReturnType == typeof(Task))
                {
                    invocation.ReturnValue = InternalAsyncHelper.AwaitTaskWithFinally(
                        (Task)invocation.ReturnValue,
                        exception => SaveAuditInfo(stopwatch, exception)
                        );
                }
                else //Task<TResult>
                {
                    invocation.ReturnValue = InternalAsyncHelper.CallAwaitTaskWithFinallyAndGetResult(
                        invocation.Method.ReturnType.GenericTypeArguments[0],
                        invocation.ReturnValue,
                        exception => SaveAuditInfo(stopwatch, exception)
                        );
                }
            }
    
            private void SaveAuditInfo(Stopwatch stopwatch, Exception exception)
            {
                stopwatch.Stop();
    
    
    
            }
    
        }
    

    I am not doing much anything in the SyncMethods as I don't have the need. But when I try the Asyn Method I get :

    e.g. invocation.ReturnValue = Id = 13743, Status = WaitingForActivation, Method = "{null}", Result = "{Not yet computed}"

  • User Avatar
    0
    hikalkan created
    Support Team

    Hi,

    Your code seems fine at first look. Return value seems also normal. What exception are you getting or what's the problem here? I will create an interception document in a few days (probably today or tomorrow). If you have time, you can wait for it to understand interception better.

  • User Avatar
    0
    maharatha created

    That would be awesome. I can definitely wait.

    The problem is what do I do with the return value when I don't have the actual value in my return value.

    Waiting eagerly for your document.